Jump to contentJump to page navigation: previous page [access key p]/next page [access key n]
Security and Hardening Guide / SELinux / Configuring SELinux
Applies to openSUSE Leap 15.4

41 Configuring SELinux

In this chapter, you will learn how to set up and manage SELinux on openSUSE Leap. The following topics are covered:

  • Why Use SELinux?

  • Understanding SELinux

  • Setting Up SELinux

  • Managing SELinux

41.1 Why use SELinux?

SELinux was developed as an additional Linux security solution that uses the security framework in the Linux kernel. The purpose was to allow for a more granular security policy that goes beyond the standard Discretionary Access Controls (DAC), the traditional file permissions of owner/group/world, and read/write/execute.

An example explains why a solution such as SELinux (or its counterpart AppArmor) is needed:

One morning, I found out that my server was hacked. The server was running a fully patched openSUSE Leap installation. A firewall was configured on it and no unnecessary services were offered by this server. Further analysis revealed that the hacker had come in through a vulnerable PHP script that was a part of one of the Apache virtual hosts that were running on this server. The intruder had managed to get access to a shell, using the wwwrun account that was used by the Apache Web server. As this wwwrun user, the intruder had created several scripts in the /var/tmp and the /tmp directories, which were a part of a botnet that was launching a Distributed Denial of Service attack against several servers.

The interesting thing about this hack is that it occurred on a server where nothing was really wrong. All file permissions were set correctly, but the intruder still managed to get into the system. This example demonstrates that in some cases additional security is needed.

SELinux uses labels attached to objects (for example, files and network sockets) and uses them for access control decision.

41.1.1 Support status

The SELinux framework is supported on openSUSE Leap 15.4. openSUSE Leap offers all binaries and libraries you need to use SELinux on your server.

A policy is not included, and you must build your own. Third-party policies are not supported. See Section 41.3, “Installing SELinux packages” and Section 41.4, “Installing an SELinux policy” for information on installing an openSUSE policy for testing.

41.1.2 Understanding SELinux components

Before starting the configuration of SELinux, you should know a bit about how SELinux is organized. Three components play a role:

  • The security framework in the Linux kernel

  • The SELinux libraries and binaries

  • The SELinux policy

The default kernel of openSUSE Leap supports SELinux and the tools that are needed to manage it. The most important part of the work of the administrator with regard to SELinux is managing the policy.

In the SELinux policy, security labels are applied to different objects on a Linux server. These objects typically are users, ports, processes, and files. Using these security labels, rules are created that define what is and what is not allowed on a server. By default, SELinux denies everything, and by creating the appropriate rules you can allow the access that is strictly necessary. Rules should therefore exist for all programs that you want to use on a system.

Alternatively, you could configure parts of a system to run in unconfined mode, which means that specific ports, programs, users, files and directories are not protected by SELinux. This mode is useful if you only want to use SELinux to protect some essential services. However, this leaves your system incompletely protected, and it is better to apply SELinux to the whole system.

To ensure the appropriate protection of your system, you need an SELinux policy. This must be a tailor-made policy in which all files are provided with a label, and all services and users have a security label as well to express which files and directories can be accessed by which user and processes on the server. Developing such a policy is a tremendous amount of work.

Note that a freely available SELinux policy might work on your server, but is unlikely to offer the same protection as a custom policy. SUSE does not support third-party policies.

41.2 SELinux policy overview

The policy is the key component in SELinux. Your SELinux policy defines rules that specify which objects can access which files, directories, ports, and processes on a system. To do this, a security context is defined for all of these. On an SELinux system where the policy has been applied to label the file system, you can use the ls -Z command on any directory to find the security context for the files in that directory. Example 41.1: “Security context settings using ls -Z shows the security context settings for the directories in the / directory of a openSUSE Leap system with an SELinux-labeled file system.

