Jump to contentJump to page navigation: previous page [access key p]/next page [access key n]
Applies to SUSE Linux Enterprise Server 11 SP4

30 Configuring SELinux on SUSE Linux Enterprise 11 SP2

Since SUSE Linux Enterprise 11 SP2, the SELinux framework is supported on SUSE Linux Enterprise. In this article you’ll learn how to set it up and how to manage SELinux on SLE 11 SP2 once it has been installed. The following topics are covered in this article:

  • SELinux backgrounds

  • Understanding SELinux

  • Setting up SELinux on SLE 11 SP2

  • Managing SELinux on SLE 11 SP2

30.1 SELinux backgrounds

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 what is offered by the default existing permissions of Read Write and Execute, and also beyond assigning permissions to the different capabilities that are available on Linux. SELinux does this by trapping all syscalls that reach the kernel, and denying them by default. This means that on a system that has SELinux enabled and nothing else configured, nothing will work. To allow your system to do anything, as an administrator you will need to write rules and put them in a policy.

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 SLES 10 SP 3 server, which was patched up to the latest level. A firewall was configured on it and no unnecessary services were offered by this server. Further analysis learned that the hacker had come in through a flaky 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 different servers on the planet.

The interesting thing about this hack is that it occurred on a server where nothing was really wrong. All permissions where set OK, but the intruder had managed to get into the system. What becomes clearly evident from this example is that in some cases additional security is needed—a security that goes beyond what is offered by using SELinux. As a less complete and less complex alternative, AppArmor can be used.

AppArmor confines specific processes in their abilities to read/write and execute files (and other things). Its view is mostly that things that happen inside a process cannot escape.

SELinux instead uses labels attached to objects (e.g. files, binaries, network sockets) and uses them to determine privilege boundaries, thereby building up a level of confinement that can span more than a process or even the whole system.

SELinux was developed by the US National Security Agency (NSA), and since the beginning Red Hat has been heavily involved in its development. The first version of SELinux was offered in the era of Red Hat Enterprise Linux 4™, around the year 2006. In the beginning it offered support for essential services only, but over the years it has developed into a system that offers many rules that are collected in policies to offer protection to a broad range of services.

SELinux was developed in accordance with some certification standards like Common Criteria and FIPS 140. Because some customers specifically requested solutions that met these standards, SELinux rapidly became relatively popular.

As an alternative to SELinux, Immunix, a company that was purchased by Novell in 2005, had developed AppArmor. AppArmor was built on top of the same security principles as SELinux, but took a completely different approach, where it was possible to restrict services to exactly what they needed to do by using an easy to use wizard-driven procedure. Nevertheless, AppArmor has never reached the same status as SELinux, even if there are some good arguments to secure a server with AppArmor rather than with SELinux.

Because more and more governmental organizations currently are requesting SELinux to be present in the Linux distributions they are using, SUSE is offering support for the SELinux framework in the latest versions of SUSE Linux Enterprise Server. This doesn’t mean that SUSE is about to switch from AppArmor to SELinux soon, for SUSE it is important that the customer can choose the security solution that fits his needs best.

30.1.1 Support Status

Currently, the SELinux framework is supported in SUSE Linux Enterprise 11 SP2. This means that you can expect that SUSE Linux Enterprise is offering all binaries and libraries you need to be able to use SELinux on your server without any problems. A policy however is not included and you will also miss some binaries that you might be familiar with from using other Linux distributions. Some of these binaries are available at http://software.opensuse.org. It is however not a good idea to install them on your SUSE Linux Enterprise system as they haven’t been tested and therefore might cause additional problems to the system. Currently, SELinux support is at a fairly early stage on SUSE Linux Enterprise and this means that unexpected behavior may occur. To limit this risk as much as possible, it is a good idea to use only the binaries that have been provided by default on SLES 11 SP2.

30.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

SUSE Linux Enterprise 11 SP2 and later comes with the standard support for SELinux in the Linux kernel, and the tools that are needed to manage the SELinux solution. You will shortly learn how to install these tools on your server. The most important part of the work of the administrator with regards 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 isn’t allowed on a server. Remember, by default SELinux denies all syscalls and by creating the appropriate rules you can allow the syscalls that you trust again. Rules should therefore exist for all programs that you want to use on a system. Alternatively, you might want to configure parts of a system to run in unconfined mode, which means that specific ports, programs, users, files and directories are not protected at all by SELinux. This mode is useful if you just want to use SELinux to protect some essential services, while you aren't specifically worried about other services. To get a really secure system, you should try to avoid this.

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 processed on the server. Developing such a policy is a tremendous amount of work. In SUSE Linux Enterprise, no policy is available yet. If you want to use SELinux, you have to take care of creating your own policy.

