SELinux: it may be the scarecrow for many and a best friend for the few. In these few following posts, I'll try to explain how to handle SELinux if one encounters it as an obstacle, with minimal explanation on historical background. Like for example the fact that it is a creation of the NSA. Yes, that government agency contributed to open source software. And that's it for the historical context.
By now, you are aware that SELinux' role is to deny access to a resource you sent a process to use. And indeed, SELinux provides an extra level of security beyond user-based and access control list prescribed access to system resources.
SELinux operates on the concept of security contexts. Each resource on the system- a file, directory, device, port- has a context label on it. Each process running on the system has such a context label as well. It is at the moment that a process is trying to access a system resource that SELinux jumps into action and decides whether that process is authorized to access the resource or not. If labels of both the process and the resource that is about to be accessed match, then the process will successfully access that resource. If labels don't match, SELinux will deny access but also will produce a denial message and assign it a unique UUID that you can later use to read the denial message and take action- which usually consists of re-labeling the resource with the correct label that will allow the process to access that resource. You probably guessed it, re-labeling a resource requires elevated user privileges.
Let's first see if SELinux itself is turned on while your system is running, and after that we'll see how to check labels of a process, a port and a file (representing every type of resource on a Unix system).
There are three available states in which SELinux may be running. To check on the current state, you don't need elevated privileges. Just issue:
as a regular user at the command line and one of the following three may be returned: Permissive, Enforcing or Disabled.
One of the novelties/oddities of RHEL 9 is that SELinux by default is now running in Permissive mode: SELinux will not deny access to a resource when its label and the label of the process trying to access aren't matching, but will produce an error message and log it into syslog. That default setting was Enforcing on previous versions of RHEL.
Knowing now what Permissive mode does, you can safely guess what Enforcing and Disabled modes do: enforce SELinux policies that prevent access when labels are mismatched and Disabled will completely turn off SELinux- both its ability to restrict access and to log policy violations.
You may be enticed to think that setting SELinux mode to Disabled on the system is an unsafe way to operate that system. It is however best to consult higher-ups in your hierarchy at work or organization-level documentation on that system before rushing to switch to Enforcing mode: certain pieces of hardware, not always legacy, have no concept of access to them regulated beyond user-level. In the past, sysadmins were left with no choice but to disable SELinux to make the non-standard hardware work with the system.
If you are the only one in charge of the system and you felt the need to switch around SELinux modes on a running system (educational purposes or testing if SELInux is denying access to a resource- as a part of the troubleshooting process), as a user with elevated privileges, to switch up the level of enforcement, issue:
or if you need to lower the level of enforcement:
Both modes have their numerical equivalents of 1 for Enforcing or 0 for Permissive. Now, disabling SELinux is done at a different level, at the kernel boot level: either as a kernel boot parameter selinux=0 at boot time (which change will not survive reboot) or adding that option as a permanent kernel boot option.
As is with all subjects Linux, there's a config file that sets the switches for SELinux operation, that file is /etc/selinux/config
To check the label of a specific file, add the -Z option to the ls command:
ls -Z /home/gjorgivarelov/file1
will produce the context label of that file.
Let's say there was a process p1 that tried to access the file file1 and SELinux prevented that but now that you are equipped with some awareness of SELinux being present on your system, you can quickly check the label of the process p1 as well:
ps -Z p1
and check that label against the output of the
ls -Z command on file1.
That was easy, but how about checking the SELinux context label of a port? Let's say you need to check the context label of port 80, very common when setting up a web server. Elevated privileges to the rescue and:
semanage port -l | grep /\<80\>/
Labels of ports, processes and resources aren't unique to each resource or process. Several ports can have the same label and the same goes for processes and files.
SELinux is able to present additional obstacles to processes trying to access resources on the system. Just because labels match doesn't mean that process has unchecked access to the resource. Enter SEBooleans. Once a process is granted access to a resource, SEBooleans present constraints within which the process can use the resource. Many of those Booleans have to do with network access, meaning they (dis)allow network access to a resource. As you may have guessed already, these values can only be on or off. You may have already encountered the need to switch an SELinux Boolean on or off while configuring a port to be used by a web server on a system that has SELinux at Enforcing.
To check if a Boolean is switched on or off:
getsebool -a | grep 'that_boolean'
and see if a required Boolean is on the list and is it turned on or off.
Toggle the Boolean on or off for the current session, for example turning on Boolean se_bool_1:
setsebool se_bool_1 on
of course with elevated privileges. Or to toggle to a new state permanently (survives reboot):
setsebool -P se_bool_1 on
Unlike labels, SE Booleans carry names unique to the action they (dis)allow. For example, to enable access to a non-standard port for the httpd process, part of the procedure might involve switching on SELinux Booleans whose name starts with httpd_. Names of these Booleans are pretty descriptive most of the time.
This concludes the introduction to SELinux, next to present will be the semanage command and how to change labels on a resource, along with the mechanism of inheritance of SELinux labels by resources at different levels of system's hierarchy.