Example 41.1: Security context settings using ls -Z
> ls -Z /
system_u:object_r:bin_t bin
system_u:object_r:boot_t boot
system_u:object_r:device_t dev
system_u:object_r:etc_t etc
system_u:object_r:home_root_t home
system_u:object_r:lib_t lib
system_u:object_r:lib_t lib64
system_u:object_r:lost_found_t lost+found
system_u:object_r:mnt_t media
system_u:object_r:mnt_t mnt
system_u:object_r:usr_t opt
system_u:object_r:proc_t proc
system_u:object_r:default_t root
system_u:object_r:bin_t sbin
system_u:object_r:security_t selinux
system_u:object_r:var_t srv
system_u:object_r:sysfs_t sys
system_u:object_r:tmp_t tmp
system_u:object_r:usr_t usr
system_u:object_r:var_t var

The most important line in the security context is the context type. This is the part of the security context that often ends in _t. It tells SELinux which kind of access the object is allowed. In the policy, rules are specified to define which type of user or which type of role has access to which type of context. For example, this can happen by using a rule like the following:

allow user_t bin_t:file {read execute gettattr};

This example rule states that the user who has the context type user_t (this user is called the source object) is allowed to access objects of class "file" with the context type bin_t (the target), using the permissions read, execute, and getattr.

An SELinux policy contains a huge number of rules. To make it more manageable, policies are often split into modules. This allows administrator to switch protection on or off for different parts of the system.

When compiling the policy for your system, you will have a choice to either work with a modular policy, or a monolithic policy, where one huge policy is used to protect everything on your system. It is strongly recommended to use a modular policy and not a monolithic policy. Modular policies are much easier to manage.

41.3 Installing SELinux packages

From the command line, install the following packages:

> sudo zypper in restorecond policycoreutils setools-console

This does not install a policy. See Section 41.4, “Installing an SELinux policy” for information on installing an openSUSE policy for testing.

41.4 Installing an SELinux policy

The policy is an essential component of SELinux. openSUSE Leap 15.4 does not include a default policy, and you must build a policy that is customized for your installation. SELinux policies should be customized for your particular needs; consult your SUSE support engineer for assistance.

For testing purposes you can obtain policies from https://download.opensuse.org/repositories/security:/SELinux_legacy/. This provides repositories for SLE with a number of additional packages, including policies.

  1. Copy the repository link that matches your SLE version, and add it with Zypper:

    > sudo zypper ar -f \
    https://download.opensuse.org/repositories/security:/SELinux_legacy/15.4/ \
    SELinux-Legacy
  2. Install the following packages:

    > sudo zypper in selinux-policy-targeted selinux-policy-devel

41.5 Putting SELinux into permissive mode

In permissive mode, SELinux does not protect your system but it still logs everything that happens. Use this mode for testing and configuring your system.

In /etc/selinux/config, SELinux is set to permissive mode by default.

To enable the use of SELinux for your system, modify the GRUB 2 boot loader. In /etc/default/grub, search for the line GRUB_CMDLINE_LINUX_DEFAULT=. Add the following two parameters:

security=selinux selinux=1

The first parameter tells the kernel to use SELinux and not AppArmor. The second parameter enables SELinux. After adding the parameters, rebuild your GRUB 2 configuration with the following command:

grub2-mkconfig -o /boot/grub2/grub.cfg

Now you can reboot. At this point you have a completely functional SELinux system, and it is time to further configure it. In the current status, SELinux does not limit any activities and logs everything that it should be doing if it were in enforcing mode. Review the log files to learn what activities are not allowed.

41.6 Putting SELinux into enforcing mode

When systems run SELinux in permissive mode, users and processes might label various file system objects incorrectly. This can cause problems when switching to enforcing mode because SELinux relies on correct labels of file system objects.

Before switching into enforcing mode, make sure to first reset the security context (extended attributes):

> sudo restorecon -R /

Now you can put SELinux into enforcing mode. For this, edit /etc/selinux/config and set SELINUX=enforcing.

Reboot your server and see if it still comes up the way you expect it to and if you can still log in.

After logging in, run the sestatus -v command. It should give you an output similar to Example 41.2: “Verifying that SELinux is functional”.

Example 41.2: Verifying that SELinux is functional
> sudo sestatus -v
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
Memory protection checking:     requested(insecure)
Max kernel policy version:      33

Process contexts:
Current context:                unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Init context:                   system_u:system_r:init_t:s0
/usr/sbin/sshd                  system_u:system_r:sshd_t:s0-s0:c0.c1023

