Red Hat Training

A Red Hat training course is available for RHEL 8

Using SELinux

Red Hat Enterprise Linux 8

Basic and advanced configuration of Security-Enhanced Linux (SELinux)

Red Hat Customer Content Services


This title assists users and administrators in learning the basics and principles upon which SELinux functions and describes practical tasks to set up and configure various services.

Providing feedback on Red Hat documentation

We appreciate your input on our documentation. Please let us know how we could make it better. To do so:

  • For simple comments on specific passages:

    1. Make sure you are viewing the documentation in the Multi-page HTML format. In addition, ensure you see the Feedback button in the upper right corner of the document.
    2. Use your mouse cursor to highlight the part of text that you want to comment on.
    3. Click the Add Feedback pop-up that appears below the highlighted text.
    4. Follow the displayed instructions.
  • For submitting more complex feedback, create a Bugzilla ticket:

    1. Go to the Bugzilla website.
    2. As the Component, use Documentation.
    3. Fill in the Description field with your suggestion for improvement. Include a link to the relevant part(s) of documentation.
    4. Click Submit Bug.

Chapter 1. Getting started with SELinux

1.1. Introduction to SELinux

Security Enhanced Linux (SELinux) provides an additional layer of system security. SELinux fundamentally answers the question: May <subject> do <action> to <object>?, for example: May a web server access files in users' home directories?

The standard access policy based on the user, group, and other permissions, known as Discretionary Access Control (DAC), does not enable system administrators to create comprehensive and fine-grained security policies, such as restricting specific applications to only viewing log files, while allowing other applications to append new data to the log files.

SELinux implements Mandatory Access Control (MAC). Every process and system resource has a special security label called an SELinux context. A SELinux context, sometimes referred to as an SELinux label, is an identifier which abstracts away the system-level details and focuses on the security properties of the entity. Not only does this provide a consistent way of referencing objects in the SELinux policy, but it also removes any ambiguity that can be found in other identification methods. For example, a file can have multiple valid path names on a system that makes use of bind mounts.

The SELinux policy uses these contexts in a series of rules which define how processes can interact with each other and the various system resources. By default, the policy does not allow any interaction unless a rule explicitly grants access.


Remember that SELinux policy rules are checked after DAC rules. SELinux policy rules are not used if DAC rules deny access first, which means that no SELinux denial is logged if the traditional DAC rules prevent the access.

SELinux contexts have several fields: user, role, type, and security level. The SELinux type information is perhaps the most important when it comes to the SELinux policy, as the most common policy rule which defines the allowed interactions between processes and system resources uses SELinux types and not the full SELinux context. SELinux types end with _t. For example, the type name for the web server is httpd_t. The type context for files and directories normally found in /var/www/html/ is httpd_sys_content_t. The type contexts for files and directories normally found in /tmp and /var/tmp/ is tmp_t. The type context for web server ports is http_port_t.

There is a policy rule that permits Apache (the web server process running as httpd_t) to access files and directories with a context normally found in /var/www/html/ and other web server directories (httpd_sys_content_t). There is no allow rule in the policy for files normally found in /tmp and /var/tmp/, so access is not permitted. With SELinux, even if Apache is compromised, and a malicious script gains access, it is still not able to access the /tmp directory.

Figure 1.1. An example how can SELinux help to run Apache and MariaDB in a secure way.


As the previous scheme shows, SELinux allows the Apache process running as httpd_t to access the /var/www/html/ directory and it denies the same process to access the /data/mysql/ directory because there is no allow rule for the httpd_t and mysqld_db_t type contexts). On the other hand, the MariaDB process running as mysqld_t is able to access the /data/mysql/ directory and SELinux also correctly denies the process with the mysqld_t type to access the /var/www/html/ directory labeled as httpd_sys_content_t.

Additional resources

To better understand SELinux basic concepts, see the following documentation:

1.2. Benefits of running SELinux

