Ever have that moment where you’re working on your SELinux enabled webserver and you’ve put in a fancy new file into /var/www/html and the darn thing just won’t show up properly, even though everything else is working? Then that sinking realization that you have to deal with three different aspects of troubleshooting permissions - ownership, Unix file permissions and SELinux permissions?

Turns out, as long as you have at least one file around that already has the correct owner, permissions and SELinux contexts you can rapidly clone everything with the --reference flag - a trick that took me way too long to discover.

Syntax

To clone owner and group, use the chown command, like so:

chown file_to_update --reference=correct_file

To clone Unix permissions, use the chmod command, like so:

chmod file_to_update --reference=correct_file

To clone SELinux context, use the chcon command, like so:

chcon file_to_update --reference=correct_file

As you can see, all three use the same syntax, so only the command has to change - this makes it easy to rapidly ensure that all potential permissions have been cloned by entering the command once then updating just the base command, leaving the syntax the same.

Example - Handling Apache Files

In this example, there are two files in /var/www/html/: index.html which was created earlier and has all the right permissions, and new_file.html which was copied in from /root and has some issues as a result. Here’s the output of ls -lZ (the Z flag outputs SELinux context).

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0 0 Apr 15 14:39 index.html
-rwx--x-w-. 1 root   root   unconfined_u:object_r:admin_home_t:s0        0 Apr 15 14:46 new_file.html

As you can see, the permissions on new_file.html are wrong, the owner and group are wrong, and so is the SELinux context. Happily we know that everything is good on index.html, so we’ll run our three commands:

chown new_file.html --reference=index.html

Running ls -lZ now shows that the owner and group are fixed, as we expected.

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0 0 Apr 15 14:39 index.html
-rwx--x-w-. 1 apache apache unconfined_u:object_r:admin_home_t:s0        0 Apr 15 14:46 new_file.html

So far, so good. Let’s run the chmod - we won’t even have to type everything out again, just go back in our terminal history and update the first part of the chown command!

chmod new_file.html --reference=index.html

And now ls -lZ shows us the permissions are corrected, all that’s left is SELinux.

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0 0 Apr 15 14:39 index.html
-rw-r--r--. 1 apache apache unconfined_u:object_r:admin_home_t:s0        0 Apr 15 14:46 new_file.html

Finally, we’ll run the chcon command.

chcon new_file.html --reference=index.html

Sure enough, one last ls -lZ proves that now everything is correct, including the SELinux context.

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0 0 Apr 15 14:39 index.html
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0 0 Apr 15 14:46 new_file.html

Obviously this command isn’t a substitute for knowing how all these different commands work, and what the permissions need to be for different applications - but if you’re replacing or adding some files, it sure is a quick way to get an update in place.