Previous Page
Next Page

8.2. Using SELinux

Security Enhanced Linux (SELinux) is installed and enabled by default in Fedora Core. SELinux controls what a program is and is not allowed to do, enforcing security policy through the kernel. This prevents an attacker from using a compromised program to do something it was not intended to do.

Although SELinux can at times be challenging to configure, it dramatically improves protection against some common system attacksso a little bit of effort can pay off in a big way.

8.2.1. How Do I Do That?

SELinux is managed using the same graphical tool used to manage the firewall. Click SystemAdministration"Security Level and Firewall" to start it, then select the SELinux tab, shown in Figure 8-5.

Figure 8-5. Graphical configuration tool for SELinux

There are three possible values for SELinux Setting:


Fully enables SELinux. Any attempted operation that violates the current security policy is blocked.


Enables SELinux security checks but does not enforce the security policy; operations that violate the current security policy are permitted, but an error message is logged to record the event. This is useful if you have previously disabled SELinux and want to evaluate the potential impact before you enable it.


Completely disables SELinux.

If you enable SELinux (using Enforcing or Permissive mode), expand the Modify SELinux Policy section by clicking the triangle. The SELinux policy configuration categories will appear, as shown in Figure 8-6.

Figure 8-6. SELinux policy configuration categories

Each of these categories contains a number of options (represented as checkboxes) called booleans. Each boolean may be set on (checked) or off (unchecked).

To expand the options in any category, click on the arrow in front of that category. In Figure 8-6, the Admin category has been expanded, and the window width has been resized to fully show each option.

After selecting or deselecting booleans as desired, click OK. Changes in boolean values will take effect immediately, but changing the SELinux setting to or from Disabled will take effect only when the system is booted. Configuring SELinux from the command line

SELinux can also be configured very easily from the command line. To enable SELinux, edit the file /etc/selinux/config and set the SELINUX value to enforcing, permissive, or disabled:

# 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 - SELinux is fully disabled.
# SELINUXTYPE= type of policy in use. Possible values are:
#       targeted - Only targeted network daemons are protected.
#       strict - Full SELinux protection.

Changes made to this file will take effect when the system is booted. If SELinux is enabled, you can use the getenforce command to view the current mode, and you can use the setenforce command to immediately switch between enforcing and permissive modes:

# getenforce
# setenforce permissive
# getenforce
# setenforce enforcing
# getenforce

Boolean valuescorresponding to the checkboxes in the graphical Security Level configuration toolcan be viewed with the getsebool command, using the -a option to see all values:

$ getsebool -a
NetworkManager_disable_trans --> off
allow_cvs_read_shadow --> off
allow_execheap --> off
allow_execmem --> on
...(Lines snipped)...
ypserv_disable_trans --> off
ypxfr_disable_trans --> off
zebra_disable_trans --> off

You can also specify a specific boolean:

$ /usr/sbin/getsebool httpd_enable_cgi
httpd_enable_cgi --> on

To temporarily set a boolean value, use the setsebool command:

# setsebool httpd_enable_cgi 1
# setsebool httpd_enable_homedirs=0

Notice that the on/off state of the boolean is expressed numerically, with 1 representing on and 0 representing off. Also note that the boolean name and value may be specified as two arguments (first example), or they may be specified as a single argument, joined with the = symbol (second example). If you use the second form, you can set multiple booleans with one command:

# setsebool httpd_enable_cgi=1 httpd_enable_homedirs=0

Changes made to boolean values with setsebool take effect immediately but are not permanent; they will reset at the next boot. To make them permanent, add the -P argument:

# setsebool -P httpd_enable_cgi=1 Determining which booleans to modify

The default boolean settings for SELinux are reasonable for most systems, but they may need to be changed to relax the security policy for specific applications.

For example, by default, web scripts are not permitted to communicate through the network; this prevents an untrusted script from somehow transferring private data to another host. But if your web scripts need to connect to an IMAP email server or an SQL database such as MySQL or PostgreSQL, you'll need to set the appropriate boolean.

In this case, you can find the boolean in the graphical interface by expanding the HTTPD Service category and looking through the options. Select the checkbox for the boolean labeled "Allow HTTPD scripts and modules to connect to the network."