The complexity of SELinux is also one of the main arguments against using it. Because a typical Linux system is so very complex, it is easy to oversee something and leave an opening that intruders can abuse to get into your system. And even if it is set up completely the way it should be, it still is very hard for an administrator to overlook all aspects with SELinux. With regards to the complexity, AppArmor takes a completely different approach and works with automated procedures that allow the administrator to set up AppArmor protection and understand exactly what is happening.

In SUSE Linux Enterprise 11 SP2, the SELinux framework is supported and provided. The SELinux policy is not. Therefore, as an administrator that wishes to use SELinux on SUSE Linux Enterprise, you will have to create your own policy, or use one of the standard policies that are available for free. Do notice though that a freely available SELinux policy might work on your server, but it will never offer complete protection for all aspects of security on your server! Also, SUSE does not support these open source policies, which is obvious because they haven’t been developed by SUSE and they do not match SUSE. But in its current state you can use SELinux to protect SUSE Linux Enterprise Server.

30.2 The Policy

As mentioned, the policy is the key component in SELinux. It 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 30.1: “Showing security context settings using ls -Z” shows the security context settings for the directories in the / directory of an SLES 11 SP2 system with an SELinux-labeled file system.

Example 30.1: Showing security context settings using ls -Z
mmi:/ # ls -Z
system_u:object_r:default_t .autorelabel
system_u:object_r:file_t .viminfo
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
system_u:object_r:httpd_sys_content_t www

The most important line in the security context is the context type. This is the part of the security context that 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 referred to as the source object) is allowed to access the file with the context type bin_t (the target), using the permissions read, execute and getattr. Later in this article you will learn how to use a standard policy to apply this kind of security context settings to the file system on your server.

The standard policy that you are going to use contains a huge amount of rules. To make it more manageable, policies are often applied as modular policies. This allows the administrator to work with independent modules that allow the 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.

30.3 Installing SELinux on SUSE Linux Enterprise 11 SP2

You can install all SELinux components while performing the installation of your SUSE Linux Enterprise system, or afterwards. Installation consists of the following steps:

  • Install all SELinux packages

  • Enable GRUB boot options

  • Install a policy

30.4 Installing SELinux Packages and modifying GRUB

The easiest way to make sure that all SELinux components are installed is by using YaST2. The procedure described below shows what to do on an installed SLES 11 SP2 server.

  1. Log in to your server as root and start YaST2.

  2. Select Software › Software Management

  3. Select View › Patterns and select the entire C/C++ Compiler and Tools software category for installation.

  4. Select View › Search and make sure that Search in Name, Keywords and Summary are selected. Now enter the keyword selinux and click Search. You now see a list of packages.

  5. Make sure that all the packages you’ve found are selected and click Accept to install them.

Selecting all SELinux Packages in YaST2
Figure 30.1: Selecting all SELinux Packages in YaST2

After installing the SELinux packages, you have to modify the GRUB boot loader. To do this, from YaST select System > Boot loader. On the Section Management tab, you'll now see the current GRUB configuration. Select the label that starts with SUSE Linux Enterprise Server 11 SP2 and click Edit. Now select the line that contains the Optional Kernel Command Line Parameters and add the following to the end of this line: security=selinux selinux=1 enforcing=0

These options are used for the following purposes:

security=selinux

This option tells the kernel to use SELinux and not AppArmor

selinux=1

This option switches on SELinux

enforcing=0

This option puts SELinux in permissive mode. In this mode, SELinux is fully functional, but doesn’t enforce any of the security settings in the policy. Use this mode for configuring your system, and once it is fully operational, change it to enforcing=1 to switch on SELinux protection on your server.

After installing the SELinux packages and enabling the SELinux GRUB boot options, reboot your server to activate the configuration. You may notice that while rebooting, an error is displayed mentioning that the policy file could not be loaded. At this point in the configuration the error is normal and you can safely ignore it. It will disappear once you have compiled the policy.

30.5 Compiling the Policy

As mentioned, the policy is an essential component of SELinux but no default policy is available for SUSE Linux Enterprise. This means that you’ll need to get a policy from somewhere else. The best choice is to get a policy from the openSUSE download site at http://software.opensuse.org. In the Package Search bar presented at this site, type selinux-policy to get access to a list of all open source policy packages presented at http://openSUSE.org.

