From Gentoo Wiki
Jump to:navigation Jump to:search

Getting an SELinux-powered Gentoo installation doesn't require weird actions. What is needed is to install Gentoo Linux with the correct profile, correct kernel configuration and some file system relabeling. It is seriously recommended to use SELinux together with other hardening improvements.

Installing Gentoo (Hardened)

This document assumes the reader starts with an existing Gentoo Linux system which needs to be converted to Gentoo with SELinux. It is possible to make the right decisions during a Gentoo installation to immediately start with an SELinux system. However, this article is focusing on a conversion of an existing system as that is the most common approach.

SELinux stage3 tarballs are also available and supported - this is significantly easier than performing the steps below. The tarballs can be simply unpacked onto a target system, relabel the entire system, add the initial user to the administration SELinux user and reboot.

When updating an already running system, please verify that the running kernel has no SELinux enabled (see Configuring kernel below) or make sure it is disabled (e.g. put selinux=0 to the kernel command line). Otherwise an "!!! [Errno 61] No data available" will happen when installing the selinux-base policy package (see bug #792723).

Performing a standard installation

Install Gentoo Linux according to the Gentoo Handbook installation instructions. It is recommended to use the hardened stage 3 tarballs. Perform a full installation to the point that the system is booted into a (primitive) Gentoo base installation.

Choosing an SELinux policy type

Gentoo supports four policy types within SELinux: strict, targeted, mcs and mls.

The differentiation between strict and targeted is based upon the unconfined domain. When targeted is loaded, the processes on the system that are not specifically confined within a particular policy module will be part of the unconfined domains whose purpose is to allow most activities by default (rather than deny by default). As a result, processes that run inside unconfined domains have no restrictions apart from those already enforced by standard Linux security. Although running without the unconfined domains is considered more secure, it will also be more challenging for the administrator to make sure the system still functions properly as there are no policy modules for each and every application "out there".

Next to targeted and strict, administrators can opt for mcs to allow categorization of resources. This is useful on multi-tenant systems such as web servers, virtualization hosts, ... where multiple processes will be running, most of them in the same security domain, but in different categories. Note though that to take advantage of the additional category support, either the applications themselves (such as the web server or hypervisor tools) need to configure the SELinux categories (so they need to support SELinux) or the administrator will need to script around to start the individual instances with separate categories. Otherwise, mcs is just the same as targeted or strict.

Finally, Gentoo also provides mls to support a true multi-level security system. However, MLS is currently still considered experimental in Gentoo and as such not recommended.

In case of mcs or mls, the unconfined USE flag needs to be used to enable or disable unconfined domains in these policy types. The strict policy store does not use the USE flag at all (as it does not support unconfined domains at all) and the targeted policy store (which uses unconfined domains) requires the USE flag set.

Generally speaking, mcs is recommended for most users. It allows for the greatest amount of flexibility and is usually expected by programs which can take advantage of the aforementioned category separation, namely virtualization and container technologies. Without mcs support, such programs may need additional configuration on other policy types.

Save the choice for the policy store in /etc/portage/make.conf. That way, Portage will only install the policy modules for that SELinux policy store. By default, the SELinux profiles enable strict and targeted (with strict being the default active type).

FILE /etc/portage/make.confSetting the supported policy stores
POLICY_TYPES="strict targeted"

Multiple stores can be defined, although only one store can be active at any point in time. This is handled through the SELinux configuration itself, which is covered later in the installation.

Setting file system contexts

If the /tmp location is a tmpfs-mounted file system, then it is necessary to tell the kernel that the root context of this location is tmp_t instead of tmpfs_t, which is the default context assigned to tmpfs-mounted file systems.

A context is a label assigned to a resource, and is what SELinux bases its access control decisions on. See type enforcement for more information, or our quick introduction to SELinux.
systemd automatically relabeles /tmp, /dev and /run. You don't need the entries then.

To configure the /tmp mount, edit the /etc/fstab file:

FILE /etc/fstabSetting the rootcontext for the /tmp mount
# For a "targeted" or "strict" policy type:
tmpfs  /tmp  tmpfs  defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t  0 0
# For an "mls" or "mcs" policy type:
tmpfs  /tmp  tmpfs  defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t:s0  0 0

Next, set the next line in /etc/fstab to configure the context for the /run location:

FILE /etc/fstabSetting the rootcontext for the /run mount
# For a "targeted" or "strict" policy type:
tmpfs  /run   tmpfs  mode=0755,nosuid,nodev,rootcontext=system_u:object_r:var_run_t  0 0
# For an "mls" or "mcs" policy type:
tmpfs  /run   tmpfs  mode=0755,nosuid,nodev,rootcontext=system_u:object_r:var_run_t:s0  0 0

Change the Gentoo profile

Read relevant documentation before performing any profile changes.

Switch the Gentoo profile to the right SELinux profile (for instance, default/linux/amd64/17.1/hardened/selinux).

root #eselect profile list
Available profile symlink targets:
  [1]   default/linux/amd64/17.1 (stable) *
  [2]   default/linux/amd64/17.1/selinux (stable)
  [3]   default/linux/amd64/17.1/hardened (stable)
  [4]   default/linux/amd64/17.1/hardened/selinux (stable)
  [5]   default/linux/amd64/17.1/desktop (stable)
  [6]   default/linux/amd64/17.1/desktop/gnome (stable)
  [7]   default/linux/amd64/17.1/desktop/gnome/systemd (stable)
  [8]   default/linux/amd64/17.1/desktop/plasma (stable)
  [9]   default/linux/amd64/17.1/desktop/plasma/systemd (stable)
  [10]  default/linux/amd64/17.1/desktop/systemd (stable)
  [11]  default/linux/amd64/17.1/developer (exp)
  [12]  default/linux/amd64/17.1/no-multilib (stable)
  [13]  default/linux/amd64/17.1/no-multilib/hardened (stable)
  [14]  default/linux/amd64/17.1/no-multilib/hardened/selinux (stable)
  [15]  default/linux/amd64/17.1/no-multilib/systemd (dev)
  [16]  default/linux/amd64/17.1/no-multilib/systemd/selinux (exp)
  [17]  default/linux/amd64/17.1/systemd (stable)
  [18]  default/linux/amd64/17.1/systemd/selinux (exp)
  [19]  default/linux/amd64/17.1/clang (exp)
  [20]  default/linux/amd64/17.0 (dev)
  [21]  default/linux/amd64/17.0/selinux (dev)
  [22]  default/linux/amd64/17.0/hardened (dev)
  [23]  default/linux/amd64/17.0/hardened/selinux (dev)
  [24]  default/linux/amd64/17.0/desktop (dev)
  [25]  default/linux/amd64/17.0/desktop/gnome (dev)
  [26]  default/linux/amd64/17.0/desktop/gnome/systemd (dev)
  [27]  default/linux/amd64/17.0/desktop/plasma (dev)
  [28]  default/linux/amd64/17.0/desktop/plasma/systemd (dev)
  [29]  default/linux/amd64/17.0/developer (exp)
  [30]  default/linux/amd64/17.0/no-multilib (dev)
  [31]  default/linux/amd64/17.0/no-multilib/hardened (dev)
  [32]  default/linux/amd64/17.0/no-multilib/hardened/selinux (dev)
  [33]  default/linux/amd64/17.0/systemd (dev)
  [34]  default/linux/amd64/17.0/x32 (dev)
  [35]  default/linux/amd64/17.0/musl (exp)
  [36]  default/linux/amd64/17.0/musl/hardened (exp)
  [37]  default/linux/amd64/17.0/musl/hardened/selinux (exp)
root #eselect profile set 4
Do not rebuild the system right now - wait until this is instructed by this document later. Rebuilding the system will pull in SELinux policies which could make the system unreachable if we reboot after it without taking proper countermeasures.

Starting from the profile change, Portage will warn after every installation that it was "Unable to set SELinux security labels". This is to be expected, because the tools and capabilities that Portage requires to set the security labels aren't available yet. This warning will vanish the moment the SELinux installation is completed.

Don't update the system yet - a couple of packages need to be installed first in a particular order that Portage isn't aware of.

Updating make.conf

Take a look at the following SELinux related USE flags and decide which ones to enable or disable.

USE flag Description
peer_perms The peer_perms capability controls the SELinux policy network peer controls. If set, the access control mechanisms that SELinux uses for network based labeling are consolidated. This setting is recommended as the policy is also updated to reflect this. If not set, the old mechanisms (NetLabel and Labeled IPsec) are used side by side.
ubac When disabled, the SELinux policy is built without user-based access control.
unconfined When set, policy builds (except for the "strict" policy) will include the unconfined module (thus allowing unconfined domains to exist on the system).

Update the USE variable in /etc/portage/make.conf or in an appropriate /etc/portage/package.use location for the sec-policy/selinux-base package.

If any of the above USE flags are changed on a running SELinux system, a full policy rebuild and full policy reload should be done to ensure that the desired changes take effect.

Installing an SELinux kernel

Option 1: re-use the default gentoo-kernel-bin

The regular pre-built Gentoo dist-kernel "sys-kernel/gentoo-kernel-bin" already contains support for SELinux but it comes pre-DISABLED (as of 5.4.x).

root #emerge --ask sys-kernel/gentoo-kernel-bin

(via the option "SELinux runtime disable" = CONFIG_SECURITY_SELINUX_DISABLE=y)

If you use this kernel-bin, it is NOT necessary to recompile in order to ENABLE it.

However, a kernel command-line parameter is REQUIRED at boot time (to undo the runtime disable) - (these can be set during grub):


lsm= is the new parameter, and can contain a list of other modules. Theoretically, you could append more modules to the lsm= in a comma separated list, like "selinux,yama" (not part of this guide, but it is currently the only other LSM security module this default dist-kernel is built with).

security= is old and deprecated, and can only contain 1 entry, but still works.

Another parameter selinux=1 is often mentioned instead, but doesn't actually take effect by itself, because the LSM parameter now takes precedence.

These parameters just ENABLE kernel support, after which, the /etc/selinux/config file will then take over and choose the mode of "enforcing/permissive/disabled" and type of "targeted/strict/mls/mcs". Enforcing mode can be set as a boot parameter with enforcing=1 or permissive mode set with enforcing=0

Those enforcing options will be relevant later in the guide, and dealt with, do not set them now

Option 2: recompiling kernel from gentoo-sources

The default Linux kernel sources also offer SELinux support, but need to be explicitly configured during compilation:

root #emerge --ask sys-kernel/gentoo-sources

Next, reconfigure the kernel with the appropriate security settings. This includes, but is not limited to

  • Support for extended attributes in the various file systems
  • Support system-call auditing
  • Support for SELinux

Below, a quick overview of the recommended settings to configure in make menuconfig:

KERNEL Enabling SELinux
Under "General setup"
[*] Auditing support
Under "File systems"
  (For each file system you use, make sure extended attribute support is enabled)
<*> Second extended fs support
[*]   Ext2 extended attributes
[ ]     Ext2 POSIX Access Control Lists
[*]     Ext2 Security Labels
<*> Ext3 journalling file system support
[*]   Ext3 extended attributes
[ ]     Ext3 POSIX Access Control Lists
[*]     Ext3 Security Labels
<*> The Extended 4 (ext4) filesystem
[*]   Ext4 extended attributes
[ ]     Ext4 POSIX Access Control Lists
[*]     Ext4 Security Labels
<*> JFS filesystem support
[ ]   JFS POSIX Access Control Lists
[*]   JFS Security Labels
[ ]   JFS debugging
[ ]   JFS statistics
<*> XFS filesystem support
[ ]   XFS Quota support
[ ]   XFS POSIX ACL support
[ ]   XFS Realtime subvolume support (EXPERIMENTAL)
[ ]   XFS Debugging Support
<*> Btrfs filesystem (EXPERIMENTAL)
[ ]   Btrfs POSIX Access Control Lists
Under "Security options"
[*] Enable different security models
[*] Socket and Networking Security Hooks
[*] NSA SELinux Support
[ ]   NSA SELinux boot parameter
[ ]   NSA SELinux runtime disable
[*]   NSA SELinux Development Support
[ ]   NSA SELinux AVC Statistics
(0)   NSA SELinux checkreqprot default value
    Ordered list of enabled LSMs ---> prepend "selinux"
"Ordered list of enabled LSMs" (CONFIG_LSM) was introduced in kernel 5.1. Before that, the same effect is obtained by setting "Default security module (SELinux)" under "Security options"

Do not forget to prepend selinux to Ordered list of enabled LSMs. Otherwise, the security=selinux boot parameter has to be set in the bootloader configuration in order to enable SELinux.

If you must be able to enable/disable SELinux, the following settings allow to boot the kernel with option selinux=0 to disable it:

KERNEL Enabling SELinux
Under "Security options"
[*] NSA SELinux Support
[*]   NSA SELinux boot parameter 
(1)     NSA SELinux boot parameter default value

Build and install the new Linux kernel and its modules.

Configure SELinux

In the second part of the SELinux installation, we cover the installation of the proper utilities, relabel the entire file system and configure the policy.

Installing policies and utilities, part one

First, install the base SELinux policy package sec-policy/selinux-base. This package provides the SELinux configuration file which needs to be adjusted prior to building all other SELinux packages. As soon as sys-apps/policycoreutils is installed (it's a dependency of sec-policy/selinux-base), Portage will attempt to enable its SELinux support. However, as SELinux is currently not properly configured, it is necessary to disable this through FEATURES="-selinux":

root #FEATURES="-selinux" emerge -1 selinux-base

Configuring the SELinux policy

The main SELinux configuration file is now at /etc/selinux/config. It needs to be edited to set two important values: SELINUX and SELINUXTYPE.

FILE /etc/selinux/config
# This file controls the state of SELinux on the system on boot.
# 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.
# SELINUXTYPE can take one of these four values:
#       targeted - Only targeted network daemons are protected.
#       strict   - Full SELinux protection.
#       mls      - Full SELinux protection with Multi-Level Security
#       mcs      - Full SELinux protection with Multi-Category Security
#                  (mls, but only one sensitivity level)

The SELINUX variable defines how SELinux should behave:

  • enforcing will enable and enforce policies. This is the target at the end, but we need to start in permissive mode first to make sure everything would work as expected.
  • permissive will enable policies, but not enforce them. Any violation is reported but not denied. This is where most users should start from as it will not impact the system, yet allow users to get acquainted with SELinux - and validate the warnings to see if the system can be switched towards enforcing or not later.
  • disabled will completely disable the policies. As this will not show any violations as well, it is not recommended.

The SELINUXTYPE variable selects the SELinux policy store to load. Most development is done using the strict policy store (as it provides full confinement), although the others are supported as well.

Make sure that the SELINUX variable is set to permissive right now. We will switch to enforcing later.

Installing policies and utilities, part two

Now continue with the installation of the SELinux policies. Rebuild the sec-policy/selinux-base package if SELINUXTYPE is changed to something else than strict, and then install the core SELinux policies through the sec-policy/selinux-base-policy package. This package contains the core SELinux policies needed to get the system up and running using SELinux. As Portage will try to label and reload policies we need to temporarily disable SELinux support again (as Portage wouldn't be able to label anything as it doesn't understand it yet).

After you've emerged sec-policy/selinux-base package in part one of this installation it is now necessary to use FEATURES="-selinux -sesandbox" for sec-policy/selinux-base and sec-policy/selinux-base-policy packages.
root #FEATURES="-selinux -sesandbox" emerge -1 selinux-base
root #FEATURES="-selinux -sesandbox" emerge -1 selinux-base-policy

Now it is finally time to rebuild all packages affected by the profile change. Don't forget to use etc-update or dispatch-conf afterwards as some changes to configuration files will need to be made. This operation will also pull in all SELinux policy packages needed for the various components already installed on the system.

root #emerge -uDN @world


Repeat these steps every time the system is rebooted from a non-SELinux enabled mode into an SELinux enabled mode, as running with a non-SELinux enabled kernel will not update the security attributes of the files created or manipulated during day-to-day activities on the system.

Next relabel all devices and openrc related files. This will apply the correct security contexts (labels) onto the necessary files. We start by bind-mounting / onto /mnt/gentoo. This will allow us to relabel the mount points themselves rather than the mounted file systems that are already mounted on the main file system.

root #mkdir /mnt/gentoo
root #mount -o bind / /mnt/gentoo

In the following command, substitute strict in the next command with targeted (or other policy store name) depending on the SELINUXTYPE value. If your system has more active mountpoints than the usual set of /dev,/home,/proc,/run,/sys,/tmp, list them too.

root #setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/{dev,home,proc,run,sys,tmp}
root #umount /mnt/gentoo

If the system uses a swapfile rather than a swap partition, label it accordingly:

root #semanage fcontext -a -t swapfile_t "/swapfile"
root #restorecon /swapfile

Now relabel the entire file system. The next command will apply the correct security context onto the files on the entire file system, based on the security context information provided by the SELinux policy modules installed.

root #rlpkg -a -r

If an SELinux policy module for a package is installed after that particular package, then rlpkg needs to be run for that package to make sure that the security contexts for its files are set correctly. For instance, if sec-policy/selinux-screen would be installed manually (due to a missing dependency) after installing app-misc/screen:

root #rlpkg screen

Define the administrator accounts

If the SELINUXTYPE variable is set to strict, then it is necessary to map the account(s) used to manage the system (those that need access to Portage) to the staff_u SELinux user. If not, none of the accounts will be able to successfully manage the system (except for root, but then the administrator will need to login as root directly and not through sudo or su.) By default, users are mapped to the user_u SELinux user who doesn't have the appropriate rights (nor access to the appropriate roles) to manage a system. Accounts that are mapped to staff_u can, but might need to switch roles from staff_r to sysadm_r before they are granted the appropriate privileges.

In the following example, we map the john Linux account to the staff_u SELinux user:

root #semanage login -a -s staff_u john
root #restorecon -R -F /home/john

When system administration tasks need to be executed, the user will need to switch the role to sysadm_r. For this, the newrole command can be used.

user $id -Z
user $newrole -r sysadm_r
Password: (Enter your password)
user $id -Z

In a targeted policy, the users will be of type unconfined_t and will already have the necessary privileges to perform system administrative tasks.


sudo can also be configured to transition from staff_u (or other) users to configured SELinux types/roles, for example:

FILE /etc/sudoers.d/wheel
%wheel ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL

Supporting service administration

By default, the Gentoo Hardened SELinux policies will allow the sysadm_t domain access to all services. However, some of these services have policies that allow them to be assigned to individual, non-root users. This requires the user to be granted the system_r role (meaning the user can, under certain circumstances, have his role change towards the system role).

It is therefore recommended to grant the system_r role to the administrative SELinux users that are going to administer the system. These are most likely the root and staff_u SELinux user.

root #semanage user -m -R "staff_r sysadm_r system_r" root
root #semanage user -m -R "staff_r sysadm_r system_r" staff_u


That's it. SELinux is now fully configured on the system. Although it will boot in permissive mode (most likely) right now, everything is now in place to validate if SELinux will further prevent applications from working or not. If, after booting and logging in, the id -Z command shows the proper context, then the system is most likely ready to be switched into enforcing mode (by editing /etc/selinux/config).