Previous Entry Share Next Entry
Audit2allow should be your third option not the first.
Whenever I talk about SELinux lately, I make everyone stand up and say.

SELinux is a labeling system.
Every process has a label every object on the system has a label.  Files, Directories, network ports ...
The SELinux policy controls how process labels interact with other labels on the system.
The kernel enforces the policy rules.

The follow up to this is, if you get a denial the First thing you should think is, perhaps one of the labels is WRONG.

I wrote a paper  a while ago called the SELinux Four Things. In which I point out the four causes of SELinux denials.

  1. You have a labeling problem.

  2. You have changed a process configuration, and you forgot to tell SELinux about it.

  3. You have a bug in either an application or SELinux policy.  Either SELinux policy did not know an application could do something, or the application is broken.

  4. You have been hacked.

The solution to #3 is to report a bug and use audit2allow to generate a local policy module and install it until either the application is fixed or SELinux policy adds rules to allow it.

The problem i see is that administrators seem to go to this option when ever they see a denial.   Lets look at a recent example from email.

In a recent email on, Richard reported:

I have a CGI application named "mapserv" that needs to write to a specific location: "/rwg/mapserver/tmp"

He figured out that Apache content was usually labeled httpd_sys_content_t, which was a step in the right direction, so I guess he labeled this rectory tree as

Then he asked about writing policy that looked like.

module test 1.0;

require {
        type httpd_sys_content_t;
        type httpd_sys_script_t;
        class dir add_name;
        class file { write create };

#============= httpd_sys_script_t ==============
allow httpd_sys_script_t httpd_sys_content_t:dir add_name;
allow httpd_sys_script_t httpd_sys_content_t:file { write create };

This policy obviously came from audit2allow, and would work, except for a couple of problems, the biggest being that all CGI Scripts would be able to read write all Apache content.  The policy is also fragile since you might get an AVC like httpd_sys_script_t is not allowed to append to httpd_sys_content_t.

manage_files_pattern(httpd_sys_script_t, httpd_sys_content_t, httpd_sys_content_t) Would have been better.

Is there a better label I could have used?

But the main point of this blog would be that Richard should not have used a audit2allow module.  He could have used httpd_sys_rw_content_t for the tmp directory.

# semanage fcontext -a -t httpd_sys_rw_content_t "/rwg/mapserver/tmp(/.*?)"
# restorecon -R -v /rwg/mapserver/tmp

This would have been choice "1" above, one of the labels is wrong.

Could I change the process label?

Dominic Grift pointed out, in a mail reply, another solution.

cat > mywebapp.te << EOF
policy_module(mywebappp, 1.0.0)

make -f /usr/share/selinux/devel/Makefile mywebapp.pp
sudo semodule -i mywebapp

Now you can use the following new types:

httpd_mywebapp_script_t (mywebapp process type)
httpd_mywebapp_script_exec_t (mywebapp cgi executable file type)
httpd_mywebapp_content_t (mywebapp readonly file type)
httpd_mywebapp_content_rw_t (mywebapp read/write file type)
httpd_mywebapp_content_ra_t (mywebapp read/append file type)
httpd_mywebapp_htaccess_t (mywebapp htaccess file types)

Basically you can just label the cgi script with the mywebapp script executable file type and then the mywebapp process will run with the mywebapp process type creating files with the mywebapp content file types.

This solution satisfies "1", changing both the process label and the target label.  This is probably the best solution, since if Richard used other CGI scripts on his machine, only the mapserver cgi script would be able to write the mapserver cgi content, and he would have better separation.

Note:  I would have used sepolicy generate --cgi PATHTO/mapserver.cgi to generate the policy.

Could I modify the SELinux configuration to allow this access?

A third option would be to turn on the httpd_unified boolean.  (This would an option of type "2").  Although not the best solution for the problem.

httpd_unified is described as "Unify HTTPD handling of all content files."

# setsebool -P httpd_unified 1

This means it will allow the apache process and default apache scripts to read/write/execute all default labeled apache content.

Bottom line, when you see an SELinux AVC, the way your decision tree should go something like the following.

  1. Is the process that is being denied running with the correct label?  Could I make it run with a better label?

  2. Does the target object have the correct label or could I assign it a label that would allow the access from the process label?

  3. Is their an SELinux Boolean that would allow the access?

  4. If this is a network port being denied, did I modify the default settings and could I modify the labels on network packets using semanage port.

  5. Do I believe this is a bug in an application?  If yes, I need to report a bug?

  6. Is this a bug in SELinux policy and the access should be allowed by default?  I should install a local modification and report this as a bug.

  7. Am I being hacked?

setroubleshoot attempts to help you walk through this process, and newer versions of audit2allow show you booleans and potential labels you can use.

No HTML allowed in subject


(will be screened)


Log in