File contexts:
Controlling terminal:           unconfined_u:object_r:user_tty_device_t:s0
/etc/passwd                     system_u:object_r:passwd_file_t:s0
/etc/shadow                     system_u:object_r:shadow_t:s0
/bin/bash                       system_u:object_r:shell_exec_t:s0 \
                                -> system_u:object_r:shell_exec_t:s0
/bin/login                      system_u:object_r:login_exec_t:s0
/bin/sh                         system_u:object_r:bin_t:s0 \
                                -> system_u:object_r:shell_exec_t:s0
/sbin/agetty                    system_u:object_r:bin_t:s0 \
                                -> system_u:object_r:getty_exec_t:s0
/sbin/init                      system_u:object_r:bin_t:s0 -> \
                                system_u:object_r:init_exec_t:s0
/usr/sbin/sshd                  system_u:object_r:sshd_exec_t:s0

If you are not able to boot the server properly with SELinux in enforcing mode, switch back to permissive mode. Check the log files with less /var/log/audit/audit.log. For more details, see Section 41.9, “Troubleshooting”.

41.7 Configuring SELinux

Before you start tuning your server, verify the SELinux installation. You have already used the command sestatus -v to view the current mode, process, and file contexts. Next, run

> sudo semanage boolean -l

which lists all Boolean switches that are available, and at the same time verifies that you can access the policy. Example 41.3, “Getting a list of booleans and verifying policy access” shows part of the output of this command.

Example 41.3: Getting a list of booleans and verifying policy access
> sudo semanage boolean -l
SELinux boolean                          Description
ftp_home_dir                   -> off   ftp_home_dir
mozilla_read_content           -> off   mozilla_read_content
spamassassin_can_network       -> off   spamassassin_can_network
httpd_can_network_relay        -> off   httpd_can_network_relay
openvpn_enable_homedirs        -> off   openvpn_enable_homedirs
gpg_agent_env_file             -> off   gpg_agent_env_file
allow_httpd_awstats_script_anon_write -> off   allow_httpd_awstats_script_anon_write
httpd_can_network_connect_db   -> off   httpd_can_network_connect_db
allow_ftpd_full_access         -> off   allow_ftpd_full_access
samba_domain_controller        -> off   samba_domain_controller
httpd_enable_cgi               -> off   httpd_enable_cgi
virt_use_nfs                   -> off   virt_use_nfs

Another command that outputs useful information at this stage is

> sudo semanage fcontext -l

It shows the default file context settings as provided by the policy (see Example 41.4: “Getting file context information” for partial output of this command).

Example 41.4: Getting file context information
> sudo semanage fcontext -l
/var/run/usb(/.*)?                                 all files          system_u:object_r:hotplug_var_run_t
/var/run/utmp                                      regular file       system_u:object_r:initrc_var_run_t
/var/run/vbe.*                                     regular file       system_u:object_r:hald_var_run_t
/var/run/vmnat.*                                   socket             system_u:object_r:vmware_var_run_t
/var/run/vmware.*                                  all files          system_u:object_r:vmware_var_run_t
/var/run/watchdog\.pid                             regular file       system_u:object_r:watchdog_var_run_t
/var/run/winbindd(/.*)?                            all files          system_u:object_r:winbind_var_run_t
/var/run/wnn-unix(/.*)                             all files          system_u:object_r:canna_var_run_t
/var/run/wpa_supplicant(/.*)?                      all files          system_u:object_r:NetworkManager_var_run_t
/var/run/wpa_supplicant-global                     socket             system_u:object_r:NetworkManager_var_run_t
/var/run/xdmctl(/.*)?                              all files          system_u:object_r:xdm_var_run_t
/var/run/yiff-[0-9]+\.pid                          regular file       system_u:object_r:soundd_var_run_t

41.8 Managing SELinux

The base SELinux configuration is now operational and it can now be configured to secure your server. In SELinux, an additional set of rules is used to define exactly which process or user can access which files, directories, or ports. To do this, SELinux applies a context to every file, directory, process, and port. This context is a security label that defines how this file, directory, process, or port should be treated. These context labels are used by the SELinux policy, which defines exactly what should be done with the context labels. By default, the policy blocks all non-default access, which means that, as an administrator, you need to enable all features that are non-default on your server.

