SELinux provides several utilities for managing security policies and modules, some of which will be briefly described in the Troubleshooting SELinux issues section next. Examining each of these tools is beyond the scope of this chapter, but we'll take semanage for a quick spin, to reflect on some use cases involving security policy management.
The general syntax of the semanage command is as follows:
semanage TARGET [OPTIONS]
TARGET usually denotes a specific namespace for policy definitions (for example, login, user, port, fcontext, boolean, permissive, and so on). Let's look at a few examples to get an idea of how semanage works.
Enabling secure binding on custom ports
Let's assume we want to enable SELinux for a custom SSH port instead of the default 22. We can retrieve the current security records (labels) on the SSH port with the following command:
sudo semanage port -l | grep ssh
For a default configuration, we will get the following output:
Figure 21 – Querying the SELinux security label for the SSH port
If we want to enable SSH on a different port (such as 2222), first, we need to configure the related service (sshd) to listen on a different port. We won't go into those details here. Here, we need to enable the secure binding on the new port with the following command:
sudo semanage port -a -t ssh_port_t -p tcp 2222
Here's a brief explanation of the preceding command:
- -a (--add): Adds a new record (label) for the given type
- -t ssh_port_t: The SELinux type of the object
- -p tcp: The network protocol associated with the port
As a result of the previous command, the new security policy for the ssh_port_t type looks like this:
Figure 22 – Changing the SELinux security label for the SSH port
We could arguably delete the old security label (for port 22), but that won't really matter if we disable port 22. If we want to delete a port security record, we can do so with the following command:
sudo semanage port -d -p tcp 22
We used the -d (--delete) option to remove the related security label. To view the local customizations for our semanage port policies, we can invoke the -C (--locallist) option:
sudo semanage port -l -C
For more information on semanage port, you may refer to the related system reference (man semanage port). Next, we'll look at how to modify security permissions for specific server applications.
Modifying security permissions for targeted services
semanage uses the boolean namespace to toggle specific features of targeted services on and off. A targeted service is a daemon with built-in SELinux protection. In the following example, we want to enable FTP over HTTP connections. By default, this security feature of Apache (httpd) is turned off. Let's query the related httpd security policies:
sudo semanage boolean -l | grep httpd | grep ftp
We get the following output:
Figure 23 – Querying httpd policies related to FTP
As we can see, the related feature – httpd_enable_ftp_server – is turned off by default. The current and persisted states are currently off: (off, off). We can enable it with the following command:
sudo semanage boolean -m --on httpd_enable_ftp_server
To view the local customizations of the semanage boolean policies, we can invoke the -C (--locallist) option:
sudo semanage boolean -l -C
The new configuration now looks like this:
Figure 24 – Enabling the security policy for FTP over HTTP
In the preceding example, we used the -m (--modify) option with the semanage boolean command to toggle the httpd_enable_ftp_server feature.
For more information on semanage boolean, you may refer to the related system reference (man semanage boolean). Now, let's learn how to modify the security context of specific server applications.
Modifying security contexts for targeted services
In this example, we want to secure SSH keys stored in a custom location on the local system. Since we're targeting a filesystem-related security policy, we will use the fcontext (file context) namespace with semanage.
The following command queries the file context security settings for sshd:
sudo semanage fcontext -l | grep sshd
Here's a relevant excerpt from the output:
Figure 25 – The security context of SSH keys
The following command also adds the /etc/ssh/keys/ path to the secure locations associated with the sshd_key_t context type:
sudo semanage fcontext -a -t sshd_key_t '/etc/ssh/keys(/.*)?'
The '/etc/ssh/keys(/.*)?' regular expression matches any files in the /etc/ssh/keys/ directory, including subdirectories at any nested level. To view the local customizations of the semanage fcontext policies, we can invoke the -C (--locallist) option:
sudo semanage fcontext -l -C
We should see our new security context:
Figure 26 – The modified security context of our SSH keys
We should also initialize the filesystem security context of the /etc/ssh/keys directory (if we've already created it):
sudo restorecon -r /etc/ssh/keys
restorecon is an SELinux utility for restoring the default security context to a filesystem object. The -r (or -R) option specifies a recursive action on the related path.
For more information on semanage fcontext, you may refer to the related system reference (man semanage fcontext). Next, we'll look at enabling permissive mode for specific server applications.
Enabling permissive mode for targeted services
Earlier in this chapter, we created a custom daemon (packtd) with its security policy. See the related topic in the Creating an SELinux security policy section. When we worked on the packtd daemon and tested its functionality, initially, we had to deal with its SELinux policy violations. Eventually, we fixed the required security policy context and everything was fine. During the entire process, we were able to run and test with packtd without having the daemon shut down by SELinux due to non-compliance. Yet, our Linux system runs SELinux in enforcing mode (by default) and is not permissive. See the Understanding SELinux modes section for more information on enforcing and permissive modes.
How, then, is it possible that packtd ran unrestricted while violating security policies?
By default, SELinux is permissive to any untargeted type in the system. By untargeted, we mean a domain (type) that hasn't been forced into a restrictive (or confined) mode yet.
When we built the security policy for our packtd daemon, we let the related SELinux build tools generate the default type enforcement file (packt.te) and other resources for our domain. A quick look at the packt.te file shows that our packtd_t type is permissive:
Here's the relevant excerpt from the file:
Figure 27 – The packtd_t domain is permissive
So, the packtd_t domain is permissive by nature. The only way to confine packtd is to remove the permissive line from the packtd.te file and rebuild the related security policy. We will leave that as an exercise to you. The case we wanted to make here was to present a possibly misbehaving – in our case, permissive – domain that we can catch by managing permissive types with the semanage permissive command.
To manage permissive mode for individual targets, we can use the semanage command with our permissive namespace. The following command lists all the domains (types) currently in permissive mode:
sudo semanage permissive -l
In our case, we have the built-in packtd_t domain, which is permissive:
Figure 28 – Displaying permissive types
In general, it is unlikely that a default SELinux configuration would have any permissive types.
We can use the semanage permissive command to temporarily place a restricted domain into permissive mode while testing or troubleshooting a specific functionality. For example, the following command sets the Apache (httpd) daemon in permissive mode:
sudo semanage permissive -a httpd_t
When we query for permissive types, we get the following result:
Figure 29 – Customized permissive types
Domains or types that are made permissive with the semanage permissive command will show up as Customized Permissive Types.
To revert the httpd_t domain to the confined (restricted) state, we can invoke the semanage permissive command with the -d (--delete) option:
sudo semanage permissive -d httpd_t
Note that we cannot confine built-in permissive types with the semanage command. As we mentioned previously, the packtd_t domain is permissive by nature and cannot be restricted.