There is also a manpage provided for each of the most popular servers protected by SELinux. These manpages are named service _selinux; for example, to access a description of the SELinux booleans that affect httpd, view the httpd_selinux manpage:

$ man httpd_selinux

To see a list of all the service-specific manpages for SELinux, enter the command:

$ apropos _selinux

In the BOOLEAN section you will find this text:

       httpd scripts by default are not allowed to connect out to the network.
              This would prevent a hacker from breaking into you httpd  server
              and attacking other machines.  If you need scripts to be able to
              connect you can set the httpd_can_network_connect boolean on.

              setsebool -P httpd_can_network_connect 1

To translate between the descriptions shown in the graphical Security Level Configuration tool and the boolean names used by setsebool and getsebool, use the file /usr/share/system-config-securitylevel/selinux.tbl, which looks like this:

unlimitedUtils _("Admin") _("Allow privileged utilities like hotplug and insmod to run unconfined.")
unlimitedRC _("Admin") _("Allow rc scripts to run unconfined, including any daemon started by an rc script that does not have a domain transition explicitly
unlimitedRPM _("Admin") _("Allow rpm to run unconfined.")
staff_read_sysadm_file _("Admin") _("Allow staff_r users to search the sysadm home dir and read files (such as ~/.bashrc)")
direct_sysadm_daemon _("Admin") _("Allow sysadm_t to directly start daemons")
...(Lines snipped)...

Each line consists of the boolean name used by setsebool/getsebool, followed by the configuration category and the description used by the Security Level Configuration tool.

Use grep with a server name, boolean name, or a description from the configuration tool to quickly find values in this file:

$ cd /usr/share/system-config-securitylevel
$ grep httpd selinux.tbl
httpd_enable_cgi _("HTTPD Service") _("Allow HTTPD cgi support")
httpd_can_network_connect _("HTTPD Service") _("Allow HTTPD scripts and modules to connect to the network.")
httpd_enable_homedirs _("HTTPD Service") _("Allow HTTPD to read home directories")
httpd_ssi_exec _("HTTPD Service") _("Allow HTTPD to run SSI executables in the same domain as system CGI scripts.")
httpd_builtin_scripting _("HTTPD Service") _("Allow HTTPD to support built-in scripting")
httpd_disable_trans _("HTTPD Service") _("Disable SELinux protection for httpd daemon")
httpd_suexec_disable_trans _("HTTPD Service") _("Disable SELinux protection for http suexec")
httpd_unified _("HTTPD Service") _("Unify HTTPD handling of all content files.")
httpd_tty_comm _("HTTPD Service") _("Unify HTTPD to communicate with the terminal.  Needed for handling certificates.")
$ grep "Allow ftp to read/write files in the user home directories" selinux.tbl
ftp_home_dir _("FTP") _("Allow ftp to read/write files in the user home directories")
$ grep unlimitedRPM selinux.tbl
unlimitedRPM _("Admin") _("Allow rpm to run unconfined.")

Table 8-1 contains some of the most commonly altered SELinux booleans.

Table 8-1. Commonly altered SELinux booleans
Boolean nameDescription in system-config-securitylevelReason for alteringDefault value

Allow sysadm_t to debug or ptrace applications.Permit root to use tools such as gdb for debugging.Off

Allow the use of shared libraries with Text Relocation.Required to use Adobe Flash browser plug-in and Sun Java.Off

Permits the FTP server to write to files labeled with type public_content_rw_t, described in Table 8-2.Off

Allow httpd scripts and modules to connect to the network.Enables web scripts to connect to databases and mail servers.Off

Allow httpd to read home directories.Enables the use of ~/public_html for personal web pages.Off

Unify httpd to communicate with the terminal. Needed for handling certificates.Enables the use of certificates with passphrases (requires the passphrase to be entered on the terminal).Off

Permits Apache to write to files labeled with type public_content_rw_t (see Table 8-2).Off

Allow named to overwrite master zone files.Required for dhcpd updating of zones.Off

Allow reading on any NFS filesystem.Enables NFS file sharing (read-only).Off

Allow read/write/create on any NFS filesystem.Enables NFS file sharing (read/write).Off

Support NFS home directories.Allows home directories (such as /home/chris) to be imported from an NFS server.Off

Allow Samba to share users' home directories.Allows homes shares in smb.conf.Off

Allow users to log in with CIFS home directories.Allows home directories (such as /home/chris) to be imported from a Samba or Windows server.Off

Permits Samba to write to files labeled with type public_content_rw_t.Off

Allow Spam Assassin daemon network access.Enables the use of real-time blackhole lists (RBLs) by Spam Assassin.Off

Allow SSH logins as sysadm_r:sysadm_t.Allows root login via SSH (otherwise, you'll need to log in as a regular user and then use su). This may be required if you're running remote backups via SSH.Off

Disable SELinux protection for subsystem.Use this as a last alternative. It's better to disable SELinux protection for one subsystem than to turn it off entirely. Off Using file labels

SELinux uses file labels to specify an SELinux context for each file. To display the context labels, use the -Z or --context options to ls:

$ ls -Z /etc
-rw-r--r--  root     root     system_u:object_r:etc_t          a2ps.cfg
-rw-r--r--  root     root     system_u:object_r:etc_t          a2ps-site.cfg
drwxr-xr-x  root     root     system_u:object_r:etc_t          acpi
-rw-r--r--  root     root     system_u:object_r:adjtime_t      adjtime
drwxr-xr-x  root     root     system_u:object_r:etc_t          alchemist
-rw-r--r--  root     root     system_u:object_r:etc_aliases_t  aliases
-rw-r-----  root     smmsp    system_u:object_r:etc_aliases_t  aliases.db
drwxr-xr-x  root     root     system_u:object_r:etc_t          alsa
drwxr-xr-x  root     root     system_u:object_r:etc_t          alternatives
-rw-r--r--  root     root     system_u:object_r:etc_t          anacrontab
-rw-------  root     root     system_u:object_r:etc_t          at.deny
-rw-r--r--  root     root     system_u:object_r:automount_etc_t auto.master
-rw-r--r--  root     root     system_u:object_r:automount_etc_t auto.misc
-rwxr-xr-x  root     root     system_u:object_r:automount_etc_t
-rwxr-xr-x  root     root     system_u:object_r:automount_etc_t auto.smb
...(Lines snipped)...

The context label displayed on each line contains the text system_u:object_r: followed by the file type assigned to the file. In the output above, the aliases file has been given the file type etc_aliases_t (which is unique to that file), indicating that the SELinux policy treats that file specially.

All file types end in _t for easy identification.

Files contained in your home directory are usually given the type user_home_t. The default policy will not permit web pages in ~/public_html to be accessed through the web server, even if the httpd_enable_homedirs boolean is turned on, unless the files being shared have the type httpd_sys_content_t. To change file contexts, use the chcon command:

$ chcon -R -t httpd_sys_content_t ~/public_html

The -R option causes chcon to recursively change the context of directories within ~/public_html, and -t httpd_sys_content_t sets the file type.

The file context types most commonly used with chcon are shown in Table 8-2.

Table 8-2. Common nondefault file context types

Files that may be served by httpd Web pages, graphics, CSS files, client-side ECMAScript/JavaScript

CGI scripts that may be executed by httpd Web scripts written in any external scripting language (e.g., scripts written in Perl when you are not using mod_perl)

CGI scripts that will not be constrained by SELinuxDangerous!but may be required for some complex CGI scripts

Datafiles that may be read (but not written) by CGI scriptsStatic CGI script datafiles

Datafiles that may be read and appended (but not overwritten or truncated) by CGI scriptsScript logfiles, guestbooks, nonrevisable order queues, survey and quiz records

Datafiles that may be read/written by CGI scriptsUser profiles, session status, and other CGI datafiles

Enables sharing of the file by Samba (not required for home directories)Group Samba shares

Enables sharing of the file (read only) by Samba, httpd, NFS, and rsync Files shared by multiple servers

Enables sharing of the file (read/write) by Samba, httpd, FTP, and rsync Files shared and updatable through multiple servers

A file label that has been changed manually may be changed back to the default value during a relabeling (discussed in the next section).

For example, if you have created the /var/samba directory and are using it for Samba group shares, it will need to be labeled with the type samba_share_t:

# chcon -R -t samba_share_t /var/samba

To make that the default context label for /var/samba, edit /etc/selinux/targeted/contexts/files/file_contexts.local to contain this line:

/var/samba(/.*)?      system_u:object_r:samba_share_t

The first field contains a regular expression specifying that this entry will match any filename starting with /var/samba. The context label in the second field (which must include the system_u:object_r: portion) configures the default label for files that match the regular expression. Relabeling the system

Some caution is in order: you may end up with a system where many file labels are wrong if you update your SELinux policy, mount your filesystems without SELinux support enabled (perhaps during rescue mode), or go wild with chcon. To relabel your system, you should create the empty file /.autorelabel and then boot the system:

# touch /.autorelabel
# shutdown -r now

During system startup, your files will be relabeled to default values, except for files labeled with a type listed in /etc/selinux/targeted/contexts/customizable_types. The relabeling operation will typically take a few minutes on a desktop system or small server, and could take much longer on a large server or very old computer. Viewing and interpreting SELinux messages

SELinux policy messages are sent to syslog and usually end up in /var/log/messages. To find them among the other messages, search for the string avc:

# grep avc: /var/log/messages
May  2 16:32:56 laptop3 kernel: audit(1146601976.667:289): avc:  
denied  { getattr } for  pid=23807 comm="httpd" name="public_html" dev=dm-1
ino=192237 scontext=user_u:system_r:httpd_t:s0
tcontext=user_u:object_r:user_home_t:s0 tclass=dir

Here we see that an access request was denied between a subject with an scontext of user_u:system_r:httpd_t:s0 and a tcontext of user_u:object_r:user_home_t:s0 for the tclass dir (a filesystem directory). The additional fields provide a bit more information: the attempted operation was getattr (get attributes), the process ID of the subject was 23807, the command executing was httpd, the directory name was public_html, the storage device was dm-1, and the inode number was 192237.

The fact that the storage device name starts with dm (which stands for device mapper) indicates that the directory is stored in a logical volume. You can find the device number from a detailed listing of the device node:

$ ls -l /dev/dm-1
brw-r-----  1 root disk 253, 1 Apr 29 08:57 /dev/dm-1

The output indicates that the device number is 253, 1. Compare this with the device nodes in /dev/mapper:

$ ls -l /dev/mapper
total 0
crw-------  1 root root  10, 63 Apr 29 08:57 control
brw-rw----  1 root disk 253,  1 Apr 29 08:57 main-home
brw-rw----  1 root disk 253,  3 Apr 29 08:57 main-remote
brw-rw----  1 root disk 253,  0 Apr 29 08:57 main-root
brw-rw----  1 root disk 253,  4 Apr 29 08:57 main-test
brw-rw----  1 root disk 253,  2 Apr 29 08:57 main-var

According to this output, /dev/dm-1 corresponds to /dev/mapper/main-home, which refers to the logical volume home within the volume group main. The mount command shows the mount point for this volume:

$ mount
/dev/mapper/main-root on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/hdc2 on /boot type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw)
/dev/mapper/main-home on /home type ext3 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
automount(pid10695) on /net type autofs (rw,fd=4,pgrp=10695,minproto=2,maxproto=4)

We know that the directory filename is public_html, but we don't know the full pathname of the directory. Passing the mount point and inode number to find will reveal the pathname:

# find /home -xdev -inum 192237

The -xdev argument limits the search to a single filesystem.

So now we know that httpd (Apache) was unable to access the directory /home/chris/public_html.

The command audit2why will attempt to decode SELinux error messages:

# grep avc: /var/log/messages|audit2why
May  2 16:32:56 laptop3 kernel: audit(1146601976.667:289): avc:  denied  { getattr } for  pid=23807 comm="httpd" name="public_html" dev=dm-1 ino=192237 scontext=user_u:system_r:httpd_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=dir
        Was caused by:
                Missing or disabled TE allow rule.
                Allow rules may exist but be disabled by boolean settings; 
                check boolean settings.
                You can see the necessary allow rules by running audit2allow 
                with this audit message as input.

This explanation is not very informative, but it does tell us that there is no type enforcement rule to allow this access, and that may be because of a boolean setting. Viewing the manpage for httpd_selinux gives information about the necessary boolean setting, along with the required context label:

       httpd by default is not allowed to access users home directories.
       If you want to allow access to users home directories you  need  to
       set the httpd_enable_homedirs boolean and change the context of the 
       files that you want people to access off the home dir.

              setsebool -P httpd_enable_homedirs 1
              chcon -R -t httpd_sys_content_t ~user/public_html

Issuing the commands given in the manpage fixes the problem. Here I've substituted the actual user's name into the chcon argument:

# setsebool -P httpd_enable_homedirs
# chcon -R -t httpd_sys_content_t ~chris/public_html

Fedora Core 6 includes the first release of the setroubleshoot tool, which provides a desktop notification of AVC denials as well as a GUI program for analyzing AVC messages. To use this tool, install the setroubleshoot package.

8.2.2. How Does It Work?

The Linux kernel provides the Linux Security Module (LSM) interface to enable additional access controls to be added to operations. These interfaces provide connections, or hooks, into the system call code used by processes to request that the kernel perform an operation, such as opening a file, sending a signal to another process, or binding to a network socket.

SELinux uses these hooks to permit or deny requests made by a process (subject) on a resource (such as a file, network socket, or another process, called an object). These controls are called mandatory access controls (MAC) because they enforce a consistent security policy across the entire system. This stands in contrast to the traditional Unix/Linux file permissions, which are considered discretionary access controls (DAC) because the access settings are left to each user's discretion.

SELinux does not override permissions; access to a resource must be permitted by all security mechanismsincluding SELinux, permission modes, ACLs, mount options, and filesystem attributesbefore it will be granted.

An SELinux policy defines the rules used to make each access decision. There are three inputs into each decision: the security context of the source subject, and the security context and class of the target object.

Each security context consists of four parts: a user, a role, a type, and a sensitivity. In order to track this information, SELinux assigns a label to each subject and object.

You can view the context of processes by using the -Z (or --context) argument with the ps command:

$ ps -e -Z
LABEL                             PID TTY          TIME CMD
system_u:system_r:init_t            1 ?        00:00:02 init
system_u:system_r:kernel_t          2 ?        00:00:00 ksoftirqd/0
system_u:system_r:kernel_t          3 ?        00:00:00 watchdog/0
system_u:system_r:kernel_t          4 ?        00:00:00 events/0
...Lines snipped...
user_u:system_r:unconfined_t    24168 pts/2    00:00:00 bash
user_u:system_r:unconfined_t    24228 pts/2    00:00:00 ps
user_u:system_r:unconfined_t    24229 pts/2    00:00:00 tail

This information is also displayed by the GNOME System Monitor, as shown in Figure 8-7.

If you've added the System Monitor applet to your GNOME panel, clicking on it will start the GNOME System Monitor. You can also start it using the menu entry ApplicationsSystem ToolsSystem Monitor, or by typing the command gnome-system-monitor.

Figure 8-7. GNOME System Monitor display showing the security contexts of processes

The label on the init process (highlighted in Figure 8-7) indicates that the user is system_u, the role is system_r, and the type is init_t. The sensitivity is not shown in this output. This label defines the source security context (scontext) because the init process is a source of system access requests.

_t indicates a type, _r indicates a role, and _u indicates a user.

When init attempts to read the configuration file /etc/inittab, the label on that file defines the target security context (tcontext):

$ ls -Z /etc/inittab
-rw-r--r--  root     root     system_u:object_r:etc_t          /etc/inittab

Context labels on files are stored in the file's attributes, and therefore SELinux can be used only on filesystems that support these attributes: ext2, ext3, and XFS. Other filesystems, such as ReiserFS, JFS, ISO9660, and VFAT do not support these attributes yet.

You can view the context labels as a file attribute using the getfattr command, specifying the security.selinux attribute name:

# getfattr -n security.selinux /etc/hosts
getfattr: Removing leading '/' from absolute path names
# file: etc/hosts

The last portion of the security.selinux attribute is the sensitivity level, which is used only for multilevel security (MLS) and multicategory security (MCS). The \000 at the end of the attribute indicates an ASCII NUL character, used to delimit the end of the attribute in traditional C style.

The target class (tclass) associated with the object being accessed is determined by the type of object (and in some cases, how it is being accessed); in this example, where init is attempting to access /etc/inittab, the tclass is file. Therefore the SELinux policy is checked to see if access is permitted for an scontext of system_u:system_r:init_t, a tcontext of system_u:object_r:etc_t, and a tclass of file. To speed access, SELinux rules are cached in an area of memory called the access vector cachewhich explains why SELinux error messages are labeled avc.

The Fedora project has three policies available:


The default policy installed with Fedora Core. This policy is targeted for the protection of the most frequently attacked portions of the system, including most network services. Programs that are not targeted are unconstrained by SELinux.


This policy denies every action except those explicitly permitted. Although this should be more secure than the targeted policy, it's hard to create a policy that encompasses all possible configurations of all programs that can be installed on a Fedora system, and attempting to use this policy has frustrated many system administrators into turning off SELinux altogether. In other words, the targeted policy is often more secure simply because it's more likely to be used.


Experimental policy to support multilevel security ( MLS). This is important for some government certifications and is not widely used outside of government. (The future MCS framework appearing in the targeted policy will use specific features of MLS for a type of discretionary access control).

In the default targeted policy, the role element of the security context is not used (all subjects are system_r, and all objects are object_r), and very few users are defined (just system_u, user_u, and root).

SELinux policies are difficult and time-consuming to write, and even more difficult to write well. Nonetheless, they have to be customized to suit the particular needs of each site. The SELinux booleans provide a compromise between complexity and flexibility, by enabling policy options to be configured without editing, compiling, and retesting the policy code.

The SELinux technology was originally developed by the U.S. National Security Agency (NSA), with several partner organizations. The kernel components of SELinux have been incorporated into the main Linux kernel releases. The Fedora project utilizes those kernel components along with customized policy and some user tools (such as versions of ls and ps that include the -Z options, and SELinux-specific tools such as chcon and getenforce, and the graphical configuration tool system-config-securitylevel). Red Hat is a major contributor to SELinux development.

8.2.3. What About... ...using the strict or MLS policies?

These alternate policies are provided as RPM packages and are installed using yum:

# yum install selinux-policy-strict selinux-policy-mls

Switch between the installed policies using the graphical configuration tool ( system-config-securitylevel from the command line, or SystemAdministration"Security Level and Firewall" from the menu). When more than one policy is installed, a drop-down menu for Policy Type appears on the SELinux tab, as shown in Figure 8-8. When you change the policy, the warning dialog shown at bottom left of Figure 8-8 will appear, informing you that the policy change will cause the filesystem to be relabeled. Click Yes to approve the relabeling, and then click OK in the Security Level Configuration window. Reboot to activate the new policy.

Figure 8-8. Selecting policy using the Security Level Configuration tool

To change the policy from the command prompt, edit /etc/selinux/config and change the SELINUXTYPE value to the policy of your choice (targeted, strict, or mls):

# 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 - SELinux is fully disabled.
# SELINUXTYPE= type of policy in use. Possible values are:
#       targeted - Only targeted network daemons are protected.
#       strict - Full SELinux protection.

# SETLOCALDEFS= Check local definition changes

Then create the empty file /.autorelabel to ensure that the filesystem will be relabeled when the system is booted:

# touch /.autorelabel

Reboot to activate the change.

Fedora development is focused on the targeted policy. Changing the policy may lead to a number of unexpected system problems! ...booting with SELinux disabled?

If you have SELinux enabled, but your system cannot boot successfully due to an SELinux problem, you may need to temporarily disable it while you investigate.

To boot with SELinux disabled, append selinux=0 to the boot options.

8.2.4. Where Can I Learn More?

Previous Page
Next Page