41.8.1 Viewing the security context

As already mentioned, files, directories, and ports can be labeled. Within each label, different contexts are used. To be able to perform your daily administration work, the type context is what you are most interested in. As an administrator, you will mostly work with the type context. Many commands allow you to use the -Z option to list current context settings. In Example 41.5: “The default context for directories in the root directory” you can see what the context settings are for the directories in the root directory.

Example 41.5: The default context for directories in the root directory
> sudo ls -Z
dr-xr-xr-x. root root system_u:object_r:bin_t:s0       bin
dr-xr-xr-x. root root system_u:object_r:boot_t:s0      boot
drwxr-xr-x. root root system_u:object_r:cgroup_t:s0    cgroup
drwxr-xr-x+ root root unconfined_u:object_r:default_t:s0 data
drwxr-xr-x. root root system_u:object_r:device_t:s0    dev
drwxr-xr-x. root root system_u:object_r:etc_t:s0       etc
drwxr-xr-x. root root system_u:object_r:home_root_t:s0 home
dr-xr-xr-x. root root system_u:object_r:lib_t:s0       lib
dr-xr-xr-x. root root system_u:object_r:lib_t:s0       lib64
drwx------. root root system_u:object_r:lost_found_t:s0 lost+found
drwxr-xr-x. root root system_u:object_r:mnt_t:s0       media
drwxr-xr-x. root root system_u:object_r:autofs_t:s0    misc
drwxr-xr-x. root root system_u:object_r:mnt_t:s0       mnt
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 mnt2
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 mounts
drwxr-xr-x. root root system_u:object_r:autofs_t:s0    net
drwxr-xr-x. root root system_u:object_r:usr_t:s0       opt
dr-xr-xr-x. root root system_u:object_r:proc_t:s0      proc
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 repo
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 root
dr-xr-xr-x. root root system_u:object_r:bin_t:s0       sbin
drwxr-xr-x. root root system_u:object_r:security_t:s0  selinux
drwxr-xr-x. root root system_u:object_r:var_t:s0       srv
-rw-r--r--. root root unconfined_u:object_r:swapfile_t:s0 swapfile
drwxr-xr-x. root root system_u:object_r:sysfs_t:s0     sys
drwxrwxrwt. root root system_u:object_r:tmp_t:s0       tmp
-rw-r--r--. root root unconfined_u:object_r:etc_runtime_t:s0 tmp2.tar
-rw-r--r--. root root unconfined_u:object_r:etc_runtime_t:s0 tmp.tar
drwxr-xr-x. root root system_u:object_r:usr_t:s0       usr
drwxr-xr-x. root root system_u:object_r:var_t:s0       var

In the listing above, you can see the complete context for all directories. It consists of a user, a role, and a type. The s0 setting indicates the security level in Multi Level Security environments. These environments are not discussed here. In such an environment, make sure that s0 is set. The Context Type defines what kind of activity is permitted in the directory. Compare, for example, the /root directory, which has the admin_home_t context type, and the /home directory, which has the home_root_t context type. In the SELinux policy, different kinds of access are defined for these context types.

Security labels are not only associated with files, but also with other items, such as ports and processes. In Example 41.6: “Showing SELinux settings for processes with ps Zaux for example you can see the context settings for processes on your server.

