Skip to main content

Four semanage commands to keep SELinux in enforcing mode

Are you avoiding SELinux entirely, or leaving large portions of your systems in permissive mode? Read on to learn how to use the SELinux targeted policy to lock things down but maintain flexibility for custom applications.
Four semanage commands to keep SELinux in enforcing mode
"Going nowhere" by Damian Gadal is licensed under CC BY 2.0

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

All of the semanage commands that add or modify the targeted policy configuration store information in *local files under the /etc/selinux/targeted directory tree. These files all have warnings that they should not be edited directly but are used to preserve customization. When the SELinux and policy packages are updated, these local customization files are left in place and applied to the updated policy.

Topics:   Linux   Security  
Author’s photo

Susan Lauber

Susan Lauber is a Consultant and Technical Trainer with her own company, Lauber System Solutions, Inc. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.