The Context of a Process in SELinux

Posted on the 09 June 2021 by Satish Kumar @satish_kumar86

As everything in SELinux works with contexts, even processes are assigned a context, also known as the domain. Let’s see how we can obtain this information, how SELinux transitions from one domain to another, and learn how to query the SELinux policy to find more information about these transitions.

Getting a process context

We saw that the nginx web server runs in the httpd_t domain, which can be seen with the ps -eZ command, as follows:

# ps -eZ | grep nginx
system_u:system_r:httpd_t:s0  3744 ?   00:00:00 nginx

Several other ways exist to obtain the process context. Although the method withpsis the most obvious, these other methods can prove useful in scripted approaches or through monitoring services.

A first approach is to read the/proc/<pid>/attr/currentpseudo-file. It displays a process’s current security context:

# pidof nginx
3746 3745 3744
# cat /proc/3744/attr/current

To receive a somewhat more human-readable output, use the secon command for the given process ID:

# secon --pid 3744
user: system_u
role: system_r
type: httpd_t
sensitivity: s0
clearance: s0
mls-range: s0

Finally, the SELinux user space project has a helper utility called getpidcon, which the libselinux library optionally provides. Although this utility is not available on CentOS (or related distributions), other distributions such as Gentoo do have it. The utility requires a single PID and returns its context:

# getpidcon 679

Now, the Apache processes don’t themselves inform SELinux that they need to run in the httpd_t (or, for Gentoo, the nginx_t) domain. For that, transition rules exist in the SELinux policy that govern when and how processes are executed in a specific domain.

Transitioning toward a domain

Just as wehave seen with files, if a process forks and creates a new process, this process, by default, inherits the context of the parent process. For the web server, the main process is running in thehttpd_tdomain, so all the launched worker processes inherit thehttpd_tdomain from it.

To differentiatethe domain of one process from another, domain transitions can be defined. Adomain transition(also known as a process transition or type transition) is a rule in SELinux that tells SELinux another domain is to be used for a forked process (actually, it is when the parent process calls theexecve()function, most likely after afork()operation).

Like the file-based transitions, domain transitions can be queried usingsesearch. Let’s investigate the domains allowed to transition to thehttpd_tdomain:

$ sesearch -T -t httpd_exec_t
type_transition certwatch_t httpd_exec_t:process httpd_t;
type_transition cluster_t httpd_exec_t:process httpd_t;
type_transition initrc_t httpd_exec_t:process httpd_t;
type_transition system_cronjob_t httpd_exec_t:process httpd_t;

In this case, SELinux will switch the context of a launched web server tohttpd_tif the parent process is running in one of the mentioned domains (such as theinitrc_tdomain) and is executing a file labeled ashttpd_exec_t(the label assigned to thehttpdandnginxbinaries).

But for this to truly happen, several other permissions (next to the domain transition) need to be in place. The following list describes these various permissions:

  • The source process (such as initrc_t) needs to be allowed to transition to the httpd_t domain, governed by the transition privilege on the process class:
$ sesearch -s initrc_t -t httpd_t -c process -p transition -A
  • The source process (such as initrc_t) needs to have the right of execution on the file it is launching (httpd_exec_t):
$ sesearch -s initrc_t -t httpd_exec_t -c file -p execute -A
  • The httpd_exec_t type must be identified as an entry point for the httpd_t domain. SELinux uses an entry point to ensure that a domain transition only occurs when using the specified file context on the executing binary or script:
$ sesearch -s httpd_t -t httpd_exec_t -c file -p entrypoint -A
  • The target domain must be allowed for the role that the parent process is in. In the case of system daemons, the role is system_r:
$ seinfo -r system_r -x | grep httpd_t

A graphical representation of these rights is as follows:

selinux process

Only when all these privileges are allowed will a domain transition occur. If not, then either the execution of the application fails (if the domain has noexecuteorexecute_no_transrights on the file), or it executes but remains running in the same domain as the parent process.

Domain transitions are an important concept as they inform the administrator how an application gets into its privileged context. To analyze this, many security administrators look at how one context can transition to another.

