There exists some blog posts, articles about SELinux mode configuration already, which easily can be found by searching on google: “how to enable/disable selinux, how to configure selinux”. Moreover, The SELinux Notebook 4th edition has information about SELinux modes and global configuration files, respectively in chapter 2.15 and 3.2.1. However, I think, SELinux has some controversial issues about mode configuration and none of these resources are good enough to clear the mind about confusing SELinux mode configuration.
First of all, linux kernel has some configuration options which allows/disallows SELinux to be disabled/enabled. These options are:
- CONFIG_SECURITY_SELINUX_BOOTPARAM: This option allows SELinux to be disabled at boot. If this option is selected, SELinux functionality can be disabled with selinux=0 on the kernel command line. Moreover, SELinux boot parameter default value can be changed by setting CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE to 0 or 1, respectively disabling or enabling SELinux at bootup.
- CONFIG_SECURITY_SELINUX_DISABLE: This option enables writing to a selinuxfs node ‘disable’, which allows SELinux to be disabled at runtime prior to the policy load. That means, kernel will be “capable” to disable SELinux at runtime. In here, Stephen Smalley claims that /sys/fs/selinux/disable can be triggered by setting SELINUX=disabled in /etc/selinux/config. However modifications on /etc/selinux/config file does not affect system until next boot-up. So that, it is the first confusing thing, since linux kernel commented on this option: “SELinux will remain disabled until the next boot”. I still do not know how to disable SELinux (disable, not permissive) at runtime by the help of this kernel configuration.
- CONFIG_SECURITY_SELINUX_DEVELOP: With this option enabled, the kernel will start in permissive mode unless you specify enforcing=1 on the kernel command line.
So far, we know that these arguments can be passed to kernel:
- selinux=1 /* enabled */
- selinux=0 /* disabled */
- enforcing=1 /* enabled & enforcing */
- enforcing=0 /* enabled & permissive */
Additionally, from Dan Walsh’s blogpost, there is also
boot argument to relabel the system with exact security contexts.
Furthermore, another way to configure SELinux modes is global configuration file: /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.
According to these options, SELinux modes can be changed. However which option overrides the other one is confusing.
Temporarily switching between permissive and enforcing
Two way to switch between permissive and enforcing at runtime. Note that after reboot these options will be overriden by the system defaults. Moreover, switching to permissive/enforcing mode is only applicable unless selinux is disabled.
- Using selinuxfx
# switching to enforcing echo 1 > /sys/fs/selinux/enforce # switching to permissive echo 0 > /sys/fs/selinux/enforce
- Using setenforce utility
# switching to enforcing setenforce 1 /* or setenforce Enforcing */ # switching to permissive setenforce 0 /* or setenforce Permissive */
Permanently switching SELinux modes
The second confusing thing about SELinux mode configuration is that even though kernel boot parameters override the config file, the exact opposite of this action is also possible. To clarify this options, I have made some tests on my running ARM platform. Note that, I compiled kernel with these configs:
CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_AVC_STATS=y CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
- No boot parameters and no config file exists, then system boots at Permissive mode. CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE & CONFIG_SECURITY_SELINUX_DEVELOP configurations are the reason of that. In fact, selinux=1 is passed as default.
- None or selinux=1 as boot parameters and SELINUX=enforcing in config file, then system boots at Enforcing.
- None or selinux=1 as boot parameters and SELINUX=permissive in config file, then system boots at Permissive.
- None or selinux=1 as boot parameters and SELINUX=disabled in config file, SELinux: Disabled at runtime.
- If selinux=0 passed as kernel boot parameter, then SELinux will be disabled whatever passed in config file. However, it is not recommended.
- enforcing=0 as boot parameter, SELINUX=enforcing in config file, then system boots at Permissive mode.
- enforcing=0 as boot parameter, SELINUX=disabled in config file, then SELinux: Disabled at runtime.
- enforcing=1 passed as boot parameter, SELINUX=permissive in config file, then system boots at Enforcing mode.
- enforcing=1 passed as boot parameter, SELINUX=disabled in config file, then unexpectedly: SELinux: Disabled at runtime and kernel panic occurs since can’t load SELinux Policy. I do not know the exact reason of this error. I actually tried to relabel filesystem before enforcing the system, so expected result of this action should be Enforcing system boot-up.
So, boot argument selinux=0 overrides /etc/config/selinux, however selinux=1 does not overrides. Moreover, while passing enforcing=0, even though in /etc/selinux/config includes SELINUX=enforcing, system starts w/ permissive mode. However if config file includes SELINUX=disabled, system starts w/o SELinux. I think this is confusing and kind of inconsistent but there should be a good rationale for that. Most people hardly ever get confronted with these situations.
Switching from disabled to enabled
As mentioned gentoo:selinux tutorials and here, If system booted with SELinux disabled, we need to relabel filesystem to enable again SELinux. After disabling SELinux, switching back to enforcing mode causes kernel crash, since relabeling can not be possible in enforcing mode. So that, switching from disabled to enabled mode is only possible in permissive mode. After booting in permissive mode:
can be used to relabel filesystem. Also, kernel boot parameter
will force the system to relabel, too. In my experiments, after disabling SELinux, passing enforcing=1 as kernel parameters causes kernel panic (as expected). Here the logs:
[ 8.245513] SELinux: Disabled at runtime. [ 8.474853] type=1404 audit(946686015.345:2): selinux=0 auid=4294967295 ses=4294967295 can't load SELinux Policy. Machine is in enforcing mode. Halting now.
So, what’s the conclusion?
If your intention is to disable SELinux permanently, and never ever want to be enabled again, even though it is not recommended, passing selinux=0 as kernel boot parameter is the best option. For this case, kernel boot argument overrides options in /etc/selinux/config. However, unless SELinux is intented to be disabled, passing selinux=1 or none as kernel boot parameter and modifying /etc/selinux/config file, according to intention, will be proper action.