Fedora 28: Mandatory Access Control with SELinux

This article will describe usage of SELinux.

1 Show SELinux status

The sestatus and the getenforce shows SELinux status. Enforcing means enabled and Permissive means disabled. SELinux is enabled by default.

$ sudo sestatus
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:      30
$ sudo getenforce
Enforcing

2 Enable and disable SELinux with setenforce (Not recommended)

Enable and disable SELinux with setenforce. "on" and "1" means enabled. "off" and "0" means disabled.

$ sudo setenforce on   # Enable SELinux.
$ sudo setenforce off  # Disable SELinux.

But "setenforce off" is not good way. You should use setroubleshoot-server, and set boolean or add policy.

3 Set SELinux boolean with setsebool

SELinux provides boolean for controlling of some function is enabled or disabled. For example, httpd_read_user_content controls to read user home directory.

Get boolean with getsebool.

$ sudo getsebool <key> # Show key value
$ sudo getsebool -a    # Show all key value

Set boolean with setsebool. -P option will apply boolean permanently. "on" and "1" means enabled. "off" and "0" means disabled.

$ sudo setsebool -P <key> on  # Enable <key>
$ sudo setsebool -P <key> off # Disable <key>

You do not need to learn boolean name with setroubleshoot-server.

4 Add SELinux policy with semodule

If setsebool cannot allow some action, you need to add SELinux policy with semodule.

  • Create ".te" file. ".te" file is text.
  • Create ".mod" file from ".te" file.
  • Create ".pp" file from ".mod" file. ".pp" file is binary.
  • Loading ".pp" file to semodule adds SELinux policy.
$ # create my-policy.te
$ checkmodule -M -m -o my-policy.mod my-policy.te
$ semodule_package -m my-policy.mod -o my-policy.pp
$ sudo semodule -i my-policy.pp

setroubleshoot-server will suggest ".te" file example.

5 Get resolution for SELinux from setroubleshoot-server

setroubleshoot-server provides resolution for SELinux to journald log when SELinux denies something.

5.1 setsebool example

SELinux will deny mod_userdir of httpd.

$ sudo journalctl
<snip>
Jun 11 22:15:59 yourhost setroubleshoot[20931]: Deleting alert
4d17868b-f30d-4719-9bbd-997a38f61807, it is dontaudit'd in current policy
Jun 11 22:16:00 yourhost setroubleshoot[20931]: SELinux is preventing
httpd from read access on the directory public_html. For complete
SELinux messages. run sealert -l 50efa2e4-2f95-40f3-ba54-114a9a44b4c2
Jun 11 22:16:00 yourhost python3[20931]: SELinux is preventing httpd
from read access on the directory public_html.
  *****  Plugin catchall_boolean (32.5 confidence) suggests  ***************

  If you want to allow httpd to read user content
  Then you must tell SELinux about this by enablin the
  'httpd_read_user_content' boolean.

  Do
  setsebool -P httpd_read_user_content 1
<snip>

You can change SELinux control with commands at the "Do".

$ sudo setsebool -P httpd_read_user_content 1

5.2 semodule example

SELinux will deny creating socket by Nagios.

$ sudo journalctl
Jun 11 23:22:42 yourhost setroubleshoot[9871]: SELinux is preventing
nagios from create access on the sock_file nagios.qh. For complete
SELinux messages. run sealert -l 3221abf3-4aae-4451-9d57-267a78ef12fe
Jun 11 23:22:42 yourhost python3[9871]: SELinux is preventing nagios
from create access on the sock_file nagios.qh.

  *****  Plugin catchall (100. confidence) suggests  ***********************

  If you believe that nagios should be allowed create access on the
  nagios.qh sock_file by default.
  Then you should report this as a bug.
  You can generate a local policy module to allow this access.

  Do
  allow this access for now by executing:
  # ausearch -c 'nagios' --raw | audit2allow -M my-nagios
  # semodule -X 300 -i my-nagios.pp

ausearch and audit2allow creates ".pp" file and ".te" file. But ausearch does not work unless SELinux denied once.

$ sudo ausearch -c 'nagios' --raw | audit2allow -M my-nagios
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i my-nagios.pp
$ ls my-nagios.*
my-nagios.pp  my-nagios.te

semodule adds SELinux policy.

$ sudo semodule -X 300 -i my-nagios.pp

For adding SELinux policy before SELinux denies, you need to create ".te" file manually.

  • Create ".te" file and ".pp" file with ausearch and audit2allow after SELinux denied on test environment. And copy ".te" file to product environment.
  • Add SELinux policy with ".te" file on product environment before SELinux denies.
$ cat my-nagios.te

module my-nagios 1.0;

require {
        type nagios_log_t;
        type nagios_t;
        class sock_file create;
}

#============= nagios_t ==============
allow nagios_t nagios_log_t:sock_file create;