Mandatory Access Control (MAC) with SELinux

Administration

Various tools are available for managing an SELinux system. For example, a utility called getenforce displays the current SELinux mode. setenforce 0|1 lets users change the mode, where 0 represents permissive mode and 1 stands for enforcing mode. Permissive mode means that unauthorized actions are logged but not prohibited, which is useful if you are developing a new policy module. The security server references its policy entries to decide what is permitted. To change a mode permanently, you need an entry in the /etc/selinux/config file (Listing 2).

Listing 2

/etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted

The most interesting tool for SELinux has to be system-config-selinux (Figure 5). It lets admins perform basic settings, such as the SELinux mode, while supporting more complex tasks such as creating new policy modules. You can also configure Booleans, which are simply instructions that enable policy rules you have prepared, without needing the m4 macro language to do so (the whole policy is based on this language).

A variety of predefined Booleans exist; for example, you can allow a web server to access data in user folders (UserDir), or allow the name server to perform changes to the zone file (DDNS). Booleans can typically be displayed at the command line with getsebool. The getsebool -a | grep httpd command, for example, lists all the Booleans for the Apache web server (Listing 3).

Listing 3

getsebool -a | grep httpd

allow_httpd_anon_write --> off
allow_httpd_dbus_avahi --> off
allow_httpd_mod_auth_pam --> off
allow_httpd_sys_script_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_network_connect --> off
httpd_can_network_connect_db --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> on
httpd_ssi_exec --> off
httpd_tty_comm --> on
httpd_unified --> on
httpd_use_cifs --> off
httpd_use_nfs --> off

A number of man pages describe the Booleans for the most popular network services. The httpd_selinux page helps you with the web server.

Also, you can change Booleans at the command line with setsebool. The following command line allows the web server to execute CGI scripts:

setsebool -P httpd_enable_cgi 1

sestatus is an interesting command-line tool that summarizes the current SELinux configuration (Listing 4).

Whereas RHEL 4 had a purely monolithic policy, today, modular variants of the policy are used. This gives administrators a number of advantages. For example, a policy developer no longer needs to worry about the complete policy sources for the SELinux system; it is sufficient to develop a single module for the application you want to protect and to add this module to the system.

The default policy, which is part of the Fedora distribution (Targeted Policy), protects many applications out of the box. The programs protected by the policy are referred to as targeted programs, which explains the policy name. The semodule command returns all available policy modules (Listing 5).

If administrators want to remove a module, and thus SELinux protection for this program, they can simply pass in the module's name with the -r switch:

semodule -r amavis

Doing so permanently removes protection for the specified application, but you can reintroduce the module later. The Policy RPM stores all available standard modules in the /usr/share/selinux/targeted directory. An administrator can reload the Amavis module by calling semodule as follows:

semodule -i /usr/share/selinux/targeted/amavis.pp

The command reloads the Amavis module on the security server running on the kernel. The module's rule set then assumes responsibility for denying or permitting any actions that relate to the Amavis software. If you need a precise overview of which rules the individual modules include, you can install the SRPM (Source RPM) for the policy you are using, or you can simply install the graphical apol tool, which can display binary policy files in clear text format, thus letting you investigate the deployed policy.

If this sounds too complicated, or if you simply need a generic overview of the policy that you have deployed, seinfo is your tool of choice (Listing 6). You can easily see how complex the total rule set actually is.

One feature of the SELinux policy on Fedora 8 is that it now also contains the properties of the older strict policy. To be more precise, it is now possible to use the targeted policy to restrict user accounts (i.e., to implement RBAC). For example, Dan Walsh has released a policy module titled xguest[3]. The module lets the administrator quickly convert any Gnome desktop into a kiosk system. The user is allowed to login as xguest. This user has very limited privileges on the Gnome desktop and a very restricted selection of programs. For example, network access is restricted to the Firefox web browser; all other applications do not have access to the network.

The module also prohibits modifications to the Gnome settings (gconf). This is an ideal environment for kiosk systems, such as those typically found at airports and in hotel lobbies. The xguest policy module can also serve as a starting point for your own development. For example, you could add further instructions to the existing rules to support SSH-based access.

Development

If you prefer to contribute actively to SELinux, rather than just configuring the SELinux policy, Fedora 8 has a number of tools that let you do so. For example, you can modify the binary policy on the fly with the semanage tool without accessing the sources. Of course, you can change every single property in this way, but this approach is typically best for simpler changes.

The SELinux policy gives the Apache web server the ability to bind to specific network ports. These ports are designated as http_port_t types in the SELinux policy. Calling semanage tells you which ports have a label of this kind:

# semanage port -l |grep http_port_t
tcp 80, 443, 488, 8008, 8009

An administrator who wants to apply this label to a new port calls semanage as follows:

semanage port -a -t http_port_t -p tcp 777

Running apol against the policy to find a matching rule reveals the following:

allow httpd_t http_port_t : tcp_socket{ name_bind name_connect };

The rule allows the processes in the httpd_t domain to access any network ports that have the http_port_t label; these ports are now 777, 80, 443, 488, 8008, and 8009.

If you would like to take this idea a step further and create completely new modules of your own, two tools are available to you: system-config-selinux and policygentool. polciygentool is part of the selinux-policy-devel RPM located in the /usr/share/selinux/devel folder. It helps you create the files you will need to generate a binary policy module. A description of the individual steps could easily fill a book, so I'll just give you a rough overview of the required instructions in the following section.

Creating a Policy

First of all, the admin launches a tool and passes in the name of the application you want to protect, along with the name of the policy module to be created:

./policygentool foo /usr/bin/foo

The tool prompts you for a number of details about the application, such as whether it uses an init script, where the log files are stored, and so on.

After you have answered all of these questions, policygentool creates three files – foo.fc, foo.if, and foo.te – which are the file context, type enforcement, and interface files. The file context file allows the administrator to link the application files to an SELinux label; the type enforcement file specifies the matching rules – that is, what the application is allowed to do. The interface file places macros at the disposal of other policy modules.

After you have edited the files, you can then create the policy module with the following entry:

make -f /usr/share/selinux/devel/Makefile

After this step, you should find the new foo.pp file below the current directory. Issuing the semodule -i foo.pp command loads the module into the kernel-based security server.

If this whole process sounds too complex for you, you can always use the graphical front end, system-config-selinux, to create a new policy module. An extensive tutorial for doing so is available online[4].