SELinux – canonical way of automatically applying a context on file creation

selinux

My current understanding is that you have to manually use restorecon to apply the desired context to a newly created file or directory unless you are happy with the context that it inherits from its parent directory.

I am wondering if it is possible to automatically apply a context on creation based on its path without having to run restorecon.

I googled a bit and found this post by Dan Walsh where he mentions restorecond which uses inotify to change context on creation. He also points out the obvious problem with it (race condition). Is this the only way to automatically solve the issue of re-context-ing in case a child should not inherit its context from the parent directory?

One problem is that restorecond does not seem to handle entries the same way as /etc/selinux/targeted/contexts/files/file_contexts, that is, no regexes and it does not work recursively, so /etc/selinux/restorecond.conf cannot contain something like

/var/www(/.*)?/logs(/.*)?

or

/var/www/*

or even

/var/www/*/logs

Is there a way to work around this problem?

EDIT:

As per @Michael's answer this should work OOTB if a respective rule exists, but it doesn't:

# rm -rf /var/www/foo
# semanage fcontext -a -t httpd_log_t '/var/www/foo/logs'
# grep '/var/www.*logs' /etc/selinux/targeted/contexts/files/file_contexts*
/etc/selinux/targeted/contexts/files/file_contexts:/var/www(/.*)?/logs(/.*)?    system_u:object_r:httpd_log_t:s0
/etc/selinux/targeted/contexts/files/file_contexts.local:/var/www/foo/logs    system_u:object_r:httpd_log_t:s0
# matchpathcon /var/www/foo/logs
/var/www/foo/logs       system_u:object_r:httpd_log_t:s0
# mkdir -p /var/www/foo/logs
# touch /var/www/foo/logs/quux
# ls -alZ /var/www/foo/logs*
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 quux
# restorecon -vR /var/www/foo
restorecon reset /var/www/foo/logs context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_log_t:s0
restorecon reset /var/www/foo/logs/quux context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_log_t:s0

Best Answer

The kernel makes the following procedure to determine what the file type of a newly created file will be.

  • There exists in policy a specific file transition rule. So apply this.
  • Make the newly created file acquire the type of the parent directory.

In the vast majority of cases, new files inherit the parent directories type. Sometimes this is not desirable -- so a policy writer can create rules based off the conditions of who is doing the labelling and where in order to transition to another type.

This is controlled in policy with the type_transition statement, although normally a policy writer will call the filetrans_pattern macro instead.

In the kernel, these decisions are not based on paths but types (although a minor exception exists in newer policies).

A rule typically looks like this;

type_transition httpd_t var_log_t:file httpd_var_log_t;

In this example, the rule states that. If the process/user performing the file creation is httpd_t and the directory the object is being created in is var_log_t and the object is classified as a file, then the new file must be labelled as httpd_var_log_t.

This, of course has a number of limitations, a good example of this is the condition when you create .htaccess files in apache (in /var/www/html). In this example the default policy of creating a file type with the same type as its parent directory applies, but in reality the proper type of this file is httpd_sys_htacess_t not the default of httpd_sys_content_t.

This was a known problem for a number of years and was eventually fixed by allowing policy writers to specify the filename that the transition applies to in policy -- unfortunately this features is not available in EL6.

In your specific case -- as you have mentioned there are some workarounds involving restorecond. Other than this you should ideally split your data up with different types by putting them in separate subdirectories where the subdirectory is an adequately labelled type. If this is still not possible, and restorecond is not possible -- the only solution is a post-fix of running restorecon on the file after its creation.

Even the 'newer' named filetrans has problems because ultimately it does not support globbing or regex, which severely limits its functionality to specifically well-named files (like .htaccess).

As it stands at this moment, there exists no in-kernel mechanism as flexible as restorecon and its regexes to properly label files correctly to that degree.

Related Topic