SELinux Permissions

  2019-12-30


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.

Writing Custom Modules