SELinux

From Segfault
Jump to navigation Jump to search

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

Autorelabel

One can choose to relabel the entire system:

touch /.autorelabel
reboot

For some reason selinux-autorelabel then runs fixfiles on volatile filesystems too:

selinux-autorelabel[771]: Relabeling / /boot /dev /dev/hugepages /dev/mqueue /dev/pts /dev/shm /home /run /sys /sys/fs/cgroup /sys/fs/pstore /sys/kernel/debug /sys/kernel/tracing /tmp

Something related was reported before in RHBZ #1412747 and one is pointed at an explanation[8][9] for this behaviour:

> By default, it includes any filesystem with the seclabel mount option from /proc/mounts

That's why selinux-autorelabel tries to relabel e.g. /sys because it's mounted with the seclabel option, as are many others:

$ mount | grep seclabel
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=4096k,nr_inodes=4085226,mode=755,inode64)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,seclabel,inode64)
[...]

TODO

 setsebool
 semanage
 chcon --reference=foo bar

Links

References