SELinux overview

This post summarizes SELinux documentation, some publicly available articles and presentations, and part of Linux Advanced Security course that I had attended at the Faculty of Electrical Engineering Education Center in Belgrade two years ago.


Linux implements discretionary access control. The controls are discretionary (you can change these at your discretion) in the sense that a subject is capable of transferring permissions to other subjects – for example, a process can change security properties of resources. Main features of this traditional access control in Linux are:

  • processes are running under UID and GID (real and effective)
  • object access is based on ownership and permissions
  • users define access control for their objects

The kernel has hard-coded access policy. The main problem is that the access is based on users’ access. Kernel can’t distinguish users from processes. For example, a compromised web browser can read all of the user’s files, including ssh private keys!  A compromised email client can make the users email files world readable. Furthermore, root user can bypass all the restrictions and it’s not easy to set minimum privileges.

To address these problems NSA initially developed SELinux (Security-Enchanced Linux) which is a set of kernel modifications to provide mandatory access control to Linux. SELinux is now developed mostly by RedHat (Dan Walsh is the lead SELinux developer).

So basically SELinux provides an additional security layer:

  • processes and resources have new security contexts
  • policy defines relationship between those contexts
  • users can’t bypass the policy

Features of SELinux are:

  • it is mandatory
  • it is modular
  • it is granular
  • there is a possibility to define minimum privileges
  • root isn’t almighty
  • it is transparent for applications

Benefits of SELinux are:

  • access is based on user and application function
  • processes run with least-privilege
  • privilege escalation tightly controlled (compromise of Apache is limited by the policy)

Three forms of access control

There are 3 forms of access control:

  1. Type enforcement (primary mechanism)
  2. Role-based access control
  3. Multi-level security

Access control is configurable via policy language (targeted, strict, mls). SELinux follows the model of least-privilege: access is denied by default.

Type enforcement overview

Security contexts are stored in extended file system attributes (xattr, metadata). Security context is assigned by labeling of the file system. Look at the following security contexts for httpd process and /var/www/html directory:

$ sudo ps -Z -C httpd | head -2
LABEL                             PID TTY          TIME CMD
system_u:system_r:httpd_t:s0     1404 ?        00:00:00 httpd
$ sudo ls -dZ /var/www/html/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/

‘system_u:system_r:httpd_t:s0’ and ‘system_u:object_r:httpd_sys_content_t:s0’ are security contexts. The fields represent user:role:type:level respectively. For type enforcement the key field is type. Access is allowed solely by type. The policy defines that httpd_t can read httpd_sys_content_t, while everything else is denied.

Files and directories are assigned type by the configuration file which specifies default context. New files in folders inherit the security contexts of directories. Process types are inherited from the parent process or are set by policy (type transition rule) or by application. Transition must be allowed by policy – e.g. apache cannot start processes in init_t.

Targeted policy

Targeted policy is default in RHEL. It is important to have in mind that with targeted policy processes are unconfined by default – the policy confines only targeted services. Unconfined processes behave almost the same as SELinux is disabled. By default user processes run in unconfined_t, while system processes run in initrc_t domain. Transition of unconfined_t into the type that is defined by the policy is automatic upon starting up of the process.

SELinux configuration

SELinux stores its configuration files in /etc/selinux:

$ ls -l /etc/selinux/
total 20
-rw-r--r--. 1 root root  449 Apr 28 19:05 config
-rw-r--r--. 1 root root  113 Feb 14 21:49 restorecond.conf
-rw-r--r--. 1 root root   76 Feb 14 21:49 restorecond_user.conf
-rw-r--r--. 1 root root 1766 Dec  7 23:44 semanage.conf
drwxr-xr-x. 5 root root 4096 Apr 28 19:11 targeted

/etc/selinux/config defines enforcing mode and policy type and /etc/sysconfig/selinux is a symlink to this file on RHEL systems. /etc/selinux/targeted directory contains targeted policies and following subdirectories:

  • contexts – object context definitions
  • modules – modules used to build the policy
  • policy – compiled (binary) policy file

The /etc/selinux/targeted/contexts/files includes the following:

  • file_contexts – basic contexts
  • file_contexts.local – local rewrites of contexts
  • file_contexts.homedir – user files
  • media – removable devices

There are man pages for SELinux policy documentation for several confined services:

