This isperhaps a weird section to begin with, but disabling SELinux is a commonly requested activity. Some vendors do not support their application running on a platform that has SELinux enabled, as those vendors do not have the expertise to develop SELinux policies for their own applications, or are not able to educate their own support lines to deal with SELinux.
Furthermore, system administrators are generally reluctant to use security controls they do not understand or find too complex to maintain. Luckily, SELinux is becoming a de facto standard technology in several Linux distributions, which is increasing its exposure and understanding among administrators. SELinux is also capable of selectively disabling its access controls for a part of a system rather than requiring us to disable it for a complete system.
Setting the global SELinux state
SELinux supports three major states that it can be in: disabled
, permissive
, and enforcing
. These states are set in the /etc/selinux/config
file, through the SELINUX
variable, as illustrated in the following code snippet:
$ grep ^SELINUX= /etc/selinux/config
SELINUX=enforcing
When the init
system process loads the SELinux policy, the SELinux code checks the state that the administrator has configured. The states are described as follows:
- If the state is
disabled
, then the SELinux code disables further support, booting the system further without activating SELinux. - If the state is
permissive
, then SELinux is active but will not enforce its policy on the system. Instead, SELinux will report any violation against the policy, but will not prevent the action itself. Thisis sometimes calledhost intrusion detectionas it works in reporting-only mode. - If the state is
enforcing
, then SELinux is active and will enforce its policy on the system. Violationsare reported and denied. This is sometimes calledhost intrusion prevention, as it enforces the rules while logging the actions it takes.
We can use the getenforce
command or the sestatus
command to get information about the current state of SELinux, like so:
$ sestatus | grep mode
Current mode: enforcing
$ getenforce
Enforcing
It is also possible to query the/sys/fs/selinux/enforce
pseudo-file to get similar information. If the file returns1
, then SELinux is in enforcing mode. If it returns0
, then it is in permissive mode. The following code snippet shows SELinux in enforcing mode:
$ cat /sys/fs/selinux/enforce
1
When we change the /etc/selinux/config
file, then we need to reboot the system for the changes to take effect. However, if we boot a system without SELinux support (disabled
), re-enabling SELinux support alone will not suffice: the administrator will need to make sure that all files on the system are relabeled (the context of all files needs to be set). Without SELinux support, Linux will create and update files without updating or setting the SELinux labels on those files. When the system is later rebooted with SELinux support, SELinux will not have any knowledge of the context of a file unless the labels are reset.
In many situations, administrators often want to disable SELinux when it starts preventing certain tasks. This is careless to say the least, and here’s why:
- SELinux is a security component—part of the operating system. Disabling SELinux is like disabling a firewall because it is blocking some communication. It might help because it’s a faster way of getting something to work again, but you’re removing measures that were enabled to protect you.
- Just as with a firewall, SELinux is configurable by rules. If an application is prevented from working correctly, we need to update the rules for that application, just as with additional firewall rules that enable a particular network flow.
- In the worst case, when we want to allow every action an application performs unconditionally, we can still leave SELinux on and just run this application in an unrestricted SELinux domain, called apermissivedomain.
Distributions put significant effort in the integration of SELinux within their products, and they have awesome support channels to help you out if all things fail.
Switching to permissive or enforcing mode
Most distribution-provided Linux kernels allow switching between enforcing and permissivemode through a simple administrativecommand. This feature is called theSELinux development modeand is supported by theCONFIG_SECURITY_SELINUX_DEVELOP
kernel configuration parameter. This kernel parameter, if set, also has the Linux kernel boot in permissive mode first, unless a specific boot option (enforcing=1
) is set.
Although we could consider this development mode a risk (all a malicious person would need to do is switch SELinux to permissive mode to disable its access controls), switching the mode requires strong administrative privileges (like theroot
user has), which most application domains don’t have.
The command to switch between permissive mode and enforcing mode is thesetenforce
command. It takes a single argument:0
(permissive) or1
(enforcing). Thepermissive
andenforcing
strings are allowed by the command as well.
The change takes effect immediately. For instance, we can use the following command to switch to permissive mode:
# setenforce 0
The effect of setenforce
is the same as writing the right integer value into the /sys/fs/selinux/enforce
pseudo-file, as illustrated in the following code snippet:
# echo 0 > /sys/fs/selinux/enforce
Switching between permissive and enforcing mode can be of interest for policy developers or system administrators who are modifying the system to use SELinux properly. We can also use it to quickly verify whether an application warning or error is due to SELinux access controls or not—assuming the application is not SELinux-aware, which we will talk about in theUnderstanding SELinux-aware applicationssection.
On production systems, it might be of interest to disable the ability to switch to permissive mode. Disabling this feature usually requires the Linux kernel to be rebuilt, but SELinux policy developers have also thought of a different way to disallow users from toggling the SELinux state. The privileges that users need to switch to permissive mode are conditional, and system administrators can easily toggle this to disable switching back from enforcing mode to permissive mode. The condition is implemented through an SELinux Boolean calledsecure_mode_policyload
whose default value isoff
(meaning switching SELinux state is allowed).
SELinux Booleansareconfigurable options that take on a single value (on
oroff
, althoughtrue
/false
and1
/0
are valid values as well) and manipulate parts of the active SELinux policy. The value of the conditionals can be persisted (meaning they survive reboots) or be kept only during the current boot session. We can persist the value across reboots by adding-P
to thesetsebool
command, as follows:
# setsebool -P secure_mode_policyload on
The use of thesecure_mode_policyload
SELinux Boolean allows administrators to restrict switching from enforcing mode back to permissive mode. This does not disable SELinux completely, but only toggles whether it will act upon its policies or not.
Switchingfrom a disabled state to a running state is not supported. However, the reverse is possible, but only under the following condition: if the Linux kernel is built with theSECURITY_SELINUX_DISABLE
kernel configuration parameter, then services such asinit
can effectively disable SELinux at runtime, but only if no SELinux policy is loaded yet. This functionality, however, is not recommended to be actively used, and was only introduced for platforms where boot options are hard to use. The feature is marked as deprecated in recent kernels as such platforms are few in number.
Using kernel boot parameters
Using thesetenforce
command makes sense when we want to switch to permissive or enforcingmode at a point in time when we have interactive access to the system. But what if we need this on system boot? If the system refuses to boot properly due to SELinux access controls, we cannot edit the/etc/selinux/config
file. Luckily, we can change the SELinux state through other means as well.
The solution is to use kernel boot parameters. We can boot a Linux system with one or two parameters that take precedence over the/etc/selinux/config
setting, as follows:
selinux=0
: This informs the system to disable SELinux completely, and has the same effect as settingSELINUX=disabled
in the configuration file. When set, the other parameter (enforcing
) is not consulted. Please remember that booting a system with SELinux disabled means that to enable it again, we need to relabel all files and resources on the filesystem. Theselinux=
parameter is supported through theCONFIG_SECURITY_SELINUX_BOOTPARAM
kernel configuration.enforcing=0
: This informs the system to run SELinux in permissive mode, and has the same effect as settingSELINUX=permissive
in the configuration file.enforcing=1
: This informs the system to run SELinux in enforcing mode, and has the same effect as settingSELINUX=enforcing
in the configuration file.
Consider a Linux system that uses GRUB2 as its boot loader, and we want to add enforcing=0
to the boot entry. To accomplish this, we execute the following steps:
- Reboot the system until the GRUB2 boot screen comes up.
- Navigate with the arrow keys to the boot entry for which the SELinux state must be altered. This is usually the default boot entry and should be already selected.
- Press theEkey to edit the boot entry line. Do this before the GRUB2 timer reaches zero; otherwise, the system will continue to boot.
- Use the arrow keys to go to the end of the line that starts with
options
. If no such line exists, go to the end of the line that starts withlinux
,linux16
, orlinuxefi
. - Add
enforcing=0
to the end of this line. - PressCtrl+XorF10to boot the entry.
Other bootloaders have similar approaches to changing the boot line without persisting it for every reboot. Consult your distribution documentation for more details.
Alongside the SELinux-specific parameters, there are a fewLinux Security Module(LSM)-relatedboot parameters that can be useful to know, especially when you are combining multiple LSM modules on the same system. These are detailed as follows:
- The
lsm.debug
boot parameter enables LSM initialization debugging output, showing which LSM modules it effectively enables or ignores, and which LSM modules are considered as exclusive. - The
lsm=lsm1,…,lsmN
option chooses the order of LSM initialization. For instance, to initialize SELinux before lockdown, uselsm=selinux,lockdown
. - The
security=
boot parameter enables selection of the active, major/exclusive LSM module. This parameter, however, is deprecated, favoring thelsm=
parameter.
When using SELinux in production, it might be wise to properly protect the boot menu—for instance, by password-protecting the menu and regularly verifying the integrity of the boot menu files.
Disabling SELinux protections for a single service
Since policy version 23 (which came with Linux 2.6.26), SELinux also supports a more granularapproach to switching between permissive and enforcing mode: the use of permissive domains. As mentioned before, a domain is a term that SELinux uses for types (labels) assigned to processes. Withpermissive domains, we canmark one or more domains as permissive (and, as such, not enforced by SELinux rules), even though the rest of the system is still running in enforcing mode.
To make a domain permissive, we use thesemanage
command, as follows:
# semanage permissive -a minidlna_t
With the same semanage
command, we can list the currently defined permissive domains, like this:
# semanage permissive -l
Builtin Permissive Types
Customized Permissive Types
minidlna_t
In the previous example, you will notice that there is also room forbuilt-inpermissive types. These are domains that have been marked as permissive by the policy developers of theLinux distribution itself. Some distributions opt to introduce new application policies in permissive mode first, allowing users to test out the policies before enforcing them. When that is the case, you can find these permissive domains underBuiltin Permissive Types
.
Another method for listing the custom permissive types (those not marked as permissive through the distribution) is to use thesemodule
command. In the previous chapter, we briefly touched on this command when talking about SELinux policy modules. We can use it to list the SELinux policy modules that havepermissive_
in their name because thesemanage permissive
command generates a small SELinux policy module to mark the domain as permissive, as illustrated in the following code snippet:
# semodule -l | grep permissive_
permissive_minidlna_t
To remove the permissive mode from the domain, pass the -d
argument to the semanage
command. This is only possible for domains that the system administrator marked as permissive, though—distribution-provided permissive domains cannot be switched to enforcing mode through this approach. This is illustrated in the following code snippet:
# semanage permissive -d minidlna_t
When a domain is marked as permissive, the application should behave as if SELinux is not enabled on the system (SELinux will not be enforcing anything that particular application/domain does), making it easier for us to discover whether SELinux is really causing a permission issue. Note, though, that other domains (including those that interact with a permissive domain) are themselves still governed and enforced through the SELinux access controls.
Understanding SELinux-aware applications
Most applicationsthemselves do not have knowledge that they are running on an SELinux-enabled system. Without this knowledge, permissive mode truly means that the application behaves as if SELinux were not enabled to begin with. However, some applications actively rely on the SELinux policy to make access control decisions, or interact with SELinux for further information gathering. We call these applicationsSELinux-awarebecause they change their behavior based on the SELinux-related information available.
Sadly, many of these SELinux-aware applications do not properly validate whether they are running in permissive mode or not. As a result, running these applications in a permissive domain (or the entire system in permissive mode) will generally not result in the application running as if SELinux were not active.
Examples ofsuch applications are theSecure Shell(SSH) daemon, the system login service, theinit
system, and some cron daemons, as well as several core Linux utilities (such asls
andid
). They might show permission failures or different behavior based on the SELinux policy, even if SELinux is not in enforcing mode.
We can find out whether an application is SELinux-aware by checking whether the application is dynamically linked with thelibselinux
library. Such checks are possible withreadelf
,ldd
, orobjdump
, as follows:
$ readelf -d /bin/ls | grep selinux
0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1]
$ ldd /bin/ls | grep selinux
libselinux.so.1 => /lib64/libselinux.so.1 (0x00005d415f3f03f0)
$ objdump -x /bin/ls | grep selinux
NEEDED libselinux.so.1
Knowing whether an application is SELinux-aware or not can help in troubleshooting failures, as the application’s behavior might still be different between a disabled SELinux state and a permissive SELinux state.
Up until now, we’ve focused on enabling or disabling SELinux, and thus on a granular or coarse-grained matter. Once it is enabled though, its interaction with the administrator will be throughpolicy enforcement and logging. So, let’s look at how SELinux handles logging.