SELinux provides the following benefits:

  • All processes and files are labeled. SELinux policy rules define how processes interact with files, as well as how processes interact with each other. Access is only allowed if an SELinux policy rule exists that specifically allows it.
  • Fine-grained access control. Stepping beyond traditional UNIX permissions that are controlled at user discretion and based on Linux user and group IDs, SELinux access decisions are based on all available information, such as an SELinux user, role, type, and, optionally, a security level.
  • SELinux policy is administratively-defined and enforced system-wide.
  • Improved mitigation for privilege escalation attacks. Processes run in domains, and are therefore separated from each other. SELinux policy rules define how processes access files and other processes. If a process is compromised, the attacker only has access to the normal functions of that process, and to files the process has been configured to have access to. For example, if the Apache HTTP Server is compromised, an attacker cannot use that process to read files in user home directories, unless a specific SELinux policy rule was added or configured to allow such access.
  • SELinux can be used to enforce data confidentiality and integrity, as well as protecting processes from untrusted inputs.

However, SELinux is not:

  • antivirus software,
  • replacement for passwords, firewalls, and other security systems,
  • all-in-one security solution.

SELinux is designed to enhance existing security solutions, not replace them. Even when running SELinux, it is important to continue to follow good security practices, such as keeping software up-to-date, using hard-to-guess passwords, and firewalls.

1.3. SELinux examples

The following examples demonstrate how SELinux increases security:

  • The default action is deny. If an SELinux policy rule does not exist to allow access, such as for a process opening a file, access is denied.
  • SELinux can confine Linux users. A number of confined SELinux users exist in the SELinux policy. Linux users can be mapped to confined SELinux users to take advantage of the security rules and mechanisms applied to them. For example, mapping a Linux user to the SELinux user_u user, results in a Linux user that is not able to run unless configured otherwise set user ID (setuid) applications, such as sudo and su, as well as preventing them from executing potentially malicious files and applications in their home directory.
  • Increased process and data separation. The concept of SELinux domains allows defining which processes can access certain files and directories. For example, when running SELinux, unless otherwise configured, an attacker cannot compromise a Samba server, and then use that Samba server as an attack vector to read and write to files used by other processes, such as MariaDB databases.
  • SELinux helps mitigate the damage made by configuration mistakes. Domain Name System (DNS) servers often replicate information between each other in what is known as a zone transfer. Attackers can use zone transfers to update DNS servers with false information. When running the Berkeley Internet Name Domain (BIND) as a DNS server in Red Hat Enterprise Linux, even if an administrator forgets to limit which servers can perform a zone transfer, the default SELinux policy prevents zone files [1] from being updated using zone transfers, by the BIND named daemon itself, and by other processes.

[1] Text files that include information, such as host name to IP address mappings, that are used by DNS servers.

1.4. SELinux architecture and packages

SELinux is a Linux Security Module (LSM) that is built into the Linux kernel. The SELinux subsystem in the kernel is driven by a security policy which is controlled by the administrator and loaded at boot. All security-relevant, kernel-level access operations on the system are intercepted by SELinux and examined in the context of the loaded security policy. If the loaded policy allows the operation, it continues. Otherwise, the operation is blocked and the process receives an error.

SELinux decisions, such as allowing or disallowing access, are cached. This cache is known as the Access Vector Cache (AVC). When using these cached decisions, SELinux policy rules need to be checked less, which increases performance. Remember that SELinux policy rules have no effect if DAC rules deny access first. Raw audit messages are logged to the /var/log/audit/audit.log and they start with the type=AVC string.

In Red Hat Enterprise Linux 8, system services are controlled by the systemd daemon; systemd starts and stops all services, and users and processes communicate with systemd using the systemctl utility. The systemd daemon can consult the SELinux policy and check the label of the calling process and the label of the unit file that the caller tries to manage, and then ask SELinux whether or not the caller is allowed the access. This approach strengthens access control to critical system capabilities, which include starting and stopping system services.

The systemd daemon also works as an SELinux Access Manager. It retrieves the label of the process running systemctl or the process that sent a D-Bus message to systemd. The daemon then looks up the label of the unit file that the process wanted to configure. Finally, systemd can retrieve information from the kernel if the SELinux policy allows the specific access between the process label and the unit file label. This means a compromised application that needs to interact with systemd for a specific service can now be confined by SELinux. Policy writers can also use these fine-grained controls to confine administrators.


To avoid incorrect SELinux labeling and subsequent problems, ensure that you start services using a systemctl start command.

