How does the file context get set on a file?
1. By default files created in a directory get the file context of the directory. So if I create a file in my /etc it will by default get a security context of etc_t.
drwxr-xr-x root root system_u:object_r:etc_t /etc -rw-r--r-- root root user_u:object_r:etc_t /etc/dan
2. Policy rules can be loaded in the kernel that specify when a domain creates a file in a directory with context foo_t, it will be created bar_t. These are called file_transition rules. A good example of this is your home dir. There is a rule in the kernel that says all files created by unconfined_t in user_home_dir_t will be created user_home_t.
user_u:system_r:unconfined_t drwxr-xr-x dwalsh dwalsh user_u:object_r:user_home_dir_t /home/devel/dwalsh -rw-rw-r-- dwalsh dwalsh user_u:object_r:user_home_t /home/devel/dwalsh/dan
3. The third way a file context can be assigned is via an SELinux aware application. An example of this is the chcon command (I will talk about chcon and other SELinux Utilities in future blogs) Policy rules still need to be in place for these tools to function properly. So a confined domain, might only have a couple of security contexts that it can relabelfrom/relabelto.
-rw-r--r-- root root user_u:object_r:bin_t /etc/dan
The core utilities that have the ability to manage file context are mv/cp/install.
SELinux awareness are in all three of these tools but sometimes they work in mysterious ways.
The goal when we added SELinux awareness to mv/cp was to maintain the same mechanism as with discretionary control.
The mv command will attempt to maintain the security context of the file when it is moved to a different directory... This causes some confusion, but this works the same was as with discretionary access. If I create a file owned by dwalsh in /tmp and then copy it to /etc, the ownership of the file will still be dwalsh in /etc. Similarly if the file was created in /tmp, it will have a security context of tmp_t, so when it is moved to /etc. It will continue to have tmp_t as it's security context.
The cp command is a little different. If a file exists that you are copying over, the new file will maintain the file context of the previous file. So if I look at /etc/resolv.conf, I will see that it is labeled net_conf_t. If I copy a file over it say /tmp/resolv.conf, labeled tmp_t, onto /etc/resolv.conf, it will still be labeled net_conf_t. If I moved the file /tmp/resolv.conf onto /etc/resolv.conf, it will end up with tmp_t.
Note: If you are running restorecond, it watches for the creation of the /etc/resolv.conf file as well as others and will fix the context if it is wrong. In order to get the results mentioned above you should stop the restorecond service. service restorecond stop.
If the file does not exist it follow the rules defined above, IE it will either get the security context of the directory, or if a file_transition rule exists it will transition the context to follow the rule. So if you remove /etc/resolv.conf and cp /tmp/resolv.conf to /etc, you will end up with a security context of etc_t. Similarly if cp /etc/resolv.conf to ~/ it will end up with a security context of user_home_t. cp has an option to preserve the mode, ownership, and timestamps, but this option does not work with the file_context, you need to use -Z.
So one of the problems we see quite often is a user creates an html file in his home dir or in /tmp and then moves it to /var/www/html. Apache then gets an access denied because apache is not allowed to read user_home_t. The quickest way to clean this up is with the restorecon command. The restorecon command reads the default file_contexts for the installed policy and then resets the file_context of all specified files.
The install command and rpm for that matter both have similar functionality to restorecon. When they create files on disk they check with the installed policy file_context file and set the appropriate file_context.