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 withps
is 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/current
pseudo-file. It displays a process’s current security context:
# pidof nginx
3746 3745 3744
# cat /proc/3744/attr/current
system_u:system_r:httpd_t:s0
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
system_u:system_r:nginx_t:s0
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_t
domain, so all the launched worker processes inherit thehttpd_t
domain 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_t
domain:
$ 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_t
if the parent process is running in one of the mentioned domains (such as theinitrc_t
domain) and is executing a file labeled ashttpd_exec_t
(the label assigned to thehttpd
andnginx
binaries).
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 thehttpd_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 thehttpd_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:

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 noexecute
orexecute_no_trans
rights 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_t
domain has fewer transitions when executing user applications compared to the confined user domains,user_t
orguest_t
: theunconfined_t
domain 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 thepasswd
command would run when executed from the current context, we’d use this command:
# selinuxexeccon /usr/bin/passwd
unconfined_u:unconfined_r:passwd_t:s0-s0:c0.c1023
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
system_u:system_r:httpd_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 ascron
orlogin
) 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 thedyntransition
privilege (one of the privileges supported for process-level activities). One example of such an application is OpenSSH, which, by default, runs in thesshd_t
domain but can transition to thesftpd_t
type.
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. Thecheckreqprot
option canbe set to0
to check protections as handled by the kernel, or1
to check protections as asked by the application.
On older systems, this option will be set to1
to support these legacy binaries. Recent distributions, however, build their applications appropriately, and the more secure setting0
is used, as displayed by thesestatus
command:
# 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.