Example 41.6: Showing SELinux settings for processes with ps Zaux
> sudo ps Zaux
LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
system_u:system_r:init_t        root         1  0.0  0.0  10640   808 ?        Ss   05:31   0:00 init [5]
system_u:system_r:kernel_t      root         2  0.0  0.0      0     0 ?        S    05:31   0:00 [kthreadd]
system_u:system_r:kernel_t      root         3  0.0  0.0      0     0 ?        S    05:31   0:00 [ksoftirqd/0]
system_u:system_r:kernel_t      root         6  0.0  0.0      0     0 ?        S    05:31   0:00 [migration/0]
system_u:system_r:kernel_t      root         7  0.0  0.0      0     0 ?        S    05:31   0:00 [watchdog/0]
system_u:system_r:sysadm_t      root      2344  0.0  0.0  27640   852 ?        Ss   05:32   0:00 /usr/sbin/mcelog --daemon --config-file /etc/mcelog/mcelog.conf
system_u:system_r:sshd_t        root      3245  0.0  0.0  69300  1492 ?        Ss   05:32   0:00 /usr/sbin/sshd -o PidFile=/var/run/sshd.init.pid
system_u:system_r:cupsd_t       root      3265  0.0  0.0  68176  2852 ?        Ss   05:32   0:00 /usr/sbin/cupsd
system_u:system_r:nscd_t        root      3267  0.0  0.0 772876  1380 ?        Ssl  05:32   0:00 /usr/sbin/nscd
system_u:system_r:postfix_master_t root   3334  0.0  0.0  38320  2424 ?        Ss   05:32   0:00 /usr/lib/postfix/master
system_u:system_r:postfix_qmgr_t postfix  3358  0.0  0.0  40216  2252 ?        S    05:32   0:00 qmgr -l -t fifo -u
system_u:system_r:crond_t       root      3415  0.0  0.0  14900   800 ?        Ss   05:32   0:00 /usr/sbin/cron
system_u:system_r:fsdaemon_t    root      3437  0.0  0.0  16468  1040 ?        S    05:32   0:00 /usr/sbin/smartd
system_u:system_r:sysadm_t      root      3441  0.0  0.0  66916  2152 ?        Ss   05:32   0:00 login -- root
system_u:system_r:sysadm_t      root      3442  0.0  0.0   4596   800 tty2     Ss+  05:32   0:00 /sbin/mingetty tty2

41.8.2 Selecting the SELinux mode

In SELinux, three different modes can be used:

Enforcing:

This is the default mode. SELinux protects your server according to the rules in the policy, and SELinux logs all of its activity to the audit log.

Permissive:

This mode is useful for troubleshooting. If set to Permissive, SELinux does not protect your server, but it still logs everything that happens to the log files.

Disabled:

In this mode, SELinux is switched off completely and no logging occurs. The file system labels however are not removed from the file system.

You have already read how you can set the current SELinux mode from GRUB 2 while booting using the enforcing boot parameter.

41.8.3 Modifying SELinux context types

An important part of the work of an administrator is setting context types on files to ensure appropriate working of SELinux.

If a file is created within a specific directory, it inherits the context type of the parent directory by default. If, however, a file is moved from one location to another location, it retains the context type that it had in the old location.

To set the context type for files, you can use the semanage fcontext command. With this command, you write the new context type to the policy, but it does not change the actual context type immediately! To apply the context types that are in the policy, you need to run the restorecon command afterward.

The challenge when working with semanage fcontext is to find out which context you actually need. You can use

> sudo semanage fcontext -l

to list all contexts in the policy, but it may be a bit hard to find out the actual context you need from that list as it is rather long (see Example 41.7: “Viewing default file contexts”).

Example 41.7: Viewing default file contexts
> sudo semanage fcontext -l | less
SELinux fcontext                                   type               Context

/                                                  directory          system_u:object_r:root_t:s0
/.*                                                all files          system_u:object_r:default_t:s0
/[^/]+                                             regular file       system_u:object_r:etc_runtime_t:s0
/\.autofsck                                        regular file       system_u:object_r:etc_runtime_t:s0
/\.autorelabel                                     regular file       system_u:object_r:etc_runtime_t:s0
/\.journal                                         all files          X:>>None>>
/\.suspended                                       regular file       system_u:object_r:etc_runtime_t:s0
/a?quota\.(user|group)                             regular file       system_u:object_r:quota_db_t:s0
/afs                                               directory          system_u:object_r:mnt_t:s0
/bin                                               directory          system_u:object_r:bin_t:s0
/bin/.*                                            all files          system_u:object_r:bin_t:s0

There are three ways to find out which context settings are available for your services:

  • Install the service and look at the default context settings that are used. This is the easiest and recommended option.

  • Consult the man page for the specific service. Some services have a man page that ends in _selinux, which contains all the information you need to find the correct context settings.

    When you have found the right context setting, apply it using semanage fcontext. This command takes -t context type as its first argument, followed by the name of the directory or file to which you want to apply the context settings. To apply the context to everything that already exists in the directory where you want to apply the context, you add the regular expression (/.*)? to the name of the directory. This means: optionally, match a slash followed by any character. The examples section of the semanage man page has some useful usage examples for semanage. For more information on regular expressions, see for example the tutorial at http://www.regular-expressions.info/.

  • Display a list of all context types that are available on your system:

    > sudo seinfo -t

    Since the command by itself outputs an overwhelming amount of information, it should be used in combination with grep or a similar command for filtering.