Red Hat Enterprise Linux 8 provides the following packages for working with SELinux:

  • policies: selinux-policy-targeted, selinux-policy-mls
  • tools: policycoreutils, policycoreutils-gui, libselinux-utils, policycoreutils-python-utils, setools-console, checkpolicy

1.5. SELinux states and modes

SELinux can run in one of three modes: enforcing, permissive, or disabled.

  • Enforcing mode is the default, and recommended, mode of operation; in enforcing mode SELinux operates normally, enforcing the loaded security policy on the entire system.
  • In permissive mode, the system acts as if SELinux is enforcing the loaded security policy, including labeling objects and emitting access denial entries in the logs, but it does not actually deny any operations. While not recommended for production systems, permissive mode can be helpful for SELinux policy development and debugging.
  • Disabled mode is strongly discouraged; not only does the system avoid enforcing the SELinux policy, it also avoids labeling any persistent objects such as files, making it difficult to enable SELinux in the future.

Use the setenforce utility to change between enforcing and permissive mode. Changes made with setenforce do not persist across reboots. To change to enforcing mode, enter the setenforce 1 command as the Linux root user. To change to permissive mode, enter the setenforce 0 command. Use the getenforce utility to view the current SELinux mode:

# getenforce
# setenforce 0
# getenforce
# setenforce 1
# getenforce

In Red Hat Enterprise Linux, you can set individual domains to permissive mode while the system runs in enforcing mode. For example, to make the httpd_t domain permissive:

# semanage permissive -a httpd_t

Note that permissive domains are a powerful tool that can compromise security of your system. Red Hat recommends to use permissive domains with caution, for example, when debugging a specific scenario.

Chapter 2. Changing SELinux states and modes

2.1. Permanent changes in SELinux states and modes

As discussed in SELinux states and modes, SELinux can be enabled or disabled. When enabled, SELinux has two modes: enforcing and permissive.

Use the getenforce or sestatus commands to check in which mode SELinux is running. The getenforce command returns Enforcing, Permissive, or Disabled.

The sestatus command returns the SELinux status and the SELinux policy being used:

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      31

When systems run SELinux in permissive mode, users and processes can label various file-system objects incorrectly. File-system objects created while SELinux is disabled are not labeled at all. This behavior causes problems when changing to enforcing mode because SELinux relies on correct labels of file-system objects. To prevent incorrectly labeled and unlabeled files from causing problems, file systems are automatically relabeled when changing from the disabled state to permissive or enforcing mode. In permissive mode, use the fixfiles -F onboot command as root to create the /.autorelabel file containing the -F option to ensure that files are relabeled upon next reboot.

2.2. Enabling SELinux

When enabled, SELinux can run in one of two modes: enforcing or permissive. The following sections show how to permanently change into these modes.

While enabling SELinux on systems that previously had it disabled, to avoid problems, such as systems unable to boot or process failures, follow this procedure:

  1. Enable SELinux in permissive mode. For more information, see Changing to permissive mode.
  2. Reboot your system.
  3. Check for SELinux denial messages.For more information, see Identifying SELinux denials.
  4. If there are no denials, switch to enforcing mode. For more information, see Changing to enforcing mode.

To run custom applications with SELinux in enforcing mode, choose one of the following scenarios:

  • Run your application in the unconfined_service_t domain.
  • Write a new policy for your application. See the Writing Custom SELinux Policy Knowledgebase article for more information.

Temporary changes in modes are covered in SELinux states and modes.

2.2.1. Changing to permissive mode

When SELinux is running in permissive mode, SELinux policy is not enforced. The system remains operational and SELinux does not deny any operations but only logs AVC messages, which can be then used for troubleshooting, debugging, and SELinux policy improvements. Each AVC is logged only once in this case.

To permanently change mode to permissive, follow the procedure below:

  1. Edit the /etc/selinux/config file as follows:

    # This file controls the state of SELinux on the system.
    # SELINUX= can take one of these three values:
    #       enforcing - SELinux security policy is enforced.
    #       permissive - SELinux prints warnings instead of enforcing.
    #       disabled - No SELinux policy is loaded.
    # SELINUXTYPE= can take one of these two values:
    #       targeted - Targeted processes are protected,
    #       mls - Multi Level Security protection.
  2. Reboot the system:

    # reboot

2.2.2. Changing to enforcing mode