Get an open source policy package from http://software.opensuse.org
Figure 30.2: Get an open source policy package from http://software.opensuse.org

Don’t click the Direct Install link, but select Show other versions. The current policy packages provided for SLE 11 are in an unstable state, but still they are the best available option because they match the layout of the file system on SLE better than the default policy for openSUSE 12.x. Many items have changed in the openSUSE 12.x file system as compared to the SLE file system, so open the SUSE SLE-11 SP1 link, accept the unstable package and click Source to download the policy source file and save it to disk. This gives you a file with the name selinux-policy-2.20081210-12.2.src.rpm (the exact name of the file might be slightly different because of the version number that is included in the filename).

After downloading the source RPM, you can apply the following steps to install it to your server:

  1. Extract the archive from the source RPM, using

    rpm2cpio selinux-policy- >version>.src.rpm | cpio -idmv

    This gives you a tarball in the current directory, with the name refpolicy-version.tar.bz2.

  2. Extract the contents of the tarball to the directory /etc/selinux/refpolicy. Use

    tar xvf refpolicy-version.tar.bz2 -C /etc/selinux

    to do this.

  3. Make sure that in the directory /etc/selinux there is a file with the name config that has the following contents:

    SELINUX=permissive
    SELINUXTYPE=refpolicy
  4. Edit the configuration file /etc/selinux/refpolicy/build.conf and make sure it includes the following parameters:

    DISTRO = suse
    UNK_PERMS = allow
    DIRECT_INITRC = y
    MONOLITHIC = n
  5. Make sure that you are in the directory /etc/selinux/refpolicy and from that directory, run the make load command. This command will take a while to complete.

  6. Use the mkinitrd command to re-create the initrd file. This is needed to guarantee proper booting of the server with the policy.

  7. Once make load has completed, reboot your server.

Before doing anything else, at this point you should use the command semanage fcontext -a -e /dev /lib/udev/devices. This is to set a context for a critical directory that is not taken care of by the policy by default.

