SELinux (Security Enhanced Linux) is a linux kernel security module that provides a mechanism for supporting access control policies. This can support the protection from tampering and bypassing threats that might be possible with certain applications. SELinux checks permissions after the usual operating system permissions (user, groups and read/write/execute policies). If the local permissions succeeds, then SELinux checks for permissions.
A Linux kernel that uses SELinux enforces mandatory access control policies that confine user programs and system services, also including file and network resources. If a program or daemon becomes compromised in an SELinux kernel space, then it is confined and limits the damage that can be caused.
SELinux users and roles do not have to be related to the actual system users and roles. For every current user or process, SELinux assigns a three string context consisting of username, role and domain (or type). This system is more flexible than normally required.
SELinux contexts follow the SELinux user:role:type:level syntax. To read more about users, roles and types, please refer to
Working with SELinux Modes
SELinux has three modes:
- Enforcing: Rules are enforced and violations are logged
- Permissive: No rule enforcement, violations logged
- Disabled: SELinux is not operational and no logging is enabled
To find out which mode the current system is in:
sestatus
You can also find out the config with:
cat /etc/selinux/config
(or, whatever SELinux root directory was identified in the previous command).
Changing any of the settings in the above file will need a restart.
To see the SELinux status of any particular file, pass the -Z
flag to ls
:
ls -Z somefile
Type:
setenforce 0
which will turn off the enforce, but a reboot means that this will be ignored and a reboot would be in enforced mode.
To change mode over a reboot edit /etc/selinux/config
:
SELINUX=permissive
Now, when you look at status, you will see that both config file and current mode are permissive.
setenforce
can only be set with enforced
or permissive
on the command line.' disabled
is allowed in the configuration file.
Controlling User Access
By default, all users are equal. User restrictions are not implemented. All users run as the unconfined_u
SELinux user, without intervention.
To create a new Linux user login and map it to an SELinux user, you can use the useradd
command with the -Z
flag:
useradd use1 -Z user_u
This will create a new Linux system user with the SELinux system rights of user_u
.
SELinux User Capabilities
The admin user pretty much has all rights.
| User | X-Windows | su/sudo | Execute /tmp ~ | Networking | |———————————————————– | sysadm_u | yes | both | yes | yes | | staff_u | yes | sudo | yes | yes | | user_u | yes | no | yes | yes | | guest_u | no | no | no | no | | xguest_u | yes | no | no | Firefox |
staff_u
can do everything apart from su
(but can sudo
). user_u
can do everything apart from root escalation rights. guest_u
can do nothing. xguest_u
can use Firefox as the only command process that uses networking.
To see what user we are use:
id -Z
Usually, on a default install, a user is unconfined_u
.
To see the users for SELinux type:
semanage user -l
To list the changes that are still locally applied (not yet in the config):
semanage login -C -l
Linux user accounts are mapped to SELinux users. We can use the login
option to list out these mappings:
semanage login -l
will give the output:
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s0:c0.c1023 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
showing that __default__
is unconfined_u
. This means there are no restrictions in place to any new accounts that are added to this machine. It is a good idea to stop this behaviour and change the __default__
to user_u
privileges.
Changing the default assignment will also affect all users previously assigned to it. To manage the assignment of an existing user with semanage
.
semanage login -m -s "user_u" -r s0 __default__
Now if you check your SELinux users, you will see that __default__
is now assigned to the user_u
:
Login Name SELinux User MLS/MCS Range Service
__default__ user_u s0 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
NOTE: This will stop all users from gaining su
and sudo
access.
To change this for a particular user:
semanage login -a -s unconfined_u lisa
This command means that lisa will now once again be able to gain root access.
To list SELinux users we use the user option:
semanage user -l
The task is to assign linux accounts to SELinux accounts. We can use the -Z
option to useradd or modify the default assignment, which will affect new accounts.
useradd -Z guest_u bob
To change this later:
semanage login -a -s user_u bob
The two commands above firstly create a user bob and assign him to the guest_u user, and then the second command associates the username bob
with the user_u
SELinux user.
Type Enforcement Rules
A processes type (e.g. httpd_t
) must have access to the objects type (e.g. httpd_sys_content_t
). If this rule does not exist, then the process will not be able to access the files it needs (in this case the process httpd cannot access the html files that it needs to serve for requests).
To find out how many allow rules there are issue:
seinfo
To see a specific rule:
sesearch --allow -s httpd_t -t httpd_sys_content_t
The processes for httpd are running as follows:
ps -Zp $(pgrep http)
LABEL PID TTY STAT TIME COMMAND
system_u:system_r:httpd_t:s0 1407 ? Ss 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 1408 ? S 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 1409 ? S 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 1410 ? S 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 1411 ? S 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 1412 ? S 0:00 /usr/sbin/httpd -DFOREGROUND
The files that are within the website for httpd to serve have the following SELinux attributes:
ls -Zd /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html
The specific rules for httpd are:
sesearch --allow -s httpd_t -t httpd_sys_content_t
Found 29 semantic av rules:
allow httpd_t httpd_sys_content_t : lnk_file { read getattr } ;
allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search open } ;
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock map open } ;
allow httpd_t httpd_content_type : file { ioctl read getattr lock map open } ;
allow httpd_t httpd_content_type : dir { getattr search open } ;
allow httpd_t file_type : dir { getattr search open } ;
allow httpd_t file_type : filesystem getattr ;
allow daemon httpd_sys_content_t : dir { getattr search open } ;
allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow httpd_t httpdcontent : file { ioctl read getattr map execute execute_no_trans open } ;
allow httpd_t httpd_sys_content_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow domain file_type : lnk_file map ;
allow httpd_t httpd_content_type : lnk_file { read getattr } ;
allow domain file_type : file map ;
allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
allow domain file_type : chr_file map ;
allow httpd_t httpd_content_type : dir { getattr search open } ;
allow httpd_t httpd_content_type : dir { getattr search open } ;
allow httpd_t httpd_content_type : dir { ioctl read getattr lock search open } ;
allow httpd_t httpd_content_type : dir { getattr search open } ;
allow domain file_type : blk_file map ;
allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow httpd_t httpdcontent : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow httpd_t httpdcontent : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow httpd_t httpdcontent : lnk_file { ioctl read write create getattr setattr lock append unlink link rename } ;
What about changing the directory /var/www/html
for the httpd server? This is where the semanage-fcontext
command will come in.
semanage fcontext -a -t httpd_sys_content_t "/srvhttpd"
restorecon -R -v /srvhttpd
The restorecon
command is important as this will persistently set the directory across reboots.
Configure httpd server to access a /srvhttpd directory. Then create the /srvhttpd directory:
mkdir -m 2750 /srvhttpd
chgrp apache /srvhttpd
echo hello > /srvhttpd/index.html
semanage fcontext -a -t httpd_sys_content_t /srvhttpd
restorecon -R -v /srvhttpd
Working with Booleans
Administrators can override SELinux enforced mode to get around problems. This can be a problem when you are trying to prevent opening up access. This can be prevented by requiring a reboot before a new mode is active. To do this you will need to set a boolean which prevents changing the mode without a reboot.
getsebool -a
will show all the booleans that are in place for this runtime. The same can be achieved with:
semanage boolean -l | grep secure_mode_policyload
To change this:
setsebool secure_mode_policyload on
getsebool -a |grep policy
The latter command confirms that the boolean is on.
If you want the boolean to take place over a reboot:
setsebool -P secure_mode_policyload on
The -P
sets this to be transient over a reboot.
To find out which booleans are available on your system enter:
semanange boolean -l
To get more detailed descriptions of the booleans, install the package selinux-policy-devel
package.
By default, Apache is prevented from accessing any DB servers. The httpd_can_network_connect_db
is off. To checkk this:
getsebool httpd_can_network_connect_db
To temporarily enable this:
setsebool httpd_can_network_connect_db on
This change is not persistent across reboots. To make a change that is persistent across reboots, use the -P
flag:
setsebool -P httpd_can_network_connect_db on
Diagnosing SELinux Issues
You can pass enforcing=0
on a grub command line (the line that loads the kernel) to change to permissive mode. This helps if there is difficulty in logging in. If necessary, this means that you can check the permissions of any files that may have changed.
This may require a file to be created /.autorelabel
, which will check through all the files and ensure that they are all relabeled according to the SELinux policies in place. Relabelling all the files can be time consuming and there is a quicker way by just relabelling the necessary files.
If you find a question mark on ls -Z file
then the file is unlabelled and cannot be verified by SELinux. To fix this:
restorecon -v filename
This will bring the label to the file. The restorecon
command is good for relabelling just one file, instead of having to go through the whole filesytem.