8.2. Using SELinuxSecurity 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 System Figure 8-5. Graphical configuration tool for SELinux![]() There are three possible values for SELinux Setting:
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. 8.2.1.1. Configuring SELinux from the command lineSELinux 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. SELINUX=enforcing # SELINUXTYPE= type of policy in use. Possible values are: # targeted - Only targeted network daemons are protected. # strict - Full SELinux protection. SELINUXTYPE=targeted 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 Enforcing # setenforce permissive # getenforce Permissive # setenforce enforcing # getenforce Enforcing 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 8.2.1.2. Determining which booleans to modifyThe 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
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 defined.") 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.
8.2.1.3. Using file labelsSELinux 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 auto.net -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.
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.
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. 8.2.1.4. Relabeling the systemSome 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. 8.2.1.5. Viewing and interpreting SELinux messagesSELinux 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 /home/chris/public_html
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
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.
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.
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.
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 security.selinux="system_u:object_r:etc_t:s0\000"
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:
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...8.2.3.1. ...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 System 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. SELINUX=enforcing # SELINUXTYPE= type of policy in use. Possible values are: # targeted - Only targeted network daemons are protected. # strict - Full SELinux protection. SELINUXTYPE=mls # SETLOCALDEFS= Check local definition changes SETLOCALDEFS=0 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.
8.2.3.2. ...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?
![]() |