'Cheatsheet/selinux' tag logo

SELinux cheatsheet

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.


      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.

      More information.

  • 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) or strict (Gentoo): Complete protection including end-user’s processes.

    • mls: MCS/MLS implementation (Gentoo also provides a mcs policy offering a single level, as opposed to mls 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.


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
  • 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


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:

# 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 instance context="system_u:object_r:removable_t").
  • Otherwise SELinux falls back on a default context (file_t or unlabeled_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) and rlpkg (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 (see selinux(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:

# Add a category:
chcat -- +Customer2 index.html
# Remove a category:
chcat -- -Customer1 index.html


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:

    semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
    restorecon -R /srv/www
  • Or a substitution can be declared:

    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 or chcat.

  • 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 an exec* 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.


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


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)>


  • av_kind: Rule type, for instance:

    • allow: Defines an authorized operation, matches sesearch option -A.

    • type_transition: Defines the transition between domains, matches sesearch 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]]]]


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


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 and off are equivalent, so are 1, true and on).
  • togglesebool <bool_name> ...: Reverse the value of the boolean settings passed as parameter. This is an older command dating back to the time when setsebool 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.


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


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>


    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:

  1. Start from a plain text source code (*.te file).

  2. Build a intermediary module (*.mod file):

    checkmodule -M -m -o mymodule.mod mymodule.te
  3. Generate the policy package suitable to be loaded by semodule (*.pp file):

    semodule_package -o mymodule.pp -m mymodule.mod

Popular tags see all