Part 4: A very brief guide to policy devel

This is a useful procedure. Say you’ve got a program that’s not working properly and can’t easily be fixed by relabeling contexts on the file system. The fix would be to change the policy.

You don’t actually have to re-draft the original policy. Policies are modular and can be loaded to fix specific problems.

Also there’s a useful tool that analyses the audit and suggests a fix to the policy.

What could be easier?

Prerequisite – you need selinux-policy-devel or the equivalent package on whatever distro you’re using. For RH and derivatives its:

$ yum install selinux-policy-devel

(You’ll also need basic dev prerequisites like make etc)

And the process is then dead easy:
1.) switch into permissive mode:

 $ setenforce 0

2.) run the application and do whatever wasn’t allowed previously.

3.) Now we’ll create a policy to fix the problem based on the audit log from step (2).

i.) Create a policy directory, and cd into it e.g.

$ mkdir /etc/selinux/my-policy
$ cd /etc/selinux/my-policy

ii.) Create a template from the audit log using a handy command:

$ audit2allow -l -a > mypolicy.te

(the file name isn’t important but the suffix, .te, is)

iii.) Create a couple of other empty files that are required by the build
process:

$ touch mypolicy.fc, mypolicy.if, mypolicy.pp

(must use the same file name as step (ii))

iv.) Examine the contents of mypolicy.te and turn it into a policy with appropriate require{} and headers, for example this I created for ftpd:

policy_module(mypolicy, 1.0)

require {
    type ftpd_t;
    type user_home_t;
}
 
allow ftpd_t self:capability { dac_read_search kill dac_override };
allow ftpd_t user_home_t:dir { read getattr search };
allow ftpd_t user_home_t:file { read lock getattr }; 

(The last 3 lines are output from audit2allow, stripped the audit2allow header, review the lines and remove any uneeded statements, and add a

policy_module header and require{} for types)

– don’t worry at this stage if you feel you may have missed some types out of require{}, as the build process will fail.

v.) Build the policy:

$ make -f /usr/share/selinux/devel/Makefile

vi.) Assuming the build worked and still in permissive mode (setenforce 0, above), install (-i) the policy (pp) file created in the build process:

$ semodule -i mypolicy.pp

vii) Set back into enforcing:

$ setenforce 1

And that’s that, the changes are persistent across reboot, or you can unload the policy at any time using the policy name (mypolicy):

$ semodule -r mypolicy

Also

 
$ semodule -l 

to list the loaded policies,

 
$ semodule -u 

to upgrade, etc etc.