1. Introduction
Security-Enhanced Linux (SELinux) is a way to manage the security of a Linux system via policies. In essence, SELinux consists of modifications to the Linux kernel alongside userland tools. Although the general principles behind SELinux are universal, its implementation and toolset can vary across distributions.
In this tutorial, we learn how to set up and disable SELinux. First, we go over the basic SELinux setup. After that, we check the basic configuration file and its options to manage SELinux. Finally, we explore pre-boot methods for controlling SELinux.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments unless otherwise specified.
2. SELinux Setup
Due to differences between Linux distributions, referring to the distribution-specific documentation when setting up SELinux is critical for system stability and security.
For example, Ubuntu doesn’t automatically load the Ubuntu SELinux policy script, so we need to download and configure it to run.
There are several steps to set up SELinux on Debian and Debian-based operating systems like Ubuntu, but they are almost universal:
- ensure kernel support for SELinux – the default or build with the CONFIG_AUDIT, CONFIG_SECURITY_SELINUX configuration flags
- ensure filesystem support for SELinux – ext* or XFS, BTRFS, ReiserFS, or SquashFS with caveats (e.g., enable XATTRs)
- install SELinux default policy and userland utilities:
$ apt-get install selinux-basics selinux-policy-default auditd
- activate SELinux via the selinux-activate (Debian) or similar command – configures GRUB and the SELinux pluggable authentication module (PAM), creating /.autorelabel
- reboot – may automatically reboot more than once until it boots to permissive mode SELinux
- if available, use a tool to check the SELinux setup, detect and report common problems – check-selinux-installation (Debian) or similar
- test the setup in permissive mode – SELinux policy isn’t enforced in this mode, but denials are logged
- if all feels correct, enable enforcing mode of the default policy – run setenforce 1 or add enforcing=1 to the kernel boot parameters
- reboot
In addition, we can check the current status of SELinux by using the sestatus command:
$ sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: permissive
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allow
Memory protection checking: actual (secure)
Max kernel policy version: 30
Of course, above are the steps to the most basic setup, on top of which a security administrator can and often should add and build their own policies and rulesets. Also, while these steps look comprehensible, due to the complexity and low level of the architecture, there are numerous pitfalls and workarounds to consider.
3. Disable SELinux
As we saw, SELinux isn’t an isolated component in a sandbox. Instead, being part of the kernel, it lives at the core of the operating system (OS) while also acting via services and userland utilities.
Thus, depending on the reason for disabling SELinux, i.e., whether there is a problem with the feature or not, we might not achieve the desired results by simply toggling a single setting, albeit in the kernel.
In all cases where we add or modify kernel parameters, we do so via the bootloader configuration files. For example, there are two standard files for GRUB:
- /etc/default/grub, in GRUB_CMDLINE_LINUX
- /etc/grub.conf, on the kernel line
Now, let’s check the SELinux control options.
3.1. /etc/selinux/config
The primary SELinux state control settings are in /etc/selinux/config:
$ cat /etc/selinux/config
# 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 these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
By assigning the permissive value to SELINUX, we ensure SELinux doesn’t force compliance with any configured policy, but we still get warning messages when the policy should have been enforced. Conversely, disabled stops these debug messages as well.
3.2. selinux=0
There is one main underlying parameter to disable SELinux: selinux=0. In normal conditions, **adding selinux=0 to the kernel command line should be sufficient to turn SELinux off:
kernel /boot/vmlinuz-[...]generic root=UUID=[...] ro quiet splash selinux=0
Alternatively, we can change the kernel parameters during boot.
Importantly, although it can be configured before we boot to Linux, the selinux=0 parameter isn’t the recommended way to temporarily disable SELinux. To that end, it’s usually better to revert the policy enforcement.
3.3. enforcing=0
The standard approach for debugging and temporarily preventing SELinux from interfering with any actions is by changing the enforcing kernel parameter to 0:
kernel /boot/vmlinuz-[...]generic root=UUID=[...] ro quiet splash enforcing=0
Indeed, this parameter is similar to the SELINUX options of the /etc/selinux/config file but can be set before boot.
Conversely, we can make sure the policy is enforced by changing the value back to 1:
kernel /boot/vmlinuz-[...]generic root=UUID=[...] ro quiet splash enforcing=1
Critically, SELinux uses auditd. So, we can check for any problematic areas where SELinux interferes via ausearch:
$ ausearch -m AVC,USER_AVC,SELINUX_ERR -ts today
This way, we can debug and see what policy changes we might need before reenabling SELinux.
4. Summary
In this article, we talked about setting up and disabling SELinux.
In conclusion, due to its wide area of effect over the system security, whenever possible, disabling SELinux should be done with caution and via the recommended channels.