At this point all prerequisites have been met and you are ready to start file system labeling. To do this, use the command restorecon -Rv /. This command starts the /sbin/setfiles command to label all files on your system. To do this, the input file /etc/selinux/refpolicy/contexts/files/file_contexts is used. Because there currently is no SELinux policy for SUSE Linux Enteprise, this is a delicate part of the configuration. The file_contexts file has to match your actual file system as much as possible, so if it goes wrong, it is likely to go wrong at this point. This can lead to a completely unbootable system. If that happens, tune the contents of the file_contexts file to match the structure of the file system your server is using. Before doing this, make sure to read the rest of this article so that you fully understand how context type is applied to files and directories (and don't forget to make a backup of the file_contexts file before starting). At the end of this article you'll find tips that help you in troubleshooting SELinux and creating a system that fully works with your SELinux policy.

Note: if while using semanage you get a message that complains about the user nobody's home directory, you can change the login shell of user nobody to /sbin/nologin. This makes sure that the user nobody's settings match the current policy settings.

After another reboot SELinux should be operational. To verify this, use the command sestatus -v. It should give you an output that looks like the output in Example 30.2: “After labeling the file system you can verify that SELinux is functional using sestatus -v.

Example 30.2: After labeling the file system you can verify that SELinux is functional using sestatus -v
sestatus -v          
mmi:/ # sestatus -v
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   permissive
Mode from config file:          permissive
Policy version:                 26
Policy from config file:        refpolicy
                
Process contexts:
Current context:                root:staff_r:staff_t
Init context:                   system_u:system_r:init_t
/sbin/mingetty                  system_u:system_r:sysadm_t
/usr/sbin/sshd                  system_u:system_r:sshd_t
                
File contexts:
Controlling term:               root:object_r:user_devpts_t
/etc/passwd                     system_u:object_r:etc_t
/etc/shadow                     system_u:object_r:shadow_t
/bin/bash                       system_u:object_r:shell_exec_t
/bin/login                      system_u:object_r:login_exec_t
/bin/sh                         system_u:object_r:bin_t -> system_u:object_r:shell_exec_t
/sbin/agetty                    system_u:object_r:getty_exec_t
/sbin/init                      system_u:object_r:init_exec_t
/sbin/mingetty                  system_u:object_r:getty_exec_t
/usr/sbin/sshd                  system_u:object_r:sshd_exec_t
/lib/libc.so.6                  system_u:object_r:lib_t -> system_u:object_r:lib_t
/lib/ld-linux.so.2              system_u:object_r:lib_t -> system_u:object_r:ld_so_t

30.6 Configuring SELinux

At this point you have a completely functional SELinux system and it is time to further configure the system. In the current status, SELinux is operational but not in enforcing mode. This means that it doesn’t limit you in doing anything, it just logs everything that it should be doing if it were in enforcing mode. This is good, because based on the log files you can find what it is that it would prevent you from doing. As a first test, it is a good idea to put SELinux in enforcing mode and find out if you can still use your server after doing so. To do this, open the /etc/selinux/config file (or the /boot/grub/menu.lst file) and make sure that the option enforcing=1 is set. Reboot your server and see if it still comes up the way you expect it to. If it does, leave it like that and start modifying the server in a way that everything works as expected. Chances are though that you won’t even be able to boot the server properly. If that is the case, switch back to the mode where SELinux is not enforcing and start tuning your server.

30.6.1 Verifying the installation

Before you start tuning your server, it is a good idea to verify the SELinux installation. You have already used the command sestatus -v to view the current mode, process, and file contexts. Next, use semanage boolean -l, which shows a list of all Boolean switches that are available, and at the same time verifies that you can access the policy. Example 30.3, “Use semanage boolean -l to get a list of Booleans and verify policy access” shows part of the output of this command.

Example 30.3: Use semanage boolean -l to get a list of Booleans and verify policy access
mmi:~ # 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_user_mysql_connect       -> off   allow_user_mysql_connect
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 should produce output at this stage is semanage fcontext -l . This command shows the default file context settings as provided by the policy (see Example 30.4: “Use semanage fcontext -l to get file context information” for partial output of this command).

Example 30.4: Use semanage fcontext -l to get file context information
/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/vpnc(/.*)?                                all files          system_u:object_r:vpnc_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

30.7 Managing SELinux

Now that the base SELinux configuration is operational, it’s time to start configuring it in a way that secures your server. Let’s remind ourselfs what SELinux is all about first. 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 have to enable all features that are non-default on your server.

30.7.1 Displaying the Security Context

As mentioned, files, folders, 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’re most interested in. As an administrator, you’ll mostly work with the type context. Many commands allow you to use the -Z option to show a list of current context settings. In Example 30.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 30.5: The default context for directories in the root directory
[root@hnl /]# 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 in this article, so just make sure that it is set to s0 and you'll be fine. 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 30.6: “Showing SELinux settings for processes” for example you can see the context settings for processes on your server.

Example 30.6: Showing SELinux settings for processes
mmi:/ # 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

30.7.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. Also, in permissive mode, the Linux kernel still maintains the SELinux labels in the file system. This is good, because this prevents your system from relabeling everything after turning SELinux on again.

Disabled:

This mode is to be deactivated. In disabled 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 while booting using the enforcing boot parameter.

30.7.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 doesn’t change the actual context type immediately! To apply the context types that are in the policy, you need to run the restorecon command afterwards.

The challenge when working with semanage fcontext is to find out which context you actually need. You can use semanage fcontext -l to show a list of all contexts in the policy, but it might be a bit hard to find out the actual context you need from that list as it is rather long (see Example 30.7: “Showing Displaying default file contexts with semanage fcontext -l).

Example 30.7: Showing Displaying default file contexts with semanage fcontext -l
[root@hnl ~]# 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.

    After finding the specific context setting you need, you just have to 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.

  • Use seinfo -t to display a list of all contexts types that are available on your system, combined with grep to find the context type you need for a specific purpose. The amount of information provided with seinfo -t is a bit overwhelming, about 3,000 contexts type are available by default!

30.7.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 doesn’t work. After changing the SELinux context it will

  1. Use mkdir /web and then go to that directory using 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, using service apache2 start.

  5. Use w3m localhost to open a session to your local Web server. You will receive a Connection refused message. Press Enter, and then q to quit w3m.

  6. Use ls -Z /srv/www to find the current context type for the default Apache DocumentRoot, which is /srv/www/htdocs. It should be set to httpd_sys_content_t.

  7. Use semanage fcontext -a -f “”-t httpd_sys_content_t ‘/web(/.*) ?’ to set the new context in the policy and press Enter.

  8. Now use restorecon /web to apply the new context type.

  9. Use ls -Z /web to show the context of the files in the directory /web. You’ll see that the new context type has been set properly to the /web directory, but not to its contents.

  10. Use restorecon -R /web to apply the new context recursively to the /web directory. The type context has now been set correctly.

  11. Restart the Web server, using service apache2 restart. You should now be able to access the contents of the /web directory.

30.7.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, you can use the semanage boolean -l command. It will show you a long list of Booleans, with a short description of what each of these Booleans will do for you. Once 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. From a root shell, type semanage boolean -l | grep ftp. This shows a list of Booleans that are related to FTP servers.

  2. Use setsebool allow_ftpd_anon_write off to switch off this Boolean. Notice that it doesn’t take much time to write the change. Use semanage boolean -l|grep ftpd_anon to verify that the Boolean is indeed turned on.

  3. Reboot your server.

  4. Check again to see if the allow_ftpd_anon_write Boolean is still turned on. As it hasn’t yet been written to the policy, you’ll notice that it is off right now.

  5. Use setsebool -P allow_ftpd_anon_write on to switch the Boolean and write the setting to the policy.

30.7.6 Working with SELinux Modules

You have compiled SELinux as modular. 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 shows a list of 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 SUSE Linux Enterprise, where there is not a completely supported SELinux policy yet, it can make sense to switch off all modules that you don’t need so that you can focus on the services that really do need SELinux protection. To switch off an SELinux module, use semodule -d modulename. If you want to switch it on again, you can use semodule -e modulename. Using this command will change the current state of the module in the /etc/selinux/refpolicy/policy/modules.conf file. Alternatively, you could also edit this file by hand.

To handle policy modules properly, it helps to understand what you’re dealing with. In the end, a policy module is a compiled policy file that you can load using the semodule -e command. You can recognize these files by the extension they use: *.pp (which stands for Policy Package). In some cases it can be useful to modify modules to have them do exactly what you need them to do. Three different kinds of files are used as input files for policy modules and you can find them in subdirectories of the /etc/selinux/refpolicy/policy/modules directory:

  • *.te files contain transition rules. These rules tell the policy how to deal with specific subprocesses that are started. You won´t often change these as an administrator.

  • *.if files define what exactly the policy should be doing. As an administrator you don´t typically change the contents of these files.

  • *.fc files contain the labeling instructions that apply to this policy. As an administrator, you might want to change the contents of the .fc files to modify the default behavior of policies.

In Example 30.8: “The first 20 lines from the apache.fc file” below you can see the first 20 lines of the apache.fc file. This is the file that contains the default file contexts that are used for the Apache server.

Example 30.8: The first 20 lines from the apache.fc file
/etc/apache(2)?(/.*)? gen_context(system_u:object_r:httpd_config_t,s0)
       /etc/apache-ssl(2)?(/.*)? gen_context(system_u:object_r:httpd_config_t,s0)
       /etc/htdig(/.*)? gen_context(system_u:object_r:httpd_sys_content_t,s0)
       /etc/httpd -d gen_context(system_u:object_r:httpd_config_t,s0) /etc/httpd/conf.*
       gen_context(system_u:object_r:httpd_config_t,s0) /etc/httpd/logs
       gen_context(system_u:object_r:httpd_log_t,s0) /etc/httpd/modules
       gen_context(system_u:object_r:httpd_modules_t,s0) /etc/vhosts --
       gen_context(system_u:object_r:httpd_config_t,s0) /srv/([^/]*/)?www(/.*)?
       gen_context(system_u:object_r:httpd_sys_content_t,s0) /srv/gallery2(/.*)?
       gen_context(system_u:object_r:httpd_sys_content_t,s0) /usr/bin/htsslpass --
       gen_context(system_u:object_r:httpd_helper_exec_t,s0) /usr/lib/apache-ssl/.+ --
       gen_context(system_u:object_r:httpd_exec_t,s0) /usr/lib/cgi-bin(/.*)?
       gen_context(system_u:object_r:httpd_sys_script_exec_t,s0)
       /usr/lib(64)?/apache(/.*)? gen_context(system_u:object_r:httpd_modules_t,s0)
       /usr/lib(64)?/apache2/modules(/.*)?
       gen_context(system_u:object_r:httpd_modules_t,s0)

In the fc file, you’ll be able to recognize different elements. First is the name of the directory or file to which the file context will apply. As you can see, variables can be used (as is the case in the first line that starts with HOME_DIR), and typically, regular expressions will be used as well. Next, the gen_context command tells the policy to which context the files related to the policy module should be set. This is the same context setting that you can see when using ls -Z on the file or directory.

As an administrator, you don’t typically change the contents of the policy files that come from the SELinux Policy RPM. You would rather use semanage fcontext to change file contexts. If you are using audit2allow to generate policies for your server, you might want to change the policy files after all. If you want to change the contents of any of the policy module files, you’ll need to compile the changes into a new policy module file. To do this, copy or link the SELinux Makefile from /etc/selinux/refpolicy to the directory that contains the policy module input files and run the following command to compile the module:

make && make install && make load

Once the make command has completed, you can manually load the modules into the system, using semodule -e.

30.8 Troubleshooting SELinux

By default, if SELinux is the reason why something isn’t 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 service auditd start and put it in the runlevels of your system, using insserv auditd. In Example 30.9: “Example lines from /etc/audit/audit.log you can see a partial example of the contents of /var/log/audit/audit.log

Example 30.9: 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 comm="syslog-ng" name="acpid" dev=sda6 ino=582296 scontext=system_u:system_r:syslogd_t tcontext=system_u:object_r:apmd_log_t tclass=file

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 some default sections. Let’s have a look at the different sections in the last line:

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:

mmi:~ # 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=”syslog-ng”:

the specific command that was associated with that PID

name=”acpid”:

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 that, using audit2allow -w -i filename:

Example 30.10: Analyzing audit messages using audit2allow
mmi:/var/log/audit # audit2allow -w -i testfile
type=AVC msg=audit(1348173901.309:300): avc:  denied  { append } for  pid=1316
comm="syslog-ng" 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.

You can use audit2allow to generate a loadable module to allow this access.

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 30.11: Using audit2allow to see which lines have denied access
mmi:/var/log/audit # audit2allow -i testfile
                                
#============= syslogd_t ==============
allow syslogd_t apmd_log_t:file append;

As the last part, use audit2allow -a -M mymodule to create an SELinux module with the name mymodule that you can load in order to allow the access that was previously denied. 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 30.12: Use audit2allow to create a policy module that will allow the action that was previously denied
mmi:/var/log/audit # audit2allow -i testfile -M blah
******************** IMPORTANT ***********************
To make this policy package active, execute:
                
semodule -i blah.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 just created for you.

30.9 Switching to Enforcing Mode

With everything you've done so far, you still cannot switch SELinux to enforcing mode. This is because of a misconfiguration in the context types for some files. If you switch to enforcing mode now, you can see that many AVC denied messages are written that are related to the tmpfs, and following these messages your system hangs with the message “INIT: Id “1” respawning too fast”.

Example 30.13: The messages that you'll see, just before the system stops, look as follows:
[ 5.595812] type=1400 audit(1361363803.588:3): avc: denied { read write }
                for pid=431 comm=”sh” name=”console” dev=tmpfs ino=2513
                scontext=system_u:system_r:sysadm_t tcontext=system_u:object_r:tmpfs_t
                tclass=chr_file
                [ 5.607734] type=1400 audit(1361363803.604:4): avc: denied { read write } for
                pid=431 comm=”sh” path=”/dev/console” dev=tmpfs ino=2513
                scontext=system_u:system_r:sysadm_t tcontext=system_u:object_r:tmpfs_t
                tclass=chr_file

As you will see, this message is repeated several times.

To fix this problem, reboot your computer in permissive mode. Copy the /var/log/audit/audit.log file to a temporary file (like /var/log/audit/audit.2allow) and remove all lines with the exception of the lines that contain the audit log messages for the errors listed above. Assuming that the name of the log file that you've created is audit.2allow, you should now run the following command: audit2allow -i audit.2allow -M bootme.

This creates a policy module file with the name bootme.pe. Make sure that this module is included in your SELinux configuration by using semodule -i bootme.pp. Now reboot your computer in enforcing mode. You will be able to boot and log in as root in your SELinux-protected system. If this is not the case, you'll have to repeat this procedure until you have no more messages in your audit.log that refer to path=”/dev/console” dev=tmpfs. This may involve several reboots.

From here, the fine tuning begins. You will notice that many items on your system don't work yet. You'll have to fix them one by one. The approach for fixing all of these errors is by using audit2allow as described in the above example, and by setting the appropriate context on files and directories on your system. Until a supported version of the SELinux policy is provided with SUSE Linux Enterprise, you'll have to follow this approach to get it to work. At least using this procedure does allow you to configure a computer with the very detailed security settings that are offered with SELinux and will make your system more secure than when using other solutions.

Print this page