$ man -k _selinux
abrt_selinux         (8)  - Security-Enhanced Linux Policy for the ABRT daemon
ftpd_selinux         (8)  - Security-Enhanced Linux policy for ftp daemons
git_selinux          (8)  - Security Enhanced Linux Policy for the Git daemon
httpd_selinux        (8)  - Security Enhanced Linux Policy for the httpd daemon
kerberos_selinux     (8)  - Security Enhanced Linux Policy for Kerberos
mysql_selinux        (8)  - Security-Enhanced Linux Policy for the MySQL daemon
named_selinux        (8)  - Security Enhanced Linux Policy for the Internet Name server (named) daemon
nfs_selinux          (8)  - Security Enhanced Linux Policy for NFS
pam_selinux          (8)  - PAM module to set the default security context
rsync_selinux        (8)  - Security Enhanced Linux Policy for the rsync daemon
samba_selinux        (8)  - Security Enhanced Linux Policy for Samba
squid_selinux        (8)  - Security-Enhanced Linux Policy for the squid daemon
ypbind_selinux       (8)  - Security Enhanced Linux Policy for NIS

Packages and utilities

Several standard utilities are modified to support SELinux:

  • ls -Z
  • id -Z
  • ps auxZ
  • lsof -Z
  • netstat -Z
  • find / -context

Other modified programs are:

  • Login programs, PAM (sshd, login, xdm)
  • Password utilites (passwd, useradd, groupadd)
  • rpm

Backup and disk management support:

  • tar, zip (both have extended attribute support)
  • rsync (-X, -xattrs)
  • star
  • amanda
  • tar –selinux
  • tar xv | restorecon -f – (good option)

libselinux package:

  • getenforce – check whether machine is enforcing or permissive
  • setenfroce 1/0 – sets the machine in enforcing/permissive
  • selinuxenabled – used in scripts
  • matchpathcon – shows the default context of file/directory
  • avcstat – display SELinux AVC statistics

coreutils package:

  • chcon – changes security context of the file

policycoreutils package:

  • sestatus – shows SELinux status
  • semodule – loads the module into the policy
  • setsebool – sets booleans
  • genhomedircon – generates file_contexts. homedir
  • setfiles – executes initial file system labeling
  • restorecon – sets default context defined by the policy
  • fixfiles – correct contexts database on file systems

checkpolicy package:

  • checkmodule – compiles module
  • checkpolicy – compiles policy

policycoreutils-python package:

  • semanage – makes queries and changes the policy
  • audit2allow – generates the rules based on activity logs

policycoreutils-gui package:

  • system-config-selinux – SELinux administration
  • selinux-polgengui – wizard for making new policies

setroubleshoot  and setroubleshoot-server packages:

  • setroubleshootd – searches and processes AVC messages
  • sealert – shows description of AVC messages
  • seapplet – pops SELinux realted messages to the user in X

File labeling

File context can be changed with the fundamental utility chcon (which is similar to chmod):

$ chcon -R -t httpd_sys_content_t /srv/www

This change will be active until next relabeling. restorecon command sets contexts that are defined by policy rules. If there is /.autorelabel file, the file system will be relabeled during the next system boot. To make the change permanent use semanage utility to set the context.

The policy defines contexts in /etc/selinux/targeted/contexts/files/file_contexts file, by using regular expressions to indicate the paths. “–” in the second column indicates regular files, “-d”directories, “-b” block devices, “-c” character devices, “-l” links, etc. Special context “<<none>>” indicates that the context should not be changed.

Log files

SELinux messages are in the form of AVC – access vector cache. You can usually find them in /var/log/messages or /var/log/audit/audit.log (if auditd is running):

