For years, SELinux has assisted in preventing damage to systems from zero-day exploits. This tool is also useful for virtual machine isolation and is required for container isolation. Yet SELinux is still commonly disabled or placed in permissive mode.

SELinux’s targeted policy is designed to isolate various process domains while still allowing interaction between services as needed. Just a few commands are needed for an administrator to configure a system to use this policy with their customized applications, keeping SELinux in enforcing mode.

[Learn more about using the SELinux policy documentation here.]

The semanage command is used to adjust file contexts, port contexts, and booleans. If there is still a conflict with a particular process, that domain can be placed into permissive mode until further investigation can be completed. This leaves the rest of the system protected in enforcing mode.

With just the four semanage commands below, most systems can be configured so your customized applications run with SELinux in enforcing mode.

The semanage boolean command

The targeted policy includes many booleans to enable and disable sets of allow rules, making the assumption that services have multiple use cases and are run differently in each environment. The use of booleans allows different rule sets for different use cases: A web server in an academic environment may need to allow students to publish content from their home directories, while a corporate, public-facing site may need to refuse access to any user home directories, limit SSI executables, and display data stored on an NFS share.

The httpd_selinux man page describes the use of all booleans provided for the httpd domain as well as sample setsebool commands to persistently enable each boolean. An alternate (and newer) way to see and change these booleans is with the semanage boolean command.

The -l option lists all the booleans in the loaded policy. You can then filter for a keyword:

$ sudo semanage boolean -l | grep httpd httpd_anon_write (off , off) Allow httpd to anon write httpd_builtin_scripting (on , on) Allow httpd to builtin scripting httpd_can_check_spam (off , off) Allow httpd to can check spam httpd_can_connect_ftp (off , off) Allow httpd to can connect ftp httpd_can_connect_ldap (off , off) Allow httpd to can connect ldap

This output includes the name of the boolean, the current and persistent state of the boolean, and a brief description of how the boolean is used.

To change the boolean with semanage use:

$ sudo semanage boolean -m --off httpd_ssi_exec

You can also list the locally customized booleans by adding the -C option:

$ sudo semanage boolean -l -C SELinux boolean State Default Description httpd_ssi_exec (off , off) Allow httpd to ssi exec virt_sandbox_use_all_caps (on , on) Allow virt to sandbox use all caps virt_use_nfs (on , on) Allow virt to use nfs

The man pages for each SELinux domain have descriptions of all provided booleans for those domains. For more options when modifying SELinux booleans with semanage , see the semanage-boolean man page.

You can automate these semanage commands with their related Ansible modules and roles. The Ansible module for semanage boolean is seboolean . This, and the related modules described below, are used by the roles provided by the linux-system-roles package in Fedora or rhel-system-roles package in Red Hat Enterprise Linux. The Red Hat package is available beginning with Red Hat Enterprise Linux 7.4 and can be found in the "Extras" repository.

The semanage fcontext command

The targeted policy provides file context information for application file—including data, log, and runtime files—default and common alternate locations. These context definitions are the mappings that the restorecon command uses to verify or change file context.

The semanage fcontext command can be used to list file context definitions, and add more. The -l option shows all of the contexts in the loaded policy. You can then filter for a keyword:

$ sudo semanage fcontext -l | grep sshd /etc/rc\.d/init\.d/sshd regular file system_u:object_r:sshd_initrc_exec_t:s0 /etc/ssh/primes regular file system_u:object_r:sshd_key_t:s0 /etc/ssh/ssh_host.*_key regular file system_u:object_r:sshd_key_t:s0 /etc/ssh/ssh_host.*_key\.pub regular file system_u:object_r:sshd_key_t:s0 /usr/lib/systemd/system/sshd-keygen.* regular file system_u:object_r:sshd_keygen_unit_file_t:s0

This output includes the regular expression pattern for the target filenames, the type of file, and the file context to assign to the matching filename.

The related man page, in this case man sshd_selinux , includes a list of managed files and a description of each file context available for the domain. There are also sample commands to specify and apply alternate labeling.

For example, if you wanted to store the sshd host keys in a separate subdirectory, you could run the following two commands:

$ sudo semanage fcontext -a -t sshd_key_t '/etc/ssh/keys(/.*)?' $ sudo restorecon -r /etc/ssh/keys

In this example, the regular expression will match the directory /etc/ssh/keys as well as any subdirectories and files found in the /etc/ssh/keys directory.

Just like the booleans, you can view any locally-customized file contexts by adding the -C option:

$ sudo semanage fcontext -l -C SELinux fcontext type Context /usr/share/dnfdaemon/dnfdaemon-system all files system_u:object_r:rpm_exec_t:s0

For more options when modifying SELinux file contexts, see the semanage-fcontext man page.

You can automate the semanage fcontext command with the Ansible sefcontext module. The restorecon command will still need to be run with a separate command module. See ansible-doc sefcontext for examples. The selinux system role includes both tasks.

The semanage port command

In addition to file contexts, the targeted policy also defines port contexts. Just as with the booleans and file contexts, the domain-specific man pages list the defined types, and may also show the sample commands needed to run a service on a different port.

View the port contexts with:

$ sudo semanage port -l | grep http http_cache_port_t tcp 8080, 8118, 8123, 10001-10010 http_cache_port_t udp 3130 http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000 pegasus_http_port_t tcp 5988 pegasus_https_port_t tcp 5989

When running a service on a custom port, you must change the configuration file for the service and also add an SELinux port definition. Without the port definition, the service will fail to start and log an error similar to "cannot bind to port".

Add a port definition with:

$ sudo semanage port -a -t http_cache_port_t -p tcp 8010

When specifying the port, you must include both the protocol and the port number. Additionally, only one type can be defined for each protocol and port number. For more options when modifying SELinux port contexts, see the semanage-port man page.

You can automate the semanage-port command with the seport Ansible module.

The semanage permissive command

Instead of moving the entire system to permissive mode—or worse, disabling SELinux completely—you can place a single domain into permissive mode. A domain in permissive mode allows all actions while still logging any would be denials. The other domains on the system remain in enforcing mode, which both logs and denies actions which are not specifically allowed.

The man pages for common domains list the SELinux types that can be placed into permissive mode.

To list any domains currently in permissive mode use:

$ sudo semanage permissive -l

At initial installation, it is unlikely that there will be any domains in permissive mode.

To place a domain into permissive mode use:

$ sudo semanage permissive -a squid_t

The -d option deletes a permissive domain, thus reenabling enforcing mode for that domain.

For more options when placing domains into permissive mode, see the semanage-permissive man page.

The Ansible selinux_permissive module can be used to place a domain into permissive mode. See ansible-doc selinux_permissive for examples.

The files