When SELinux is running in enforcing mode, it enforces the SELinux policy and denies access based on SELinux policy rules. In Red Hat Enterprise Linux, enforcing mode is enabled by default when the system was initially installed with SELinux.


This procedure assumes that the selinux-policy-targeted, libselinux-utils, and policycoreutils packages are installed.


If SELinux was disabled, follow the procedure below to change mode to enforcing again:

  1. Edit the /etc/selinux/config file as follows:

    # This file controls the state of SELinux on the system.
    # SELINUX= can take one of these three values:
    #       enforcing - SELinux security policy is enforced.
    #       permissive - SELinux prints warnings instead of enforcing.
    #       disabled - No SELinux policy is loaded.
    # SELINUXTYPE= can take one of these two values:
    #       targeted - Targeted processes are protected,
    #       mls - Multi Level Security protection.
  2. Reboot the system:

    # reboot

    On the next boot, SELinux relabels all the files and directories within the system and adds SELinux context for files and directories that were created when SELinux was disabled.


After changing to enforcing mode, SELinux may deny some actions because of incorrect or missing SELinux policy rules. To view what actions SELinux denies, enter the following command as root:


Alternatively, with the setroubleshoot-server package installed, enter:

# grep "SELinux is preventing" /var/log/messages

If SELinux is active and the Audit daemon (auditd) is not running on your system, then search for certain SELinux messages in the output of the dmesg command:

# dmesg | grep -i -e type=1300 -e type=1400

2.3. Disabling SELinux

When SELinux is disabled, SELinux policy is not loaded at all; it is not enforced and AVC messages are not logged. Therefore, all benefits of running SELinux are lost.


Red Hat strongly recommends to use permissive mode instead of permanently disabling SELinux. See Changing to permissive mode for more information about permissive mode.

To permanently disable SELinux, follow the procedure below:

  1. Configure SELINUX=disabled in the /etc/selinux/config file:

    # This file controls the state of SELinux on the system.
    # SELINUX= can take one of these three values:
    #       enforcing - SELinux security policy is enforced.
    #       permissive - SELinux prints warnings instead of enforcing.
    #       disabled - No SELinux policy is loaded.
    # SELINUXTYPE= can take one of these two values:
    #       targeted - Targeted processes are protected,
    #       mls - Multi Level Security protection.
  2. Reboot your system. After reboot, confirm that the getenforce command returns Disabled:

    $ getenforce

2.4. Changing SELinux modes at boot time

On boot, you can set several kernel parameters to change the way SELinux runs:

Setting this parameter causes the machine to boot in permissive mode, which is useful when troubleshooting issues. Using permissive mode might be the only option to detect a problem if your file system is too corrupted. Moreover, in permissive mode the system continues to create the labels correctly. The AVC messages that are created in this mode can be different than in enforcing mode. In permissive mode, only the first denial is reported. However, in enforcing mode you might get a denial on reading a directory and an application stops. In permissive mode, you get the same AVC message, but the application continues reading files in the directory and you get an AVC for each denial in addition.

This parameter causes the kernel to not load any part of the SELinux infrastructure. The init scripts notice that the system booted with the selinux=0 parameter and touch the /.autorelabel file. This causes the system to automatically relabel the next time you boot with SELinux enabled.


Red Hat does not recommend using the selinux=0 parameter. To debug your system, prefer using permissive mode.


This parameter forces the system to relabel similarly to the following commands:

# touch /.autorelabel
# reboot

If a file system contains a large amount of mislabeled objects, you might need to boot in permissive mode in order to make the autorelabel process successful.

Chapter 3. Configuring SELinux for applications and services with non-standard configurations

When SELinux is in enforcing mode, the default policy is the targeted policy. The following sections provide information on setting up and configuring the SELinux policy for various services after you change configuration defaults, such as ports, database locations, or file-system permissions for processes.

In the following procedures, you learn to change SELinux types for non-standard ports, to identify and fix incorrect labels for changes of default directories, and to adjust the policy using SELinux booleans.

3.1. Customizing the SELinux policy for the Apache HTTP server in a non-standard configuration

