In this article:
This page is only designed as a memory-refresher. SElinux may be a complex thing to get right, if you are not familiar with it yet I highly encourage you to read Sven Vermeulen books.
SELinux state
To detect whether SELinux is enabled or not:
- From a script,
selinuxenabled
doesn’t produce any output and its exit code gives SELinux status. - From an interactive prompt,
sestatus
provides more information.
SELinux main configuration file is /etc/selinux/config, it defines:
-
SELINUX=
: SELinux state:-
enforcing
: Enabled and block unauthorized actions (policy violations). -
permissive
: Enabled, but only logs unauthorized actions and does not block them (useful for development and HIDS purposes). -
disabled
: SELinux is completely disabled.Warning
If SELinux has been temporarily disabled (which is not recommended, there are usually cleaner ways to proceed), a global relabel will be required before re-enabling SELinux.
-
-
SELINUXTYPE=
: The policy currently in use, available policies depend on the distribution:-
targeted
: SELinux protection targets some system and daemon processes, the end-user is usually not confined (unconfined_t domain). -
minimum
(Red Hat) orstrict
(Gentoo): Complete protection including end-user’s processes. -
mls
: MCS/MLS implementation (Gentoo also provides amcs
policy offering a single level, as opposed tomls
which is still experimental on this distribution).
-
Current configuration overview
Several traditional commands have been modified to include the -Z
option,
such as:
id -Z
: Current user SELinux context.ps -eZ
: SELinux of currently running processes.ls -lZ
: SELinux context of the files in the current directory.
Users list:
- Unix users:
getent passwd
- SELinux users:
semanage user -l
Relation between Unix and SELinux users: semanage login -l
.
This list is also available in the file
/etc/selinux/{SELINUXTYPE}/seusers (do not modify this file directly!).
Roles list: seinfo -r
Category and security level list: chacat -L
or in the file
/etc/selinux/{SELINUXTYPE}/setrans.conf.
Note
In fact the list is hardcoded in SELinux: s0-s15:c0.c1023, but
setrans.conf lists aliases which are translated in the background by
the mcstrans
daemon.
Relation between SELinux users and roles on one side and security levels and
categories on the other side: semanage user -l
Modify a user account context
-
Relation between a Unix user and a SELinux user:
- Add:
semanage login -a -s staff_u larry
- Modify:
semanage login -m -s staff_u larry
- Delete:
semanage login -d larry
- Add:
-
Relation between a SELinux user, a role and a MCS/MLS level:
- Add:
semanage user -a -R 'staff_r sysadm_r' larry_u
- Modify:
semanage user -m -R 'staff_r sysadm_r' larry_u
- Delete:
semanage user -d larry_u
- Add:
Note
When modifying user’s context, changes are taken into account only on the next session opening. It is therefore mandatory to ensure that the user has been fully logged off:
1 2 3 4 5 6 | # Lock the account: passwd -l larry # Stop all user's processes: killall -KILL -u larry # Unlock the account: passwd -u larry |
Execute a command under a different context
newrole [-r ROLE] [-t TYPE] [-l LEVEL]
: Open a shell under a different role (the re-authentication process can be avoided using PAM settings).runcon [-u USER] [-r ROLE] [-t TYPE] [-l LEVEL] COMMAND
: Launch a command under a different role or as a different user.sudo [-r ROLE] [-t TYPE] COMMAND
: Launch a command under a different role, the role can be automatically selected from the sudoers file:larry ALL=(ALL) TYPE=dbadm_t ROLE=dbadm_r ALL
Those three commands allow to use a different role or type, only runcon
allows to use a different SELinux user, sudo
does not allow to use a
different MCS/MLS level.
Other commands natively implement SELinux contexts handling and allow more
specific operations, such as run_init
to start daemons on non-systemd systems.
Authentication services (such as getty
, sshd
, and xdm
) can rely on PAM
to handle SELinux context switching (pam_selinux
(8) module).
They therefore do not need to be modified.
Application-based context transition can be configured in these files:
- /etc/selinux/{SELINUXTYPE}/contexts/default_contexts: Default transition rules.
- /etc/selinux/{SELINUXTYPE}/contexts/users/{target-selinux-user}: Contains rules overwriting the default ones.
The first column matches the source context, then the first of the following contexts allowed for the current user is selected.
File context
Current context
The context is usually checked using ls -lZ
or stat
.
It is stored in the extended attribute security.selinux, as can be checked
using the command getfattr -m . -d <path>
.
The attributes belonging to the security namespace are not directly editable
by the file owner, he must have the CAP_SYS_ADMIN capability to change them.
Two hardlinks cannot use two different contexts.
If they are used for a similar purpose, a way must be found to make them share the
same context.
Otherwise, a copy (cp
) must be used instead of a link.
If the file system does not support extended attributes, or if no extended attribute or an invalid one is defined:
- The context to use can be passed through a
mount
(8) option (for instancecontext="system_u:object_r:removable_t"
). - Otherwise SELinux falls back on a default context (
file_t
orunlabeled_t
) which is unaccessible from most domains.
Modify file’s context
Automatic context modification
-
restorecon
is used to:- Restore the context of a file or a directory tree.
- Find files with an unexpected context.
-
fixfiles
(Red Hat) andrlpkg
(Gentoo) are used to:- Restore the context of all the files provided by a given package.
- Restore the context of all mounted file systems.
- Check files context.
- Schedule a global relabel for the next system restart.
-
Creating the /.autolabel file (
touch /.autolabel
) then restart the system is the recommended way (seeselinux
(8)) to relabel the whole file system. This step is necessary when enabling a previously disabled SELinux.
These tools rely on regular expressions stored in the files /etc/selinux/{SELINUXTYPE}/contexts/file_contexts[.*].
Most of these rules are also viewable using semanage fcontext -l
, except:
- Rules affecting home directories files.
- Paths explicitly set to not be automatically relabeled.
These rules can match:
- Any file type (default behavior).
- Directories (
-d
). - Socket files (
-s
). - Named pipes (
-p
). - Block devices (
-b
). - Character devices (
-c
). - Symbolic links (
-s
).
When several rules match the same file:
- If a rule defined by the user (using
semanage
and stored in the file file_contexts.local) matches, the last defined one will be used. - Otherwise, the “most specific” system rule will be used. The “specificity” of a rule is mainly measured by the absence of regular expression pattern or the largest number for fixed character before the pattern.
Manual context modification
The ability to manually relabel a file is restricted by the relabelfrom and relabelto privileges.
Use chcon
to test the impact of a context change:
-
Use the
-t
option to pass a new context explicitely:chcon -R -t httpd_sys_content_t /srv/www
-
Use the
--reference
option to apply the same context as a reference file:chcon --reference /var/www/index.html /srv/www/index.html
chcat
is a wrapper around chcon
and allows to add and remove some
categories without having to provide the resulting categories list explicitly:
1 2 3 4 | # Add a category: chcat -- +Customer2 index.html # Remove a category: chcat -- -Customer1 index.html |
Warning
Don’t forget to use --
to mark the end of the options, especially when
removing a category otherwise your command-line parameters may not be
parsed correctly.
setfiles
offers the same kind of features, but is older and mainly used
in the background by other, higher-level commands.
Manual modifications of files context will be lost on global relabel operations
unless if the destination context is a “customizable type”, listed in the
file /etc/selinux/{SELINUXTYPE}/context/customizables_types (this file can
be edited manually but it may be overwritten when updating the system…).
The restorecond
and fixfiles
will relabel such files only when the -F
flag is used.
The recommended way to make such change permanent is by proceeding in two steps and define the modification as a user’s rule:
-
The new context can be passed explicitly:
1 2
semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?" restorecon -R /srv/www
-
Or a substitution can be declared:
1 2
semanage fcontext -e /var/www /srv/www restorecon -R /srv/www
semanage
substitution do not work the same way as chcon
references:
chcon
applies the same context to all files given as parameter.semanage
saves the substitution declaration in the file_contexts.subs file and, for instance, /srv/www/icons will receive the same context as /var/www/icons which can be a different context than other directories.
Usually, only the type field of the context is modified.
The user part is only used when UBAC is enabled in the SELinux policy,
and the role field remains object_r
for all files, roles being currently
only applied to running processes (users and daemons).
New files context
SELinux does not rely on the file_contexts.* files for newly created files. Instead, several situations are possible:
-
By default, new files context is inherited from their parent directory.
-
The SELinux policy may define transition rules like “If a process running with context A creates a file in a directory with context B, then the file will be labeled with context C”. For instance, if a web server with context httpd_t creates a temporary file in a directory bearing the context tmp_t, the created file will be affected the context httpd_tmp_t. These transition rules can also take the file name into account.
sesearch
is used to search in a SELinux policy, its-T
option allows to search for types transition:sesearch -T -s httpd_t -t tmp-t
Of course the process’s context must also have enough rights on the resulting file context (create, read, write,append, etc.):
sesearch -A -s httpd_t -t httpd_tmp_t
-
An application directly interacting with SELinux API, given the right privileges, can set the context of created files the same way a user would use
chcon
orchcat
. -
At last the
restorecond
daemon can monitor a set of paths defined in the file /etc/selinux/restorecond.conf and apply the context rules defined in file_context.*. This daemon is an ancestor of the type transition rules and is less used nowadays.
Processes and threads context
Processes and thread context is determined in a similar way than new files
context.
Child process context is handled while processing the call to an exec*
family function (execve()
, execl()
, etc.), usually following a call to
fork()
:
-
Inheritance of the parent process context by default.
-
A transition rule can force the transition to a different domain. For instance a process with the domain system_u:system_r:initrc_t executing a file with the domain httpd_exec_t results in child process with the domain set to system_u:system_r:httpd_t.
sesearch
can be used to investigate such rules:sesearch -T -s initrc_t -t httpd_exec_t
Several prerequisites are mandatory for such transition to work correctly:
-
The parent process must have the right to execute the target file:
sesearch -A -s initrc_t -t httpd_exec_t -c file -p execute
-
The transition from the type initrc_t to the type httpd_t must be authorized:
sesearch -A -s initrc_t -t httpd_t -c process -p transition
-
The target type httpd_t must be authorized for the process role system_r:
seinfo -rsystem_r -x | grep httpd_t
-
The type httpd_exec_t must be identified as an entry point for the type httpd_t:
sesearch -A -s httpd_t -t httpd_exec_t -c file -p entrypoint
-
-
At last an application with the dyntransition privilege can use the
setexeccon()
function to set the context to use upon the next call to anexec*
family function.
A thread can also have its own context set the same way, but its privileges must be a subset of the parent thread privileges. The child cannot have any privilege that the parent thread doesn’t already have. The Apache module mod_selinux for instance is implemented this way.
If a label is missing or invalid, the default label unlabeled_t is used.
Note
A common cause for invalid domains is the update of the SELinux policy to a new version which doesn’t know the label of some currently running processes.
Network communication context
Network ports labels
Similarly to files, network ports (sockets) are associated to a label allowing to determine authorized actions depending on the process label.
To view current ports labels: semanage port -l
To modify ports labels:
- Add a label:
semanage port -a -t http_port_t -p tcp 81
- Modify a label:
semanage port -m -t http_port_t -p tcp 81
- Delete a label:
semanage port -d -t http_port_t -p tcp 81
Note
It is possible to provide a port range by separating the first and last
port using a dash (for instance 81-89
).
The range must be expressed the same way in both the creation and deletion commands, otherwise the deletion command will not work.
Network packets labels (SECMARK)
Network packets labeling is handled by Netfilter.
In addition to the classical actions ACCEPT, DROP, RETURN and QUEUE,
iptables
or ip6tables
may use:
- SECMARK: to label an individual packet.
- CONNSECMARK: to label a whole connection.
Two operational modes are available:
-
Label of incoming/outgoing traffic: SELinux extends Netfilter filtering features but the label remains local to the host.
-
End-to-end traffic labeling: as long as both the client and the server hosts share the same naming convention and that an appropriate protocol is used, it becomes possible to apply labels to the network communication from end-to-end.
Protocols used for end-to-end network labeling are:
-
IPSec: The most modern and common solution, allows to carry the whole context information along with the network data.
-
Netlabel/CIPSO: Solution providing backward compatibility with legacy hardened operating systems. It carries only the sensitivity information.
-
Querying the current policy
Rules syntax
SELinux rules are composed of TE rules and AV.
The syntax is as follow:
<av_kind> <source_type(s)> <target_type(s)> : <class(es)> <permission(s)>
Where:
-
av_kind: Rule type, for instance:
-
allow
: Defines an authorized operation, matchessesearch
option-A
. -
type_transition
: Defines the transition between domains, matchessesearch
option-T
.
-
-
source_type(s): is one of the following:
-
A domain, also called “type”, hence the fact that SELinux is called a “Type Enforcement based MAC” since the rules rely on type information to control the access.
To list available types:
seinfo -t
-
An attribute, this is a group name allowing to target a potentially large number of domains in a single rule.
To list available attributes:
seinfo -a
, to list the domains contained in a given attribute:seinfo -a<attribute_name> -x
. -
At a lower level it can also be an alias, this is just a synonym of an existing type.
-
-
target_type: Any valid type name.
-
classe(es): Defines the type of resource (file, socket, etc.) covered by the rule.
To list available classes:
seinfo -c
-
permission(s): The permissions granted, the object class dictates the list of possible permissions.
To list available permissions:
seinfo -c<class_name> -x
sesearch
provides a variable degree of granularity in the search results.
Providing more arguments provides narrower results:
sesearch (-A|-T|...) [-s SOURCE [-t TARGET [-c CLASS [-p PERMISSION]]]]
Constraints
In addition to the Type Enforcment rules which rely on object types, SELinux also provides constraints. These are a kind of conditional expression allowing to take the context’s user and role into account.
For instance, UBAC is implemented this way:
u1 == u2 or u1 == system_u or u2 == system_u or t1 != ubac_constrained_type or t2 != ubac_constrained_type
Technically, the command seinfo --constrain
should allow to list enabled
constraints, but the output is generated in postfixed notation with attributes
expanded and is therefore hardly usable as-is.
Modify the current policy behavior
Boolean settings
To list available boolean settings with their current value and a description:
semanage boolean -l
Note
As the list of all available boolean settings may be long, use grep
to
limit to the relevant entries.
To quickly know the value of a boolean given its name:
getsebool <boolean_name>
To find a boolean name starting from an allow rule:
sesearch -AC -s httpd_t -t user_home_t -p read
To find the rules affected by a given boolean:
sesearch -ATC -b <boolean_name> | grep -e ^E -e ^D
.
This command output follows the convention below:
- First letter:
- E: The rule is currently enabled.
- D: The rule is currently disabled.
- Second letter:
- T: The rule is enabled when the boolean setting is enabled (true).
- F: The rule is enabled when the boolean setting is disabled (false).
Temporary modification
To temporarily modify a boolean value (the change will be reverted on next system restart):
setsebool <bool_name>=(0|false|off|1|true|on) ...
: Assign an explicit value to the boolean setting (0
,false
andoff
are equivalent, so are1
,true
andon
).togglesebool <bool_name> ...
: Reverse the value of the boolean settings passed as parameter. This is an older command dating back to the time whensetsebool
was unable to set multiple settings in an atomic way.
Unlike persistent modifications, temporary modification of a boolean value is a nearly instantaneous operation.
Persistent modification
To modify a boolean setting so it remains persistent across system reboots:
setsebool -P <boolean_name>=(on|off) ...
semanage boolean -m -(0|-off|1|-on) <bool_name>
,semange
can also take its input from a file listing the settings to modify using the-F
option.
Persistent changes imply to rebuild the whole SELinux policy, they may therefore take some time depending on the size of the current SELinux policy.
Note
On Gentoo systems, the SELinux policies only contains rules covering installed packages, while on Red Hat systems the SELinux policies are monolithic and always contain all created rules.
As a result, permanently modifying a setting takes a noticeably longer time on Red Hat systems. Be patient…
Rules troubleshooting and modification
Use audit2allow
to troubleshoot and generate rules and modules:
-
To analyze the cause of an interdiction (equivalent of
audit2why
on some distributions):grep avc /var/log/messages | audit2allow -w
-
To generate the allow rules matching interdictions.
audit2allow
tells when a boolean allows to reach the same goal or if the interdiction has been raised by a constraint instead of a TE rule. The-R
option allows the use of macros, this makes the result more readable but also more prone to unwanted side-effects.grep avc /var/log/messages | audit2allow [-R]
-
To generate a directly loadable module, the command below would generate a policy package file named example.pp:
grep avc /var/log/messages | audit2allow -M example
Warning
While audit2allow
remains a good troubleshooting utility, its automatic rules
generation feature however must be used with great care to not affect the
system security negatively.
Use semodule
to manage SELinux modules:
-
To list loaded modules:
semodule -l
-
To load an additional module (this is a persistent change: the module will remain loaded upon system restarts):
semodule -i /path/to/example.pp
-
To enable/disable a module:
semodule -(e/d) <module_name>
Note
Disabling a module while keeping it loaded is useful to keep its types definition without enabling any of its rules.
selocal
is available only on Gentoo and helps to manage locally defined
SELinux rules.
To manually build a SELinux policy package:
-
Start from a plain text source code (*.te file).
-
Build a intermediary module (*.mod file):
checkmodule -M -m -o mymodule.mod mymodule.te
-
Generate the policy package suitable to be loaded by
semodule
(*.pp file):semodule_package -o mymodule.pp -m mymodule.mod