So, you’re now scratching your head and saying, When I can’t access something that I should be able to, how do I know that it’s an SELinux problem? Ah, I’m glad you asked.
Whenever something happens that violates an SELinux rule, it gets logged in the /var/log/audit/audit.log file. Tools are available that can let you directly read that log, but to diagnose SELinux problems it’s way better to use setroubleshoot. The beauty of setroubleshoot is that it takes cryptic, hard-to-interpret SELinux messages from the audit.log file and translates them into plain, natural language. The messages that it sends to the /var/log/messages file even contain suggestions about how to fix the problem. To show how this works, let’s go back to our problem where a file in the /var/www/html directory has been assigned the wrong SELinux type. Of course, we knew right away what the problem was because there was only one file in that directory and a simple ls -Z showed what was wrong with it. However, let’s ignore that for the moment and say that we didn’t know what the problem was. By opening the /var/log/messages file in less and searching for sealert, we’ll find this message:
Nov 26 21:30:21 localhost python: SELinux is preventing httpd from open access on the file /var/www/html/index.html.#012#012***** Plugin restorecon (92.2 confidence) suggests ************************#012#012If you want to fix the label. #012/var/www/html/index.html default label should be httpd_sys_content_t.#012Then you can run restorecon.#012Do#012# /sbin/restorecon -v /var/www/html/index.html#012#012***** Plugin catchall_boolean (7.83 confidence) suggests ******************#012#012If you want to allow httpd to read user content#012Then you must tell SELinux about this by enabling the 'httpd_read_user_content' boolean.#012#012Do#012setsebool -P httpd_read_user_content 1#012#012***** Plugin catchall (1.41 confidence) suggests **************************#012#012If you believe that httpd should be allowed open access on the index.html file by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'httpd' --raw | audit2allow -M my-httpd#012# semodule -i my-httpd.pp#012
The first line of this message tells us what the problem is. It’s saying that SELinux is preventing us from accessing the /var/www/html/index.html file because it’s set with the wrong type. It then gives us several suggestions on how to fix the problem, with the first one being to run the restorecon command, as I’ve already shown you how to do.
So far, I’ve only talked about using setroubleshoot on text-mode servers. After all, it’s very common to see Linux servers running in text-mode, so all of us Linux folk have to be text-mode warriors. But on desktop systems or on servers that have a desktop interface installed, there is a graphical utility that will automatically alert you when setroubleshoot detects a problem:
Click on that alert icon, and you’ll see the following:
Click the Troubleshoot button, and you’ll see a list of suggestions on how to fix the problem:
As is often the case with GUI thingies, this is mostly self-explanatory, so you shouldn’t have any problem figuring it out.
If you’re dealing with a simple problem like the one I’ve just shown you, then you can probably assume that you can safely do what the first suggestion in the setroubleshoot message tells you to do. But there will be times when things get a bit more complex, where you might have more than one problem. For times like these, you need to use permissive mode.
When you first install your Red Hat or CentOS system, SELinux is in enforcing mode, which is the default. This means that SELinux will actually stop actions that are in violation of the active SELinux policy. This also means that, if you have multiple SELinux problems when you try to perform a certain action, SELinux will stop the action from taking place after the first violation occurs. When it happens, SELinux won’t even see the remaining problems, and they won’t show up in the messages log file. If you try to troubleshoot these types of problem while in enforcing mode, you’ll be like the proverbial dog who chases its own tail. You’ll go round and round and will accomplish nothing.
In permissive mode, SELinux allows actions that violate policy to occur, but it will log them. By switching to permissive mode and doing something to induce the problem that you were seeing, the prohibited actions will take place but setroubleshoot will log all of them in the messages file. This way, you’ll get a better view of what you need to do to get things working properly.
First, let’s use getenforce to verify what our current mode is:
[donnie@localhost ~]$ sudo getenforce Enforcing [donnie@localhost ~]$
Now, let’s temporarily place the system into permissive mode:
[donnie@localhost ~]$ sudo setenforce 0 [donnie@localhost ~]$ sudo getenforce Permissive [donnie@localhost ~]$
When I say temporarily, I mean that this will only last until you do a system reboot. After a reboot, you’ll be back in enforcing mode. Also, note that a 0 after setenforce denotes that I’m setting permissive mode. To get back to enforcing mode after you’re done with troubleshooting, replace the 0 with a 1:
[donnie@localhost ~]$ sudo setenforce 1 [donnie@localhost ~]$ sudo getenforce Enforcing [donnie@localhost ~]$
We’re now back in enforcing mode.
At times, you may need to make permissive mode persist after a system reboot. An example of this would be if you ever have to deal with a system that has had SELinux disabled for a long period of time. In a case like that, you wouldn’t want to just put SELinux into enforcing mode and reboot. If you try that, it will take forever for the system to properly create the file and directory labels that make SELinux work, and the system might lock up before it’s done. By placing the system into permissive mode first, you’ll avoid having the system lock up, although it will still take a long time for the relabeling process to complete.
To make permissive mode persistent across system reboots, you’ll edit the selinux file in the /etc/sysconfig directory. Here’s what it looks like by default:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
The two important things you see here are that SELinux is in enforcing mode, and that it’s using the targeted policy. To switch to permissive mode, just change the SELINUX= line, and save the file:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=permissive # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
The sestatus utility shows us lots of cool information about what’s going on with SELinux:
[donnie@localhost ~]$ sudo sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: targeted Current mode: enforcing Mode from config file: permissive Policy MLS status: enabled Policy deny_unknown status: allowed Max kernel policy version: 28 [donnie@localhost ~]$
The two items that interest us here are the current mode and the mode from a configuration file. By changing the configuration file to permissive, we haven’t changed the current running mode. So, we’re still in enforcing mode. The switch to permissive won’t happen until I either reboot this machine or until I manually switch by issuing a sudo setenforce 0 command. And of course, you don’t want to stay in permissive mode forever. As soon as you no longer need permissive mode, change the configuration file back to enforcing and do sudo setenforce 1 to change the running mode.