You can configure the Apache HTTP server to listen on a different port and to provide content in a non-default directory. To prevent consequent SELinux denials, follow the steps in this procedure to adjust your system’s SELinux policy.


  • The httpd package is installed and the Apache HTTP server is configured to listen on TCP port 3131 and to use the /var/test_www/ directory instead of the default /var/www/ directory.
  • The policycoreutils-python-utils package is installed.


  1. Start the httpd service and check the status:

    # systemctl start httpd
    # systemctl status httpd
    httpd[14523]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:3131
    systemd[1]: Failed to start The Apache HTTP Server.
    [trimmed for clarity]
  2. The SELinux policy assumes that httpd runs on port 80:

    # semanage port -l | grep http
    http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
    http_cache_port_t              udp      3130
    http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
    pegasus_http_port_t            tcp      5988
    pegasus_https_port_t           tcp      5989
  3. Change the SELinux type of port 3131 to match port 80:

    # semanage port -a -t http_port_t -p tcp 3131
  4. Start httpd again:

    # systemctl start httpd
  5. However, the content remains inaccessible:

    # wget localhost:3131/index.html
    HTTP request sent, awaiting response... 403 Forbidden
    [trimmed for clarity]

    Find the reason with the sealert tool:

    # sealert -l "*"
    SELinux is preventing httpd from getattr access on the file /var/test_www/html/index.html.
    [trimmed for clarity]
  6. Compare SELinux types for the standard and the new path using the matchpathcon tool:

    # matchpathcon /var/www/html
    /var/www/html   system_u:object_r:httpd_sys_content_t:s0
    # matchpathcon /var/test_www/html
    /var/test_www/html      system_u:object_r:var_t:s0
  7. Change the SELinux type of the new /var/test_www/html/ content directory to the type of the default /var/www/html directory:

    # semanage fcontext -a -e /var/www /var/test_www
  8. Relabel the /var directory recursively:

    # restorecon -Rv /var/
    Relabeled /var/test_www/html from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
    Relabeled /var/test_www/html/index.html from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

Verification steps

  1. Check that the httpd service is running:

    # systemctl status httpd
    Active: active (running)
    systemd[1]: Started The Apache HTTP Server.
    httpd[14888]: Server configured, listening on: port 3131
    [trimmed for clarity]
  2. Verify that the content provided by the Apache HTTP server is accessible:

    # wget localhost:3131/index.html
    HTTP request sent, awaiting response... 200 OK
    Length: 0 [text/html]
    Saving to: ‘index.html’
    [trimmed for clarity]

Additional resources

  • The semanage(8), matchpathcon(8), and sealert(8) man pages.

3.2. Adjusting the policy for sharing NFS and CIFS volumes using SELinux booleans

You can change parts of SELinux policy at runtime using booleans, even without any knowledge of SELinux policy writing. This enables changes, such as allowing services access to NFS volumes, without reloading or recompiling SELinux policy. The following procedure demonstrates listing SELinux booleans and configuring them to achieve the required changes in the policy.

NFS mounts on the client side are labeled with a default context defined by a policy for NFS volumes. In RHEL, this default context uses the nfs_t type. Also, Samba shares mounted on the client side are labeled with a default context defined by the policy. This default context uses the cifs_t type. You can enable or disable booleans to control which services are allowed to access the nfs_t and cifs_t types.

To allow the Apache HTTP server service (httpd) to access and share NFS and CIFS volumes, perform the following steps:


  • Optionally, install the selinux-policy-devel package to obtain clearer and more detailed descriptions of SELinux booleans in the output of the semanage boolean -l command.


  1. Identify SELinux booleans relevant for NFS, CIFS, and Apache:

    # semanage boolean -l | grep 'nfs\|cifs' | grep httpd
    httpd_use_cifs                 (off  ,  off)  Allow httpd to access cifs file systems
    httpd_use_nfs                  (off  ,  off)  Allow httpd to access nfs file systems
  2. List the current state of the booleans:

    $ getsebool -a | grep 'nfs\|cifs' | grep httpd
    httpd_use_cifs --> off
    httpd_use_nfs --> off
  3. Enable the identified booleans:

    # setsebool httpd_use_nfs on
    # setsebool httpd_use_cifs on

    Use setsebool with the -P option to make the changes persistent across restarts. A setsebool -P command requires a rebuild of the entire policy, and it might take some time depending on your configuration.