41.8.4 Applying file contexts

To help you apply the SELinux context properly, the following procedure shows how to set a context using semanage fcontext and restorecon. You will notice that at first attempt, the Web server with a non-default document root does not work. After changing the SELinux context, it will:

  1. Create the /web directory and then change to it:

    > sudo mkdir /web  && cd /web
  2. Use a text editor to create the file /web/index.html that contains the text welcome to my Web site.

  3. Open the file /etc/apache2/default-server.conf with an editor, and change the DocumentRoot line to DocumentRoot /web

  4. Start the Apache Web server:

    > sudo systemctl start apache2
  5. Open a session to your local Web server:

    > w3m localhost

    You will receive a Connection refused message. Press Enter, and then q to quit w3m.

  6. Find the current context type for the default Apache DocumentRoot, which is /srv/www/htdocs. It should be set to httpd_sys_content_t:

    > sudo ls -Z /srv/www
  7. Set the new context in the policy and press Enter:

    > sudo semanage fcontext -a -f "" -t httpd_sys_content_t '/web(/.*) ?'
  8. Apply the new context type:

    > sudo restorecon /web
  9. Show the context of the files in the directory /web. You will see that the new context type has been set properly to the /web directory, but not to its contents.

    > sudo ls -Z /web
  10. Apply the new context recursively to the /web directory. The type context has now been set correctly.

    > sudo restorecon -R /web
  11. Restart the Web server:

    > sudo systemctl restart apache2

    You should now be able to access the contents of the /web directory.

41.8.5 Configuring SELinux policies

The easiest way to change the behavior of the policy is by working with Booleans. These are on-off switches that you can use to change the settings in the policy. To find out which Booleans are available, run

> sudo semanage boolean -l

It will show a long list of Booleans, with a short description of what each of these Booleans will do for you. When you have found the Boolean you want to set, you can use setsebool -P, followed by the name of the Boolean that you want to change. It is important to use the -P option at all times when using setsebool. This option writes the setting to the policy file on disk, and this is the only way to make sure that the Boolean is applied automatically after a reboot.

The procedure below gives an example of changing Boolean settings

  1. List Booleans that are related to FTP servers.

    > sudo semanage boolean -l | grep ftp
  2. Turn the Boolean off:

    > sudo setsebool allow_ftpd_anon_write off

    Note that it does not take much time to write the change. Then verify that the Boolean is indeed turned off:

    > sudo semanage boolean -l|grep ftpd_anon
  3. Reboot your server.

  4. Check again to see if the allow_ftpd_anon_write Boolean is still turned on. As it has not yet been written to the policy, you will notice that it is off.

  5. Switch the Boolean and write the setting to the policy:

    > sudo setsebool -P allow_ftpd_anon_write

41.8.6 Working with SELinux modules

By default, SELinux uses a modular policy. This means that the policy that implements SELinux features is not just one huge policy, but it consists of many smaller modules. Each module covers a specific part of the SELinux configuration. The concept of the SELinux module was introduced to make it easier for third party vendors to make their services compatible with SELinux. To get an overview of the SELinux modules, you can use the semodule -l command. This command lists all current modules in use by SELinux and their version numbers.

As an administrator, you can switch modules on or off. This can be useful if you want to disable only a part of SELinux and not everything to run a specific service without SELinux protection. Especially in the case of openSUSE Leap, where there is not a completely supported SELinux policy yet, it can make sense to switch off all modules that you do not need so that you can focus on the services that really do need SELinux protection. To switch off an SELinux module, use

> sudo semodule -d MODULENAME

To switch it on again, you can use

> sudo semodule -e modulename

41.9 Troubleshooting

By default, if SELinux is the reason something is not working, a log message to this effect is sent to the /var/log/audit/audit.log file. That is, if the auditd service is running. If you see an empty /var/log/audit, start the auditd service using

> sudo systemctl start auditd

