This blog post is originally written by Srinivas Gowda G from Dell Linux Engineering group.
Dell recently announced support for RHEL7 on Dell PowerEdge Servers. As is the case with any SELinux (Security Enhanced Linux) enabled OS, your applications might hit SELinux surprises with RHEL7. Applications that ran perfectly well on RHEL6 might now complain about SELinux denials in RHEL7. Most of the time when faced with SELinux issues the first temptation is to disable SELinux or switch to Permissive mode. Not the best thing to do!!! .
In this article I intend to give an overview of SELinux architecture, demonstrate usage of some of the SELinux utilities available as part of RHEL7 and a few pointers on how best to deal with SELinux denials. SELinux provides an excellent Access Control Mechanism built into Linux. It was originally developed by US National Security Agency but is now part of various Linux distributions including RHEL7 providing enhanced security to Linux operating systems.
Most Linux users are familiar with DAC (Discretionary Access Control), the various degrees of permission levels that can be assigned to files in Linux as shown in this quick example:
$ ls -l foo
-r-xr-xr-x 1 test testgroup 112 Oct 3 2013 foo.txt
SELinux implements Mandatory Access Control (MAC) over the existing DAC. In DAC the owner of the object specifies which subjects can access the object. Say for the above file foo, you want to give read and write permission to all the users and groups, and also in addition provide execution permission to user “test”. We can use chmod command to provide these permissions
$ chmod 766 foo
$ ls -l foo
-rwxrw-rw- 1 test testgroup 112 Oct 3 2014 foo.txt
As we see in DAC, control of access to files is based on the discretion of the owner. Access is controlled based on Linux user and group IDs.
One of the important file in the configuration space is /etc/selinux file, here is a sample output of the default setting you might find in RHEL7
# 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.
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
To make persistent changes of SELinux status or protection type (MLS/targeted) you must first edit the /etc/selinux configuration file and restart the operating system.
By default RHEL7 enables SELINUX in enforcing mode and SELINUXTYPE is targeted. There are good numbers of utilities that can be used to play around SELinux; I’ll try to cover as much as possible in this blog and restrict myself with the default “targeted” policy.
sestatus utility can be used to check the current status of SELinux on your RHEL7 system.
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
setenforce can be used to change the selinux mode in a non-persistent way.
usage: setenforce [ Enforcing | Permissive | 1 | 0 ]
Similarly getenforce utility can be used to get the status of SELinux
Each file, users and process on a SELinux enabled system has a Security label called context associate with it. Here are some examples of how you can check the context of a file, process or users
If I were to look at the SELinux context of /bin then you can use ls -dZ or you can prefer to use secon which is more descriptive.
$ secon -f /bin/
In this example we have a file myFile for which SELinux provides a user (unconfined_u), a role (object_r), a type (user_home_t), and a level (s0) and it is this information that are used to make the access control decision in SELinux.
$ ls -Z myFile
-rw-rw-r--. user1 group1 unconfined_u:object_r:user_home_t:s0 file1
Similarly for a process whose PID is 3161 you can check the SELinux context
$ secon -p 3161 ( or use ps –eZ)
sestatus and secon is part of policycoreutils package. To list SELinux confined users
$ semanage user -l
Labeling MLS/ MLS/
SELinux User Prefix MCS Level MCS Range SELinux Roles
guest_u user s0 s0 guest_r
root user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
staff_u user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
sysadm_u user s0 s0-s0:c0.c1023 sysadm_r
system_u user s0 s0-s0:c0.c1023 system_r unconfined_r
unconfined_u user s0 s0-s0:c0.c1023 system_r unconfined_r
user_u user s0 s0 user_r
xguest_u user s0 s0 xguest_r
semanage login -l gives the mapping between SElinux and linux users
$ semanage login -l
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 *
The default SELinux policy used in RHEL7 is "Targeted Policy". In targeted policy, type translates to a domain for a process and type for a file. An executable of type_t transitions to a domain domain_t as defined by Entry point permissions defined in policy tables. If you wish to change security labels then you can do so by using chcon or semanage utility. Changes made using chcon is not persistent and is lost when file systems are relabeled. If you are dealing with SELinux related issues it is very important that you know how to set correct or appropriate context to files and directories. This will help you solve majority of SELinux denials.
The following example tries to demonstrate these steps. I have a user “linux” whose home directory has a folder called Music already present
# Directory Music has type audio_home_t
$ ls -dZ
drwxr-xr-x. linux linux unconfined_u:object_r:audio_home_t:s0 Music
# Now I will create a dummy file file1 inside "Music" folder and check the context of this new file.
$ touch Music/file1
$ ls -dZ Music/
-rw-rw-r--. linux linux unconfined_u:object_r:audio_home_t:s0 file1
# Let’s use chcon to relabel security label type of directory "Music" from audio_home_t to admin_home_t
$ chcon -t admin_home_t Music
drwxr-xr-x. linux linux unconfined_u:object_r:admin_home_t:s0 Music
#Now that we have relabeled, lets create file2 inside "Music"
$ touch Music/file2
#unlike file1 which had "audio_home_t" , we now see that the file2 is labeled as "admin_home_t" which is same as its parent directory
$ ls -Z Music/
-rw-rw-r--. linux linux unconfined_u:object_r:admin_home_t:s0 file2
restorecon is a SELinux utility that is mainly used to reset the security context of files or directories. It only modifies type portion of the security context of objects with preexisting labels.
# Restore files to default SELinux security contexts. All the previous changes will be reverted.
$ restorecon -R .
# We now can see that both Music and files inside this directory are relabeled to the default values.
-rw-rw-r--. linux linux unconfined_u:object_r:audio_home_t:s0 file1
-rw-rw-r--. linux linux unconfined_u:object_r:audio_home_t:s0 file2
You can’t relabel files with arbitrary types.
$ chcon -t dummy_type_t Music/file1
chcon: failed to change context of Music/file1 to unconfined_u:object_r:dummy_type_t:s0 : Invalid argument
However new types can be created by writing new policy rules.
If you are wondering how to validate the correctness of security context of objects then refer to matchpathcon utility. matchpathcon utility can be used to check the default security context associated with a file. matchpathcon queries the system policy to find out the correct context to files and reports the same.
$ matchpathcon -V /home/linux/Music/file2
/home/linux/Music/file1 has context unconfined_u:object_r:admin_home_t:s0, should be unconfined_u:object_r:audio_home_t:s0
By now you must be wondering where these context rules are defined. In RHEL7 /etc/selinux/targeted/contexts is where the context of all the files is defined.
As we have seen, changes made via chcon are not persistent. Non default changes made via chcon can be reverted using restorecon utility. semanage fcontext command is used to persistently set the context of files. Similar to the example above let’s try to change the context of a file, but this time let’s do a persistent change.
# Lets create a folder called config under /root
$ mkdir config
# By default policy labels the directory as admin_home_t
$ ls -Zd config/
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 config/
# Lets relabel to config_home_t
$ chcon -t config_home_t config/
# As expected matchpatcon complains about the wrong context because default policy for config directory under /root must be admin_home_t
$ matchpathcon -V config/
config has context unconfined_u:object_r:config_home_t:s0, should be system_u:object_r:admin_home_t:s0
# Using restorecon the context reverts back to the default target label as defined by the policies
$ restorecon -v config/
$ restorecon reset /root/config context unconfined_u:object_r:config_home_t:s0->unconfined_u:object_r:admin_home_t:s0
# Now let’s write a new security context rule that will relabel "config" folder under root to config_home_t
$ semanage fcontext -a -t config_home_t "/root/config"
$ restorecon -R -v .
restorecon reset /root/config context unconfined_u:object_r:admin_home_t:s0->unconfined_u:object_r:config_home_t:s0
drwxr-xr-x. root root unconfined_u:object_r:config_home_t:s0 config/
# Let`s create files under /root/config/ folder and check its context
$ touch foo1
$ touch foo2.config
# Here foo1 and foo2.config seems to inherit the context as its parent directory
$ ls -Z config/*
-rw-r--r--. root root unconfined_u:object_r:config_home_t:s0 config/foo1
-rw-r--r--. root root unconfined_u:object_r:config_home_t:s0 config/foo2.config
# Let’s say I want only files inside /root/config with .config extension to have security context as config_home_t
$ semanage fcontext -a-a -t config_home_t "/root/config(/.*\.config)"
restorecon reset /root/config/foo1 context unconfined_u:object_r:config_home_t:s0->unconfined_u:object_r:admin_home_t:s0
$ ls -Z config/
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 foo1
-rw-r--r--. root root unconfined_u:object_r:config_home_t:s0 foo2.config
You must be able to find all these new rules added under "file_contexts.local"
$ cat /etc/selinux/targeted/contexts/files/file_contexts.local
# This file is auto-generated by libsemanage
# Do not edit directly.
Now that we have managed to modify the security context of files let’s move on to the other most useful technique to solve SELinux denials.
SELinux provides a set of Booleans that helps change some of the SELinux policies. semanage boolean -l lists SELinux policies that can be changed at run time. Booleans are pretty useful since changes can be made easily without writing policies.
getsebool -a is used to list the current status of the these Booleans, setsebool can be used change the status of the available Booleans
$ getsebool puppetmaster_use_db
puppetmaster_use_db --> off
$ setsebool -P puppetmaster_use_db on
puppetmaster_use_db --> on
-P flag make these settings to be persistent across reboots.
If you are interested to know all the existing SELinux rules on your system then there is utility called sesearch which helps you find that(use --all to list all the rules). sesearch is part of setools-console package which contains other useful utilities such as findcon, seinfo etc..
Access Vector Cache (AVC)
SElinux policies are always evolving, new rules might get added while old ones may get refined or removed. This invariably means SELinux denying access to some operations of your application. These denials are usually referred as AVC denials.
SELinux uses a cache called Access Vector Cache (AVC) that caches all the successful and failure access. These AVC denials are usually logged in /var/log/audit/audit.log, they can also be logged in system logs but it depends on which demons are running (auditd, rsyslogd, setroubleshootd). In an X windows system if you have setroubleshootd and auditd running, then a warning message is displayed on the console. If you do not have a GUI console, then you can either use ausearch which is part of audit package or inspect the audit.log or system log using good old “grep”.
SELinux provides an easy way to fix the denials using audit2allow. This is a pretty helpful utility that generates SELinux policy using the audit logs and get rid of the denials. But using this is something that you want to avoid if you are not sure about the policies are being added. Most of the denials can be dealt by either changing the context of files in conflict or enabling the available Booleans. If these two changes don’t take care of your denials then care must be taken before you start adding new policies.
Some of the RHEL7 features such as systemd will trigger changes in security context of your applications in RHEL7, care must be taken by application owners when developing or porting applications to RHEL7. It’s important to understand the context transition of process and files. “sepolicy transition” command can be used to generate a process transition report. RHEL7 has addressed some of the File name transition issues of SELinux. If you are looking for more detailed information of SELinux on RHEL7 then refer to SELinux_Users_and_Administrators_Guide , and this document also provides an overview of new SELinux features in RHEL7.