Verification steps

  1. Check that the booleans are on:

    $ getsebool -a | grep 'nfs\|cifs' | grep httpd
    httpd_use_cifs --> on
    httpd_use_nfs --> on

Additional resources

  • The semanage-boolean(8), sepolicy-booleans(8), getsebool(8), setsebool(8), booleans(5), and booleans(8) man pages.

3.3. Additional resources

Chapter 5. Creating SELinux policies for containers

RHEL 8 provides a tool for generating SELinux policies for containers using the udica package. With udica, you can create a tailored security policy for better control of how a container accesses host system resources, such as storage, devices, and network. This enables you to harden your container deployments against security violations and it also simplifies achieving and maintaining regulatory compliance.

5.1. Introduction to the udica SELinux policy generator

To simplify creating new SELinux policies for custom containers, RHEL 8 provides the udica utility. You can use this tool to create a policy based on an inspection of the container JavaScript Object Notation (JSON) file, which contains Linux-capabilities, mount-points, and ports definitions. The tool consequently combines rules generated using the results of the inspection with rules inherited from a specified SELinux Common Intermediate Language (CIL) block.

The process of generating SELinux policy for a container using udica has three main parts:

  1. Parsing the container spec file in the JSON format
  2. Finding suitable allow rules based on the results of the first part
  3. Generating final SELinux policy

During the parsing phase, udica looks for Linux capabilities, network ports, and mount points.

Based on the results, udica detects which Linux capabilities are required by the container and creates an SELinux rule allowing all these capabilities. If the container binds to a specific port, udica uses SELinux user-space libraries to get the correct SELinux label of a port that is used by the inspected container.

Afterward, udica detects which directories are mounted to the container file-system name space from the host.

The CIL’s block inheritance feature allows udica to create templates of SELinux allow rules focusing on a specific action, for example:

  • allow accessing home directories
  • allow accessing log files
  • allow accessing communication with Xserver.

These templates are called blocks and the final SELinux policy is created by merging the blocks.

Additional resources

5.2. Creating and using an SELinux policy for a custom container

To generate an SELinux security policy for a custom container, follow the steps in this procedure.


  • The podman tool for managing containers is installed. If it is not, use the yum install podman command.
  • A custom Linux container - ubi8 in this example.


  1. Install the udica package:

    # yum install -y udica
  2. Start the ubi8 container that mounts the /home directory with read-only permissions and the /var/spool directory with permissions to read and write. The container exposes the port 21.

    # podman run --env container=podman -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it ubi8 bash

    Note that now the container runs with the container_t SELinux type. This type is a generic domain for all containers in the SELinux policy and it might be either too strict or too loose for your scenario.

  3. Enter the podman ps command to obtain the ID of the container:

    # podman ps
    CONTAINER ID   IMAGE                                   COMMAND   CREATED          STATUS              PORTS   NAMES
    37a3635afb8f  bash      15 minutes ago   Up 15 minutes ago           heuristic_lewin
  4. Create a container JSON file, and use udica for creating a policy module based on the information in the JSON file:

    # podman inspect 37a3635afb8f > container.json
    # udica -j container.json my_container
    Policy my_container with container id 37a3635afb8f created!


    # podman inspect 37a3635afb8f | udica my_container
    Policy my_container with container id 37a3635afb8f created!
    Please load these modules using:
    # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
    Restart the container with: "--security-opt label=type:my_container.process" parameter
  5. As suggested by the output of udica in the previous step, load the policy module:

    # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
  6. Stop the container and start it again with the --security-opt label=type:my_container.process option:

    # podman stop 37a3635afb8f
    # podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it ubi8 bash