For policy writers, deciding when to create a domain transition and when to keep the processes running in the same (source) context is a matter of design. Generally, policy developerswill try to keep the parent context confined so that every additional privilege is a source of consideration for switching to another domain (which has that privilege). Basically, policy developers will trigger a transition when the target application requires significantly more (or different) permissions than the source domain holds.

That is also why theunconfined_tdomain has fewer transitions when executing user applications compared to the confined user domains,user_torguest_t: theunconfined_tdomain already holds many privileges, so transitioning to a different domain has little value. Note that this is a decision made by the policy writers or Linux distribution, not by the SELinux technology itself. All SELinux does is enforce the policy rules.

Verifying a target context

When executing applications, the SELinux policy might have the command run in a different domain. Althoughwe could start querying all rules withsesearch, a simpler command exists that tells us what the target context is when we execute a command or script:selinuxexeccon.

This command requires at least one argument (the path of the binary or script that would be executed) and an optional second (the source context). If we omit the second argument, the tool will use the current context as the source context.

For instance, to find out in which domain thepasswdcommand would run when executed from the current context, we’d use this command:

# selinuxexeccon /usr/bin/passwd

The following example shows the target context when the init_t domain executes the nginx binary:

# selinuxexeccon /usr/sbin/nginx system_u:system_r:init_t:s0

Using selinuxexeccon is much faster than querying all appropriate permissions separately.

Other supported transitions

Regulardomain transitions are the most common transitions in SELinux, but other transitions are possible as well. For instance, some applications (such ascronorlogin) are SELinux-aware and will specify which domain to transition to. These applications call thesetexeccon()method (set execution context) to specify the target domain and do not use a type transition rule. The other privilege requirements, however, still hold.

Some SELinux-aware applications are even able to change theircurrentcontext (and not just the context of the application they execute). To accomplish this, the application domain needs thedyntransitionprivilege (one of the privileges supported for process-level activities). One example of such an application is OpenSSH, which, by default, runs in thesshd_tdomain but can transition to thesftpd_ttype.

Querying initial contexts

When SELinuxdoes not have a label yet for a resource, it willassign an initial context (or initialsecurity ID(SID)) to the resource. For a few classes, the SELinux policy will have a default initial context from which it can further jumpstart and assign labels.

The initial contexts for various SIDs can be queried usingseinfo:

# seinfo --initalsid -x
Initial SIDs: 27
  sid any_socket system_u:object_r:unlabeled_t:s0
  sid devnull system_u:object_r:null_device_t:s0
  sid unlabeled system_u:object_r:unlabeled_t:s0

As you can see, not all classes have a default context assigned, as other classes have their contexts derived from the contexts of the currently listed initial SIDs.

Tweaking memory protections

Legacy binaries on Linux systems might require execution permissions to be set on memory regions when these are used for reading, even when the execute permission is not actually used. This read-implies-exec is a nuisance for mandatory access controls such as SELinux because they need to document the appropriate permissions in their policy. If an application needs read access, does the policy then also have to include the implied execute rights? And if the policy does not include execute rights, should the read operation then fail because it implied execute permissions?

SELinux developers allow administrators to select their most appropriate permission handling by introducing a memory protection check that can be tuned. Thecheckreqprotoption canbe set to0to check protections as handled by the kernel, or1to check protections as asked by the application.

On older systems, this option will be set to1to support these legacy binaries. Recent distributions, however, build their applications appropriately, and the more secure setting0is used, as displayed by thesestatuscommand:

# sestatus | grep Memory
Memory protection checking:   actual (secure)

You can toggle this support through /sys/fs/selinux/checkreqprot:

# echo 1 > /sys/fs/selinux/checkreqprot
# sestatus | grep Memory
Memory protection checking:   requested (insecure)

The parameter’s default value is configured when building the Linux kernel, through the CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE kernel configuration parameter. Administrators can also boot the system with the checkreqprot= boot parameter to have the specified value set.

Back to Featured Articles on Logo Paperblog