With SELinux enabled, processes and files are labeled with a context containing additional SELinux-specific information, such as user, role, type, and level (optional). The context data serves for SELinux access control decisions.
SELinux adds the -Z option to the ls, ps, and other commands, thus displaying the security context of filesystem objects, processes, and more.
Let's create an arbitrary file and examine the related SELinux context:
touch afile ls -Z afile
The output is as follows:
Figure 15 – Displaying the SELinux context of a file
The SELinux context has the following format – a sequence of four fields, separated by a colon (:):
We will explain SELinux context fields.
The SELinux user is an identity known to the policy that's authorized for a specific set of roles and has a particular level that's designated by an MLS/MCS range (see the SELinux level section for more details). Every Linux user account is mapped to a corresponding SELinux user identity using an SELinux policy. This mechanism allows regular Linux users to inherit the policy restrictions associated with SELinux users.
A process owned by a Linux user receives the mapped SELinux user's identity to assume the corresponding SELinux roles and levels.
The following command displays a list of mappings between Linux accounts and their corresponding SELinux user identities. The command requires superuser privileges. Also, the semanage utility is available with the policycoreutils package, which you may need to install on your system:
sudo semanage login -l
The output may slightly differ from system to system:
Figure 16 – Displaying the SELinux user mappings
For more information on the semanage command-line utility, you may refer to the related system reference (man semanage, man semanage-login).
SELinux roles are part of the RBAC security model, and they are essentially RBAC attributes. In the SELinux context hierarchy, users are authorized for roles, and roles are authorized for types or domains. In the SELinux context terminology, types refer to filesystem object types and domains refer to process types (see more in the SELinux type section).
Take Linux processes, for example. The SELinux role serves as an intermediary access layer between domains and SELinux users. An accessible role determines which domain (that is, processes) can be accessed through that role. Ultimately, this mechanism controls which object types can be accessed by the process, thus minimizing the surface for privilege escalation attacks.
The SELinux type is an attribute of SELinux type enforcement – a MAC security construct. For SELinux types, we refer to domains as process types and types as filesystem object types. SELinux security policies control how specific types can access each other – either with domain-to-type access or domain-to-domain interactions.
The SELinux level is an attribute of the MLS/MCS schema and an optional field in the SELinux context. A level usually refers to the security clearance of a subject's access control to an object. Levels of clearance include unclassified, confidential, secret, and top-secret and are expressed as a range. An MLS range represents a pair of levels, defined as low-high if the levels differ, or just low if the levels are identical. For example, a level of s0-s0 is the same as s0. Each level represents a sensitivity-category pair, with categories being optional. When a category is specified, the level is defined as sensitivity:category-set; otherwise, it's defined as sensitivity only.
We are now familiar with SELinux contexts. We'll see them in action, starting with the SELinux contexts for users, next.
SELinux contexts for users
The following command displays the SELinux context associated with the current user:
In our case, the output is as follows:
Figure 17 – Displaying the current user's SELinux context
In RHEL/CentOS, Linux users are unconfined (unrestricted) by default, with the following context fields:
- unconfined_u: User identity
- unconfined_r: Role
- unconfined_t: Domain affinity
- s0-s0: MLS range (the equivalent of s0)
- c0.c1023: Category set, representing all categories (from c0 to c1023)
Next, we'll examine the SELinux context for processes.
SELinux context for processes
The following command displays the SELinux context for the current SSH processes:
ps -eZ | grep sshd
The command yields the following output:
Figure 18 – Displaying the SELinux context for SSH-related processes
From the output, we can infer that the top line refers to the sshd server process, which is running with the system_u user identity, system_r role, and sshd_t domain affinity. The second line refers to the current user's SSH session, hence the unconfined context. System daemons are usually associated with the system_u user and system_r role.
Before concluding this section on SELinux contexts, we'll examine the relatively common scenario of SELinux domain transitions, which is where a process in one domain accesses an object (or process) in a different domain.
SELinux domain transitions
Assuming an SELinux-secured process in one domain requests access to an object (or another process) in a different domain, SELinux domain transitions come into play. Unless there's a specific security policy allowing the related domain transition, SELinux would deny access.
An SELinux-protected process transitioning from one domain into another invokes the entrypoint type of the new domain. SELinux evaluates the related entrypoint permission and decides if the soliciting process can enter the new domain.
To illustrate a domain transition scenario, we will take the simple case of using the passwd utility when users change their password. The related operation involves the interaction between the passwd process and the /etc/shadow (and possibly /etc/gshadow) file(s). When the user enters (and reenters) the password, passwd would hash and store the user's password in /etc/shadow.
Let's examine the SELinux domain affinities involved:
ls -Z /usr/bin/passwd ls -Z /etc/shadow
The corresponding output is as follows:
Figure 19 – Comparing the domain affinity context
The passwd utility is labeled with the passwd_exec_t type, while /etc/shadow is labeled with shadow_t. There must be a specific security policy chain that allows the related domain to transition from passwd_exec_t to shadow_t; otherwise, passwd will not work as expected.
Let's validate our assumption. We'll use the sesearch tool to query for our assumed security policy:
sudo sesearch -s passwd_t -t shadow_t -p write --allow
Here's a brief explanation of the preceding command:
- sesearch: Searches the SELinux policy database
- -s passwd_t: Finds policy rules with passwd_t as their source type or role
- -t shadow_t: Finds policy rules with shadow_t as their target type or role
- -p write: Finds policy rules with write permissions
- --allow: Finds policy rules that allow the queried permissions (specified with -p)
The output of the preceding command is as follows:
Figure 20 – Querying SELinux policies
Here, we can see the append create permissions, as we correctly assumed.
How did we pick the passwd_t source type instead of passwd_exec_t? By definition, the domain type corresponding to the executable file type, passwd_exec_t, is passwd_t. If we were not sure about who has write permissions to the shadow_t file types, we could have simply excluded the source type (-s passwd_t) in the sesearch query and parsed the output (for example, using grep passwd).
The use of the sesearch tool is very convenient when we're querying security policies. There are a handful of similar tools for troubleshooting or managing the SELinux configuration and policies. One of the most notable SELinux command-line utilities is semanage for managing SELinux policies. We'll examine it next.