and enable it in the targets of your system, using

> sudo systemctl enable auditd

In Example 41.8: “Example lines from /etc/audit/audit.log you can see a partial example of the contents of /var/log/audit/audit.log

Example 41.8: Example lines from /etc/audit/audit.log
type=DAEMON_START msg=audit(1348173810.874:6248): auditd start, ver=1.7.7 format=raw kernel=3.0.13-0.27-default auid=0 pid=4235 subj=system_u:system_r:auditd_t res=success
type=AVC msg=audit(1348173901.081:292): avc:  denied  { write } for  pid=3426 comm="smartd" name="smartmontools" dev=sda6 ino=581743 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir
type=AVC msg=audit(1348173901.081:293): avc:  denied  { remove_name } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir
type=AVC msg=audit(1348173901.081:294): avc:  denied  { unlink } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:295): avc:  denied  { rename } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582373 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:296): avc:  denied  { add_name } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir
type=AVC msg=audit(1348173901.081:297): avc:  denied  { create } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:298): avc:  denied  { write open } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:299): avc:  denied  { getattr } for  pid=3426 comm="smartd" path="/var/lib/smartmontools/smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.309:300): avc:  denied  { append } for  pid=1316

At first look, the lines in audit.log are a bit hard to read. However, on closer examination they are not that hard to understand. Every line can be broken down into sections. For example, the sections in the last line are:

type=AVC:

every SELinux-related audit log line starts with the type identification type=AVC

msg=audit(1348173901.309:300):

This is the time stamp, which unfortunately is written in epoch time, the number of seconds that have passed since Jan 1, 1970. You can use date -d on the part up to the dot in the epoch time notation to find out when the event has happened:

> date -d @1348173901
Thu Sep 20 16:45:01 EDT 2012
avc: denied { append }:

the specific action that was denied. In this case the system has denied the appending of data to a file. While browsing through the audit log file, you can see other system actions, such as write open, getattr and more.

for pid=1316:

the process ID of the command or process that initiated the action

comm="rsyslogd":

the specific command that was associated with that PID

name="smartmontools":

the name of the subject of the action

dev=sda6 ino=582296:

the block device and inode number of the file that was involved

scontext=system_u:system_r:syslogd_t:

the source context, which is the context of the initiator of the action

tclass=file:

a class identification of the subject

Instead of interpreting the events in audit.log yourself, there is another approach. You can use the audit2allow command, which helps analyze the cryptic log messages in /var/log/audit/audit.log. An audit2allow troubleshooting session always consists of three different commands. First, you would use audit2allow -w -a to present the audit information in a more readable way. The audit2allow -w -a by default works on the audit.log file. If you want to analyze a specific message in the audit.log file, copy it to a temporary file and analyze the file with:

> sudo audit2allow -w -i FILENAME
Example 41.9: Analyzing audit messages
> sudo audit2allow -w -i testfile
type=AVC msg=audit(1348173901.309:300): avc:  denied  { append } for  pid=1316
comm="rsyslogd" name="acpid" dev=sda6 ino=582296
scontext=system_u:system_r:syslogd_t tcontext=system_u:object_r:apmd_log_t tclass=file
This was caused by:

Missing type enforcement (TE) allow rule.

To generate a loadable module to allow this access, run

> sudo audit2allow

To find out which specific rule has denied access, you can use audit2allow -a to show the enforcing rules from all events that were logged to the audit.log file, or audit2allow -i FILENAME to show it for messages that you have stored in a specific file:

Example 41.10: Viewing which lines deny access
> sudo audit2allow -i testfile
#============= syslogd_t ==============
allow syslogd_t apmd_log_t:file append;

To create an SELinux module with the name mymodule that you can load to allow the access that was previously denied, run

> sudo audit2allow -a -R -M mymodule

If you want to do this for all events that have been logged to the audit.log, use the -a -M command arguments. To do it only for specific messages that are in a specific file, use -i -M as in the example below:

Example 41.11: Creating a policy module allowing an action previously denied
> sudo audit2allow -i testfile -M example
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i example.pp

As indicated by the audit2allow command, you can now run this module by using the semodule -i command, followed by the name of the module that audit2allow has created for you (example.pp in the above example).