SELinux
Installation
Kernel support:
CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_AVC_STATS=y CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set CONFIG_DEFAULT_SECURITY_SELINUX=y CONFIG_DEFAULT_SECURITY="selinux"
Debian
A short summary of Debian's setup manual[1]
apt-get install auditd checkpolicy policycoreutils selinux-basics selinux-utils # Debian, Ubuntu
Configure GRUB and PAM and create an /.autorelabel
file:
selinux-activate
After rebooting the machine, run check-selinux-installation
to verify if everything is setup correctly.
Fedora
yum install policycoreutils policycoreutils-python audit checkpolicy # Fedora systemctl enable auditd.service systemctl start auditd.service
SELinux prevented gdm-session-wor from reading and writing files stored on an NFS filesytem.
Fix Command:
sudo setsebool -P use_nfs_home_dirs=1
SELinux is preventing /usr/sbin/prelink "setattr" access . [prelink has a permissive type (prelink_t). This access was not denied.] Allowing Access: You can generate a local policy module to allow this access - see FAQ (https://docs.fedoraproject.org/selinux-faq-fc5/#id2961385) Please file a bug report.
SELinux is preventing /sbin/cachefilesd "create_files_as" access . $ grep ^dir /etc/cachefilesd.conf dir /var/cache/fscache sudo mkdir -m0700 /var/cache/fscache sudo mount -o remount,user_xattr /
Note: user_xattr
is now the default for ext4
filesystems.[2]
For debugging purposes, we can disable SELinux too:
- Boot with
selinux=0
- Boot with
enforcing=0
(permissive) - Set
SELINUX=disabled
(resp.permissive
) in/etc/selinux/config
and reboot.
Allow the Adobe Flash plugin:[3]
sudo setsebool -P unconfined_mozilla_plugin_transition 0
Configuration
When booting, SELinux can be enabled/disabled with the following boot options:
security=selinux # Choose SELinux as the security module selinux=1 # Use 0 to disable SELinux enforcing=1 # Use 0 to enable permissive mode
When enabled, /etc/selinux/config
is evaluated during bootup:
SELINUX=permissive # enforcing, permissive, disabled SELINUXTYPE=default # default, mls, src SETLOCALDEFS=0 # (don't) check for local definition changes
To check if SELinux is enabled:
$ selinuxenabled; echo $? 0 # 0: enabled, 1: not enabled
$ getenforce Permissive # Enforcing, Permissive, Disabled $ setenforce Enforcing # Enforcing, Permissive
View/set SELinux boolean values:
$ getsebool -a [...] $ setsebook user_ping on $ getsebool user_ping user_ping --> on
Usage
Quick Start
While still in permissive mode, look out for AVC (Access Vector Cache) messages in /var/log/audit/audit.log
. We're going to produce a local policy manually.
audit2allow --dmesg -M local_dmesg audit2allow --boot -M local_boot semodule -v -i local_dmesg.pp semodule -v -i local_boot.pp
Details
Depending on the distribution support, there will be base policies available to allow certain kinds of programs:
$ semodule -l | head -3 apache 2.2.0 apm 1.11.0 clamav 1.8.0
SELinux has strong support in RedHat & Fedora and only basic support in Debian or Ubuntu based distributions:
fedora$ semodule -l | wc -l 382 debian$ semodule -l | wc -l 48
Considering the vast amount of different applications out there, we may have to adjust the basic rulesets and create a local policy file. Let's print out all violations that occured since the last reboot but are only present in dmesg
, as auditd
was not yet running:
$ audit2allow --dmesg --module local module local 1.0; require { type udev_t; type modules_conf_t; class file read; } allow udev_t modules_conf_t:file read; [...]
Print out all violations that occured since the last reboot and were logged by auditd
:
$ audit2allow --boot --module local module local 1.0; require { type spamd_var_lib_t; type gpg_t; [...] class dir { read search create }; } #============= gpg_t ============== allow gpg_t crond_tmp_t:dir search; allow gpg_t spamd_var_lib_t:dir search;
FIXME: the --boot
and --dmesg
options cannot be combined but we have to somehow merge both policy files into one. Doing that manually is error prone and leads to duplicate statements that could be consolidated[4] easily. I.e. instead of writing
allow httpd_t user_home_t:dir getattr; allow httpd_t user_home_t:dir search;
one could write:
allow httpd_t user_home_t:dir { getattr search };
Let's look which actions got denied so far:
$ ausearch --interpret --success no | awk '/avc.*denied/ {print $12}' | sort | uniq -c | sort -n 1 comm=master 2 comm=pam-tmpdir-help 4 comm=grep 8 comm=rsync 12 comm=lighttpd 14 comm=gpg
We'll build a local policy for the rsync process:
$ grep -h "avc: denied" /var/log/audit/audit.log* | grep /usr/bin/perl | audit2allow -m local_munin > local_munin.te
If the AVC message has been logged to syslog
(because auditd
was not running), we have to decode the alert first.
$ awk '/For complete SELinux/ {print $9 " " $NF}' messages | sort | uniq -c | sort -n
463 /usr/bin/python2.7 780716dc-31dd-45d8-8482-f4e8f9006609
10790 /usr/bin/perl 72981dad-8665-4fcf-b588-a2f1d0a89234
36336 /usr/sbin/httpd e9762990-cfbf-4456-8579-880ef364e001
$ grep e9762990-cfbf-4456-8579-880ef364e001 messages | tail -1
Oct 20 00:30:47 len setroubleshoot: SELinux is preventing /usr/bin/perl from write access on the directory
/var/lib/munin/plugin-state. For complete SELinux messages. run sealert -l 72981dad-8665-4fcf-b588-a2f1d0a89234
Create a local policy file from this alert (using "munin" as the policy name):
$ sealert -l 72981dad-8665-4fcf-b588-a2f1d0a89234 | audit2allow -m local_munin > local_munin.te
These .te files ("Type Enforcement") are fairly readable, be sure to check them before using them in the following steps. Also, there's usually no way to go back from a .pp
or .mod
file to a .te
file so it's best to keep them around.[5]
Continuing from the munin issue above, we can syntactically check local_munin.te
and convert it into a .mod file ("Policy Module"):
$ checkmodule -M -m local_munin.te -o local_munin.mod checkmodule: loading policy configuration from local_munin.te checkmodule: policy configuration loaded checkmodule: writing binary representation (version 14) to local_munin.mod
...and generate a .pp file ("Policy Package") from it:
$ semodule_package -m local_munin.mod -o local_munin.pp
And finally load the package file:
$ semodule -v -i local_munin.pp
Or, without the checkmodule call:
$ sealert -l 72981dad-8665-4fcf-b588-a2f1d0a89234 | audit2allow -M local_munin $ semodule -i local_munin.pp
The semodule
program will load the module into the kernel and will take quite some time and memory to complete. If successful, we see something like this:
$ semodule -l | grep local_ local_munin 1.0
This module is now loaded permanently across reboots.
To remove the module:
$ semodule -r local_munin
Applications
httpd
Allow httpd
to query databases via PHP:[6]
setsebool -P httpd_can_network_connect_db on
Enable homedirs like ~user
to be served from the webserver:
setsebool -P httpd_enable_homedirs on
clamd
The ClamAV daemon wouldn't start properly:
Starting ClamAV daemon: clamd LibClamAV Warning: RWX mapping denied: Can't allocate RWX Memory: Permission denied LibClamAV Warning: Bytecode: disabling JIT because SELinux is preventing 'execmem' access. Run 'setsebool -P clamd_use_jit on'.
dovecot
Dovecot wants to read /etc/shadow
- but an SELinux policy trying to allow this is running into a constraint[7]:
libsepol.check_assertion_helper: assertion on line 0 violated by allow dovecot_t shadow_t:file { read } and Expand module failed
As a workaround, we can set the can_read_shadow_passwords
attribute:
require { attribute can_read_shadow_passwords; } typeattribute dovecot_t can_read_shadow_passwords; allow dovecot_t shadow_t:file { read getattr open };
Samba
$ cat /etc/samba/smb.conf [global] security = share [public] path = /mnt/foo writable = yes guest ok = yes
Prepare and start:
sudo mkdir /mnt/foo sudo chcon -t samba_share_t /mnt/foo sudo setsebool -P samba_export_all_ro on sudo systemctl start smbd
Tools
A few tools have already been mentioned above, let's recap and add some more:
$ sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: default Current mode: enforcing Mode from config file: enforcing Policy MLS status: enabled Policy deny_unknown status: denied Max kernel policy version: 29
Check if SELinux is enabled:
$ selinuxenabled; echo $? 0
Check if SELinux is in "permissive" or "enforcing" mode:
$ getenforce # Use setenforce to change the mode Enforcing
$ getsebool -a | head -3 # Use setsebool to change these values allow_cvs_read_shadow --> off allow_execheap --> off allow_execmem --> off
audit2why
tries to explain AVC (Access Vector Cache) violations and provides hints how to resolve them:
$ ausearch --interpret --success no | tail -1 | audit2why type=AVC msg=audit(07/13/2014 02:10:12.122:59354) : avc: denied { getattr } for pid=28917 comm=rsync path=/run/rsnapshot.ready dev="tmpfs" ino=32330 scontext=unconfined_u:system_r:rsync_t:s0-s0:c0.c1023 tcontext=system_u:object_r:var_run_t:s0 tclass=file Was caused by: The boolean rsync_export_all_ro was set incorrectly. Description: rsync_export_all_ro Allow access by executing: # setsebool -P rsync_export_all_ro 1
TODO
setsebool semanage chcon --reference=foo bar
Links
- Fedora SELinux Project Pages
- SELinux FAQ
- RHEL7: SELinux User's and Administrator's Guide
- Debian SELinux support
- SELinux User Resources
- Security-Enhanced Linux
- SELinux for Mere Mortals
- Merging SELinux policies
References
- ↑ Debian SELinux Setup
- ↑ ext4: enable acls and user_xattr by default
- ↑ SELinux is preventing /usr/sbin/prelink from 'relabelfrom' accesses on the file undo.#prelink#.JSIRiV.
- ↑ Red Hat Enterprise Linux 4: Red Hat SELinux Guide: 8.2 Minor Customizations of the Existing Policy
- ↑ How to get a .te file from an existing .pp file?
- ↑ httpd to query databases via PHP
- ↑ I followed all the rules and built policy with audit2allow and the semodule command blows up