Verification steps

  1. Check that the container runs with the my_container.process type:

    # ps -efZ | grep my_container.process
    unconfined_u:system_r:container_runtime_t:s0-s0:c0.c1023 root 2275 434  1 13:49 pts/1 00:00:00 podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it ubi8 bash
    system_u:system_r:my_container.process:s0:c270,c963 root 2317 2305  0 13:49 pts/0 00:00:00 bash
  2. Verify that SELinux now allows access the /home and /var/spool mount points:

    [root@37a3635afb8f /]# cd /home
    [root@37a3635afb8f home]# ls
    [root@37a3635afb8f ~]# cd /var/spool/
    [root@37a3635afb8f spool]# touch test
    [root@37a3635afb8f spool]#
  3. Check that SELinux allows binding only to the port 21:

    [root@37a3635afb8f /]# yum install nmap-ncat
    [root@37a3635afb8f /]# nc -lvp 21
    Ncat: Version 7.60 ( )
    Ncat: Generating a temporary 1024-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.
    Ncat: SHA-1 fingerprint: 6EEC 102E 6666 5F96 CC4F E5FA A1BE 4A5E 6C76 B6DC
    Ncat: Listening on :::21
    Ncat: Listening on
    [root@37a3635afb8f /]# nc -lvp 80
    Ncat: Version 7.60 ( )
    Ncat: Generating a temporary 1024-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.
    Ncat: SHA-1 fingerprint: 6EEC 102E 6666 5F96 CC4F E5FA A1BE 4A5E 6C76 B6DC
    Ncat: bind to :::80: Permission denied. QUITTING.

Additional resources

  • For more information, see the udica(8) and podman(1) man pages.

5.3. Additional resources

Chapter 6. Deploying the same SELinux configuration on multiple systems

This section provides two recommended ways for deploying your verified SELinux configuration on multiple systems:

  • Using RHEL System Roles and Ansible
  • Using semanage export and import commands in your scripts

6.1. Introduction to the SELinux system role

RHEL System Roles is a collection of Ansible roles and modules that provide a consistent configuration interface to remotely manage multiple RHEL systems. The SELinux system role enables the following actions:

  • Cleaning local policy modifications related to SELinux booleans, file contexts, ports, and logins.
  • Setting SELinux policy booleans, file contexts, ports, and logins.
  • Restoring file contexts on specified files or directories.

The following table provides an overview of input variables available in the SELinux system role.

Table 6.1. SELinux system role variables

Role variableDescriptionCLI alternative


Chooses a policy protecting targeted processes or Multi Level Security protection.

SELINUXTYPE in /etc/selinux/config


Switches SELinux modes. See ansible-doc selinux

setenforce and SELINUX in /etc/selinux/config.


Enables and disables SELinux booleans. See ansible-doc seboolean.



Adds or removes a SELinux file context mapping. See ansible-doc sefcontext.

semanage fcontext


Restores SELinux labels in the file-system tree.

restorecon -R


Sets SELinux labels on ports. See ansible-doc seport.

semanage port


Sets users to SELinux user mapping. See ansible-doc selogin.

semanage login

The /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml example playbook installed by the rhel-system-roles package demonstrates how to set the targeted policy in enforcing mode. The playbook also applies several local policy modifications and restores file contexts in the /tmp/test_dir/ directory.

Additional resources

6.2. Using the SELinux system role to apply SELinux settings on multiple systems

Follow the steps to prepare and apply an Ansible playbook with your verified SELinux settings.



  1. Enable the RHEL Ansible repository, for example:

    # subscription-manager repos --enable ansible-2-for-rhel-8-x86_64-rpms
  2. Install Ansible Engine:

    # yum install ansible
  3. Install RHEL system roles:

    # yum install rhel-system-roles
  4. Apply your playbook with an SELinux system role.

    The following command applies an example playbook, which is a part of the rhel-system-roles package. You can use this playbook as a template:

    # ansible-playbook -i host1,host2,host3 /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml

Additional resources

  • For more information, install the rhel-system-roles package, and see the /usr/share/doc/rhel-system-roles/selinux/ and /usr/share/ansible/roles/rhel-system-roles.selinux/ directories.

6.3. Transferring SELinux settings to another system with semanage

Use the following steps for transferring your custom and verified SELinux settings between RHEL 8-based systems.


  • The policycoreutils-python-utils package is installed on your system.


  1. Export your verified SELinux settings:

    # semanage export -f ./my-selinux-settings.mod
  2. Copy the file with the settings to the new system:

    # scp ./my-selinux-settings.mod new-system-hostname
  3. Log in on the new system:

    $ ssh root@new-system-hostname
  4. Import the settings on the new system:

    new-system-hostname# semanage import -f ./my-selinux-settings.mod

Additional resources

  • semanage-export(8) and semanage-import(8) man pages

Legal Notice

Copyright © 2020 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.