User:Jowr/selinuxrewrite
Getting a 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 (such as PaX / grSecurity).
Gentoo supports SELinux installation both from scratch (via the requisite stage3 tarball) as well as by converting an existing non-SELinux system.
Conversion of an existing system
This process is relatively risk free, as Gentoo will happily run normally with SELinux userspace in an inconsistent state so long as the selinux filesystem in /sys/fs/selinux
is not mounted. It is, however, important that the steps be followed in this order to ensure that the system arrives in a stable state.
Reversion / removal is as simple as a profile change and a system rebuild.
Change the Gentoo profile
Switch the Gentoo profile to the right SELinux profile (for instance, hardened/linux/amd64/no-multilib/selinux).
root #
eselect profile list
Available profile symlink targets: [1] default/linux/amd64/13.0 [2] default/linux/amd64/13.0/selinux [3] default/linux/amd64/13.0/desktop [4] default/linux/amd64/13.0/desktop/gnome [5] default/linux/amd64/13.0/desktop/gnome/systemd [6] default/linux/amd64/13.0/desktop/kde [7] default/linux/amd64/13.0/desktop/kde/systemd [8] default/linux/amd64/13.0/developer [9] default/linux/amd64/13.0/no-multilib [10] default/linux/amd64/13.0/x32 [11] hardened/linux/amd64 * [12] hardened/linux/amd64/selinux [13] hardened/linux/amd64/no-multilib [14] hardened/linux/amd64/no-multilib/selinux [15] hardened/linux/amd64/x32 [16] hardened/linux/uclibc/amd64
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.
I'M LETTING THE PROFILE GUIDE MAKE.CONF AND OTHER CHANGES AND LEAVING IT TO "CONFIGURING SELINUX" FOR FURTHER TUNING, TO AVOID WIKIBLOAT AND ENDLESS LINKS
Setting mount point 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.
To configure the /tmp mount, edit the /etc/fstab file:
# 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:
# 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
Installing a SELinux kernel
Although the default Linux kernels offer SELinux support, it is recommended to use the sys-kernel/hardened-sources package as it offers more hardening features alongside SELinux.
root #
emerge --ask sys-kernel/hardened-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 can be found.
Under "General setup"
[*] Prompt for development and/or incomplete code/drivers
[*] Auditing support
[*] Enable system-call 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
[ ] Ext2 execute in place support
<*> Ext3 journalling file system support
[ ] Default to 'data=ordered' in ext3
[*] 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
(1) NSA SELinux checkreqprot default value
[ ] NSA SELinux maximum supported policy format version
Default security module (SELinux) --->
Rebuild system
At this juncture, userspace needs to be rebuilt with SELinux support.
Rebuild your system with the above changes. Treat this like any other major system use flag / profile adjustment:
root #
emerge --changed-use @system @world --deep
It is important that system userspace be in a consistent state for the next step.
Once the kernel and userspace are successfully built, reboot.
Fix filesystem labeling
The system will now have the required kernel and userspace support for SELinux.
root #
restorecon -R /
Run restorecon -R against the other mount points on your system if you have, say,
/var
on a different partitionThis will ensure that every file on your system is properly labeled for SELinux.
Reboot again once this is done, as the running processes will not be running under the correct SELinux context.
Once this is done, you should see the following:
user $
id -Z
staff_u:staff_r:staff_t
user $
sestatus
SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: strict Current mode: permissive Mode from config file: permissive Policy MLS status: disabled Policy deny_unknown status: denied Max kernel policy version: 29
If that is indeed the case, proceed to Configure SELinux for further system tuning and configuration.
Installation from stage3
Currently the selinux stage3 tarball is marked as experimental and is only available for the amd64 architecture
Using the SELinux stage3 with the same process as described in the handbook will leave you with a standard hardened gentoo installation with the system built for full SELinux support.
Do not build in kernel support for SELinux at this time as the filesystem is not yet labeled.
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 because the kernel is not yet configured. This warning will vanish the moment the SELinux installation is completed.
Setting mount point 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.
To configure the /tmp mount, edit the /etc/fstab file:
# 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:
# 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
Installing a SELinux kernel
Although the default Linux kernels offer SELinux support, it is recommended to use the sys-kernel/hardened-sources package as it offers more hardening features alongside SELinux.
root #
emerge --ask sys-kernel/hardened-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 can be found.
Under "General setup"
[*] Prompt for development and/or incomplete code/drivers
[*] Auditing support
[*] Enable system-call 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
[ ] Ext2 execute in place support
<*> Ext3 journalling file system support
[ ] Default to 'data=ordered' in ext3
[*] 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
(1) NSA SELinux checkreqprot default value
[ ] NSA SELinux maximum supported policy format version
Default security module (SELinux) --->
Do not forget to set the Default security module to SELinux. Otherwise, the security=selinux
boot parameter has to be set in the bootloader configuration.
It is recommended to use PaX as well. More information on PaX within Gentoo Hardened can be found in the Hardened Gentoo PaX Quickstart Guide.
Build and install the new Linux kernel and its modules.
With the above changes made, reboot the system.
Fix filesystem labeling
The system will now have the required kernel and userspace support for SELinux.
root #
restorecon -R /
Run restorecon -R against the other mount points on your system if you have decided to setup Gentoo with, say,
/var
on a different partitionThis will ensure that every file on your system is properly labeled for SELinux.
Reboot again once this is done, as the running processes will not be running under the correct SELinux context.
Once this is done, you should see the following:
user $
id -Z
staff_u:staff_r:staff_t
user $
sestatus
SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: strict Current mode: permissive Mode from config file: permissive Policy MLS status: disabled Policy deny_unknown status: denied Max kernel policy version: 29
Configure SELinux
In the second part of the SELinux installation, we will cover post-installation configuration of a SELinux system.
Choosing a 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 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.
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).
POLICY_TYPES="strict"
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.
EXPAND ON WHAT TO DO IF A USER WANTS A DIFFERENT POLICY TYPE OR SECURITY LEVEL THAN STANDARD
make.conf settings
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. |
open_perms
|
The open_perms capability enables the SELinux permission "open" for files and file-related classes. Support for the "open" call was added a bit later than others so support was first made optional. However, the policies have matured sufficiently to have the open permission set. |
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.
Configuring the SELinux policy
The main SELinux configuration file is located at /etc/selinux/config. It needs to be edited to set two important values: SELINUX
and SELINUXTYPE
if you wish to use a different policy or enforcement style.
# 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.
SELINUX=permissive
# 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)
SELINUXTYPE=strict
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.
We will switch to enforcing later.
Set standard SELinux booleans
COULDN'T THIS BE SET IN THE GENTOO REFPOLICY AS DEFAULT SO USERS DON'T HAVE TO DO THIS?
If Gentoo is installed using the hardened sources (as is recommended), enable the SSP SELinux boolean:
root #
setsebool -P global_ssp on
SELinux booleans enable (or disable) SELinux policy rules based on the boolean value. In this case, the boolean allows every domain read access to the /dev/urandom device.
You can view what SELinux booleans, their current and default states, and what they do with the following command:
root #
semanage boolean -l
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 succesfully 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
staff_u:staff_r:staff_t
user $
newrole -r sysadm_r
Password: (Enter your password)
user $
id -Z
staff_u:sysadm_r:sysadm_t
In a targeted policy, the users will be of type unconfined_t and will already have the necessary privileges to perform system administrative tasks.
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 therefor 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.
ISN'T THIS ALREADY DONE BY DEFAULT?
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
Enable the selinux_gentoo service
IS THIS STILL NECESSARY? IT DOES NOT SEEM LIKE IT.
Gentoo provides an init script called selinux_gentoo which restores the contexts of dynamically created files and devices or pseudo file systems (/dev (optionally) and /sys) as those file systems cannot persist context changes across reboots.
The init script also supports booting in permissive mode first (for instance due to a custom initramfs that fails to work in enforcing mode) and switch to enforcing mode later.
root #
rc-update add selinux_gentoo boot
Update the boot loader configuration with one or more of the following boot options:
- nosetenforce if the system is booted with
enforcing=0
and you do not want the init script to switch back to enforcing mode (if configured in /etc/selinux/config). If /etc/selinux/config file is configured to boot in permissive mode, this init script will not change this behavior. - norestorecon if you do not want to restore the contexts of /dev.
# Boot in SELinux permissive and switch to enforcing later
# Requires /etc/selinux/config to have SELINUX=enforcing
title Gentoo Hardened/SELinux
root (hd0,0)
kernel /boot/kernel root=/dev/vg/root ... enforcing=0 ...
# Boot in SELinux permissive and stay in permissive, even if
# /etc/selinux/config has SELINUX=enforcing
title Gentoo Hardened/SELinux
root (hd0,0)
kernel /boot/kernel root=/dev/vg/root ... enforcing=0 nosetenforce ...
# Boot in SELinux permissive and switch to enforcing later
# Requires /etc/selinux/config to have SELINUX=enforcing
GRUB_CMDLINE_LINUX="enforcing=0"
# OR: Boot in SELinux permissive and stay in permissive, even if
# /etc/selinux/config has SELINUX=enforcing
GRUB_CMDLINE_LINUX="enforcing=0 nosetenforce"
Make administration easier
SELinux is difficult, and not just in the conceptual sense.
If you are willing to make some tradeoffs against system security, there are some changes that can be made that will smooth administration of a SELinux system.
Automatic root login to sysadm_r
BEST PRACTICES? I LIKE AND DO THIS BUT THIS MAY NOT BE OPTIMAL
As described previously, remote root logins require a role transition to sysadm_r in order to do administrative tasks. If you would like to have this transition automatically happen, it takes two simple steps:
- Set up the SELinux boolean that allows this
The policy default is to not allow this behavior, however there's a boolean that controls this behavior.
root #
setsebool -P ssh_sysadm_login on
- Setup the root user context to allow the transition
SSH is what sets your user up with whatever role it is configured to use, as such it needs to be told to do this.
Open up /etc/selinux/SELINUX/contexts/users/root in a text editor. It will look like the following:
system_r:crond_t unconfined_r:unconfined_t sysadm_r:cronjob_t staff_r:cronjob_t user_r:cronjob_t
system_r:local_login_t unconfined_r:unconfined_t sysadm_r:sysadm_t staff_r:staff_t user_r:user_t
staff_r:staff_su_t unconfined_r:unconfined_t sysadm_r:sysadm_t staff_r:staff_t user_r:user_t
sysadm_r:sysadm_su_t unconfined_r:unconfined_t sysadm_r:sysadm_t staff_r:staff_t user_r:user_t
user_r:user_su_t unconfined_r:unconfined_t sysadm_r:sysadm_t staff_r:staff_t user_r:user_t
#
# Uncomment if you want to automatically login as sysadm_r
#
# system_r:sshd_t unconfined_r:unconfined_t sysadm_r:sysadm_t staff_r:staff_t user_r:user_t
Uncomment the system_r:sshd_t
line.
No service or system restarts are necessary.
Warning
Do not exit your existing shell to test this, in case something went wrong. Preserving a functioning shell is good practice for making changes such as this.
To test this, login as root again and you should be able to obtain the following:
user $
id -Z
root:sysadm_r:sysadm_t
Automatic init context transition for root
When a user wants to restart a service, the user needs both the ability to execute the init script in /etc/init.d/
as well as the ability to transition to the relevant SELinux initrc context.
It always ends up going like this:
user $
run_init service sshd restart
Authenticating root.
Password:
If you do not wish to enter the root password every time you restart a service (Eg, you control access via SSH keys and keep the root password elsewhere) this is straight forward to setup.
Open /etc/pam.d/run_init
. It will look like the following:
#%PAM-1.0
# Uncomment the next line if you do not want to enter your passwd everytime
# auth sufficient pam_rootok.so
auth include system-auth
account include system-auth
password include system-auth
session include system-auth
session optional pam_xauth.so
Uncomment out the pam_rootok.so line.
No service or system restarts are necessary.
Warning
Do not exit your existing shell to test this, in case something went wrong. Preserving a functioning shell is good practice for making changes such as this.
To test this, login as root again and you should be able to obtain the following:
user $
run_init service sshd restart
Authenticating root.
* Stopping sshd ... [ ok ]
* Starting sshd ... [ ok ]
Summary
That's it. SELinux is now fully configured on the system. Although it will boot in permissive mode 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.
You can set the system to enforcing by editing /etc/selinux/config, however it is strongly suggested that you do so on a temporary basis with
root #
setenforce 1
before codifying this into the system configuration in case there are unexpected issues.