May  1 19:46:55 www kernel: type=1400 audit(1335901615.836:28093): avc:  denied  { open } for  pid=13595 comm="clamscan" name="parts" dev=xvdj ino=7823 scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=dir
May  1 19:46:55 www kernel: type=1400 audit(1335901615.837:28094): avc:  denied  { getattr } for  pid=13595 comm="clamscan" path="/var/amavis/tmp/amavis-20120501T141957-11544/parts/p002" dev=xvdj ino=7822 scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=file
May  1 19:46:55 www kernel: type=1400 audit(1335901615.837:28095): avc:  denied  { read } for  pid=13595 comm="clamscan" name="p002" dev=xvdj ino=7822 scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=file
May  1 19:46:55 www kernel: type=1400 audit(1335901615.837:28096): avc:  denied  { open } for  pid=13595 comm="clamscan" name="p002" dev=xvdj ino=7822 scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=file
May  1 19:46:55 www kernel: type=1400 audit(1335901615.868:28097): avc:  denied  { write } for  pid=13595 comm="clamscan" name="tmp" dev=xvdj ino=7515 scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=dir
May  1 19:46:55 www kernel: type=1400 audit(1335901615.868:28098): avc:  denied  { add_name } for  pid=13595 comm="clamscan" name="clamav-2e86f23064829c5cae67d7e8bc85d569" scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=dir
May  1 19:46:55 www kernel: type=1400 audit(1335901615.868:28099): avc:  denied  { create } for  pid=13595 comm="clamscan" name="clamav-2e86f23064829c5cae67d7e8bc85d569" scontext=system_u:system_r:clamscan_t:s0 tcontext=system_u:object_r:amavis_var_lib_t:s0 tclass=dir

AVC messages appear because of the:

  • mislabeled files (file_t, default_t, mv’ed files, solution: restorecon)
  • process running under the wrong context
  • bug in policy
  • intrusion

Explanation of AVC messages can be shown by using the sealert command. If you don’t have the sealert command, install the following package:

$ sudo yum install setroubleshoot-server

setroubleshootd analyzes the log messages and can send email alerts. The configuration for it is at /etc/setroubleshoot/setroubleshoot.conf. sealert is a setroubleshoot client that is used to diagnose SELinux denials and attempts to provide user friendly explanations and recommendations for how one might adjust the system to prevent the denial in the future.

AVC messages could also be suppressed by the policy rule dontaudit. Sometimes this could be problematic when troubleshooting and to disable dontaudit rules run the following command:

$ sudo semanage dontaudit off

Another useful tools for troubleshooting log files can be found in policycoreutils-python package. audit2allow generates policy allow rules from logs of denied operations. Let’s see whats the problem with clamscan on my system:

$ sudo grep clamscan /var/log/messages | audit2allow 

#============= clamscan_t ==============
#!!!! The source type 'clamscan_t' can write to a 'dir' of the following type:
# clamscan_tmp_t

allow clamscan_t amavis_var_lib_t:dir { write search read create open getattr add_name };
allow clamscan_t amavis_var_lib_t:file { read getattr open };

This tells me that clamav policy is missing allow rules for allowing clamscan to access amavis’ directory to scan the files. I will use this specification to compile policy module:

$ sudo grep clamscan /var/log/messages | audit2allow -M clamscan
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i clamscan.pp

audit2allow created type enforcement file clamscan.te and clamscan.pp policy package. Next step involves loading the policy package file:

$ sudo semodule -vi clamscan.pp
Attempting to install module 'clamscan.pp':
Ok: return value of 0.
Committing changes:

Whoops what was that? It turns out that the kernel killed the process because it made the system ran out of memory:

May  2 12:56:57 www kernel: Out of memory: Kill process 3375 (semodule) score 312 or sacrifice child
May  2 12:56:57 www kernel: Killed process 3375, UID 0, (semodule) total-vm:309008kB, anon-rss:292076kB, file-rss:104kB

I freed some of the reserved memory and compiled the module successfully:

$ sudo semodule -l | grep clamscan
clamscan	1.0

This change is permanent and survives a restart. If I ever wanted to remove that policy I would execute the following:

$ sudo semodule -r clamscan

Policy customization

Policies usually have booleans associated that enable run time customization of the policy. Booleans are if/then/else statements in the policy.

  • getsebool – shows variable value
  • togglesebool – changes variable value
  • setsebool – by using -P parameter you can change the value permanently

Remember to check the particular policy man page for variables description.

semanage utility is pretty important and it can list and change policy parameters:

  • semanage user -l — list SELinux users
  • semanage port -l –list SELinux ports
  • semanage fcontext -a -t httpd_sys_content_t “/web(/.*)?” — allow Apache to serve content from /web
  • semanage port -a -t http_port_t -p tcp 81 — allow Apache to listen on non-standard port 81
  • semanage permissive -a httpd_t — disable httpd protection
  • semanage permissive -d httpd_t — enable httpd protection


Comments are closed.