Chapter 19. Using SELinux - RHEL 8

https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/system_design_guide/using_selinux

19.1. Getting started with SELinux

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

19.1.1. Introduction to SELinux

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.

Security Enhanced Linux (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.

Note 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 19.1. An example how can SELinux help to run Apache and MariaDB in a secure way.

SELinux_Apache_MariaDB_example 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

selinux(8) man page and man pages listed by the apropos selinux command. Man pages listed by the man -k _selinux command when the selinux-policy-doc package is installed. The SELinux Coloring Book helps you to better understand SELinux basic concepts. 19.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. SELinux provides 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. SELinux can mitigate 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 enforce data confidentiality and integrity, and can protect processes from untrusted inputs. SELinux is designed to enhance existing security solutions, not replace antivirus software, secure passwords, firewalls, or other security systems. 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.

19.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. 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 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 RHEL, even if an administrator forgets to limit which servers can perform a zone transfer, the default SELinux policy prevent updates for zone files [1] that use zone transfers, by the BIND named daemon itself, and by other processes. Without SELinux, an attacker can misuse a vulnerability to path traversal on an Apache web server and access files and directories stored on the file system by using special elements such as ../. If an attacker attempts an attack on a server running with SELinux in enforcing mode, SELinux denies access to files that the httpd process must not access. SELinux cannot block this type of attack completely but it effectively mitigates it. SELinux in enforcing mode successfully prevents exploitation of kernel NULL pointer dereference operators on non-SMAP platforms (CVE-2019-9213). Attackers use a vulnerability in the mmap function, which does not check mapping of a null page, for placing arbitrary code on this page. The deny_ptrace SELinux boolean and SELinux in enforcing mode protect systems from the PTRACE_TRACEME vulnerability (CVE-2019-13272). Such configuration prevents scenarios when an attacker can get root privileges. The nfs_export_all_rw and nfs_export_all_ro SELinux booleans provide an easy-to-use tool to prevent misconfigurations of Network File System (NFS) such as accidental sharing /home directories. Additional resources

SELinux as a security pillar of an operating system - Real-world benefits and examples (Red Hat Knowledgebase) SELinux hardening with Ansible (Red Hat Knowledgebase) selinux-playbooks Github repository with Ansible playbooks for SELinux hardening 19.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 RHEL 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.

If a process is sending a D-Bus message to another process and if the SELinux policy does not allow the D-Bus communication of these two processes, then the system prints a USER_AVC denial message, and the D-Bus communication times out. Note that the D-Bus communication between two processes works bidirectionally.

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

RHEL 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 19.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 labelling 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 labelling 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

Enforcing

setenforce 0

getenforce

Permissive Show more

setenforce 1

getenforce

Enforcing Show more

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.

19.2. Changing SELinux states and modes

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

19.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 Show more

Warning When systems run SELinux in permissive mode, users and processes might label various file-system objects incorrectly. File-system objects created while SELinux is disabled are not labeled at all. This behaviour 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, SELinux automatically relabels file systems when changing from the disabled state to permissive or enforcing 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.

Before rebooting the system for relabeling, make sure the system will boot in permissive mode, for example by using the enforcing=0 kernel option. This prevents the system from failing to boot in case the system contains unlabeled files required by systemd before launching the selinux-autorelabel service. For more information, see RHBZ#2021835.

19.2.2. Changing SELinux 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.

Prerequisites

The selinux-policy-targeted, libselinux-utils, and policycoreutils packages are installed on your system. The selinux=0 or enforcing=0 kernel parameters are not used. Procedure

Open the /etc/selinux/config file in a text editor of your choice, for example:

vi /etc/selinux/config

Configure the SELINUX=permissive option:

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.

SELINUX=permissive

SELINUXTYPE= can take one of these two values:

targeted - Targeted processes are protected,

mls - Multi Level Security protection.

SELINUXTYPE=targeted Show more

Restart the system:

reboot

Verification

After the system restarts, confirm that the getenforce command returns Permissive:

$ getenforce Permissive

19.2.3. Changing SELinux to enforcing mode

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

Prerequisites

The selinux-policy-targeted, libselinux-utils, and policycoreutils packages are installed on your system. The selinux=0 or enforcing=0 kernel parameters are not used. Procedure

Open the /etc/selinux/config file in a text editor of your choice, for example:

vi /etc/selinux/config

Configure the SELINUX=enforcing option:

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.

SELINUX=enforcing

SELINUXTYPE= can take one of these two values:

targeted - Targeted processes are protected,

mls - Multi Level Security protection.

SELINUXTYPE=targeted Show more

Save the change, and restart 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.

Verification

After the system restarts, confirm that the getenforce command returns Enforcing:

$ getenforce Enforcing

Troubleshooting

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:

ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts today

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

See Troubleshooting problems related to SELinux for more information.

19.2.4. Enabling SELinux on systems that previously had it disabled

To avoid problems, such as systems unable to boot or process failures, when enabling SELinux on systems that previously had it disabled, resolve Access Vector Cache (AVC) messages in permissive mode first.

When systems run SELinux in permissive mode, users and processes might label various file-system objects incorrectly. File-system objects created while SELinux is disabled are not labeled at all. This behaviour 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, SELinux automatically relabels file systems when changing from the disabled state to permissive or enforcing mode.

Warning Before rebooting the system for relabeling, make sure the system will boot in permissive mode, for example by using the enforcing=0 kernel option. This prevents the system from failing to boot in case the system contains unlabeled files required by systemd before launching the selinux-autorelabel service. For more information, see RHBZ#2021835.

Procedure

Enable SELinux in permissive mode. For more information, see Changing to permissive mode. Restart your system:

reboot

Check for SELinux denial messages. For more information, see Identifying SELinux denials. Ensure that files are relabeled upon the next reboot:

fixfiles -F onboot

This creates the /.autorelabel file containing the -F option.

Warning Always switch to permissive mode before entering the fixfiles -F onboot command.

By default, autorelabel uses as many threads in parallel as the system has available CPU cores. To use only a single thread during automatic relabeling, use the fixfiles -T 1 onboot command.

If there are no denials, switch to enforcing mode. For more information, see Changing SELinux modes at boot time. Verification

After the system restarts, confirm that the getenforce command returns Enforcing:

$ getenforce Enforcing

Next steps

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 a custom SELinux policy section for more information. Additional resources

SELinux states and modes section covers temporary changes in modes. 19.2.5. Disabling SELinux

When you disable SELinux, your system does not load your SELinux policy. As a result, the system does not enforce the SELinux policy and does not log Access Vector Cache (AVC) messages. Therefore, all benefits of running SELinux are lost.

Do not disable SELinux except in specific scenarios, such as performance-sensitive systems where the weakened security does not impose significant risks.

Important If your scenario requires to perform debugging in a production environment, temporarily use permissive mode instead of permanently disabling SELinux. See Changing to permissive mode for more information about permissive mode.

Prerequisites

The grubby package is installed:

$ rpm -q grubby grubby-

Procedure

Configure your boot loader to add selinux=0 to the kernel command line:

$ sudo grubby –update-kernel ALL –args selinux=0

Restart your system:

$ reboot

Verification

After the reboot, confirm that the getenforce command returns Disabled:

$ getenforce Disabled

Alternative method

In RHEL 8, you can still use the deprecated method for disabling SELinux by using the SELINUX=disabled option in the /etc/selinux/config file. This results the kernel booting with SELinux enabled and switching to disabled mode later in the boot process. Consequently, memory leaks and race conditions might occur that cause kernel panics. To use this method:

Open the /etc/selinux/config file in a text editor of your choice, for example:

vi /etc/selinux/config

Configure the SELINUX=disabled option:

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.

SELINUX=disabled

SELINUXTYPE= can take one of these two values:

targeted - Targeted processes are protected,

mls - Multi Level Security protection.

SELINUXTYPE=targeted Show more

Save the change, and restart your system:

reboot

19.2.6. Changing SELinux modes at boot time

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

enforcing=0 Setting this parameter causes the system to start 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 from a series of the same denials is reported. However, in enforcing mode, you might get a denial related to 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.

selinux=0 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.

Important Do not use the selinux=0 parameter in a production environment. To debug your system, temporarily use permissive mode instead of disabling SELinux.

autorelabel=1 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, start the system in permissive mode to make the autorelabel process successful.

Additional resources

For additional SELinux-related kernel boot parameters, such as checkreqprot, see the /usr/share/doc/kernel-doc-/Documentation/admin-guide/kernel-parameters.txt file installed with the kernel-doc package. Replace the string with the version number of the installed kernel, for example:

yum install kernel-doc

$ less /usr/share/doc/kernel-doc-4.18.0/Documentation/admin-guide/kernel-parameters.txt

19.3. Troubleshooting problems related to SELinux

If you plan to enable SELinux on systems where it has been previously disabled or if you run a service in a non-standard configuration, you might need to troubleshoot situations potentially blocked by SELinux. Note that in most cases, SELinux denials are signs of misconfiguration.

19.3.1. Identifying SELinux denials

Follow only the necessary steps from this procedure; in most cases, you need to perform just step 1.

Procedure

When your scenario is blocked by SELinux, the /var/log/audit/audit.log file is the first place to check for more information about a denial. To query Audit logs, use the ausearch tool. Because the SELinux decisions, such as allowing or disallowing access, are cached and this cache is known as the Access Vector Cache (AVC), use the AVC and USER_AVC values for the message type parameter, for example:

ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent

If there are no matches, check if the Audit daemon is running. If it does not, repeat the denied scenario after you start auditd and check the Audit log again.

In case auditd is running, but there are no matches in the output of ausearch, check messages provided by the systemd Journal:

journalctl -t setroubleshoot

If SELinux is active and the Audit daemon 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

Even after the previous three checks, it is still possible that you have not found anything. In this case, AVC denials can be silenced because of dontaudit rules.

To temporarily disable dontaudit rules, allowing all denials to be logged:

semodule -DB

After re-running your denied scenario and finding denial messages using the previous steps, the following command enables dontaudit rules in the policy again:

semodule -B

If you apply all four previous steps, and the problem still remains unidentified, consider if SELinux really blocks your scenario:

Switch to permissive mode:

setenforce 0

$ getenforce Permissive Show more

Repeat your scenario. If the problem still occurs, something different than SELinux is blocking your scenario.

19.3.2. Analyzing SELinux denial messages

After identifying that SELinux is blocking your scenario, you might need to analyze the root cause before you choose a fix.

Prerequisites

The policycoreutils-python-utils and setroubleshoot-server packages are installed on your system. Procedure

List more details about a logged denial using the sealert command, for example:

$ sealert -l “*” SELinux is preventing /usr/bin/passwd from write access on the file /root/test.

*** Plugin leaks (86.2 confidence) suggests ***********

If you want to ignore passwd trying to write access the test file, because you believe it should not need this access. Then you should report this as a bug. You can generate a local policy module to dontaudit this access. Do

ausearch -x /usr/bin/passwd –raw | audit2allow -D -M my-passwd

semodule -X 300 -i my-passwd.pp

*** Plugin catchall (14.7 confidence) suggests **********

Raw Audit Messages type=AVC msg=audit(1553609555.619:127): avc: denied { write } for pid=4097 comm=”passwd” path=”/root/test” dev=”dm-0” ino=17142697 scontext=unconfined_u:unconfined_r:passwd_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0

Hash: passwd,passwd_t,admin_home_t,file,write Show more

If the output obtained in the previous step does not contain clear suggestions:

Enable full-path auditing to see full paths to accessed objects and to make additional Linux Audit event fields visible:

auditctl -w /etc/shadow -p w -k shadow-write

Clear the setroubleshoot cache:

rm -f /var/lib/setroubleshoot/setroubleshoot.xml

Reproduce the problem. Repeat step 1.

After you finish the process, disable full-path auditing:

auditctl -W /etc/shadow -p w -k shadow-write

If sealert returns only catchall suggestions or suggests adding a new rule using the audit2allow tool, match your problem with examples listed and explained in SELinux denials in the Audit log. Additional resources

sealert(8) man page on your system 19.3.3. Fixing analyzed SELinux denials

In most cases, suggestions provided by the sealert tool give you the right guidance about how to fix problems related to the SELinux policy. See Analyzing SELinux denial messages for information how to use sealert to analyze SELinux denials.

Be careful when the tool suggests using the audit2allow tool for configuration changes. You should not use audit2allow to generate a local policy module as your first option when you see an SELinux denial. Troubleshooting should start with a check if there is a labelling problem. The second most often case is that you have changed a process configuration, and you forgot to tell SELinux about it.

labelling problems

A common cause of labelling problems is when a non-standard directory is used for a service. For example, instead of using /var/www/html/ for a website, an administrator might want to use /srv/myweb/. On Red Hat Enterprise Linux, the /srv directory is labeled with the var_t type. Files and directories created in /srv inherit this type. Also, newly-created objects in top-level directories, such as /myserver, can be labeled with the default_t type. SELinux prevents the Apache HTTP Server (httpd) from accessing both of these types. To allow access, SELinux must know that the files in /srv/myweb/ are to be accessible by httpd:

semanage fcontext -a -t httpd_sys_content_t “/srv/myweb(/.*)?”

This semanage command adds the context for the /srv/myweb/ directory and all files and directories under it to the SELinux file-context configuration. The semanage utility does not change the context. As root, use the restorecon utility to apply the changes:

restorecon -R -v /srv/myweb

Incorrect context

The matchpathcon utility checks the context of a file path and compares it to the default label for that path. The following example demonstrates the use of matchpathcon on a directory that contains incorrectly labeled files:

$ matchpathcon -V /var/www/html/* /var/www/html/index.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0 /var/www/html/page1.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0 Show more

In this example, the index.html and page1.html files are labeled with the user_home_t type. This type is used for files in user home directories. Using the mv command to move files from your home directory may result in files being labeled with the user_home_t type. This type should not exist outside of home directories. Use the restorecon utility to restore such files to their correct type:

restorecon -v /var/www/html/index.html

restorecon reset /var/www/html/index.html context unconfined_u:object_r:user_home_t:s0->system_u:object_r:httpd_sys_content_t:s0

To restore the context for all files under a directory, use the -R option:

restorecon -R -v /var/www/html/

restorecon reset /var/www/html/page1.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0 restorecon reset /var/www/html/index.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0 Show more

Confined applications configured in non-standard ways

Services can be run in a variety of ways. To account for that, you need to specify how you run your services. You can achieve this through SELinux booleans that allow parts of SELinux policy to be changed at runtime. This enables changes, such as allowing services access to NFS volumes, without reloading or recompiling SELinux policy. Also, running services on non-default port numbers requires policy configuration to be updated using the semanage command.

For example, to allow the Apache HTTP Server to communicate with MariaDB, enable the httpd_can_network_connect_db boolean:

setsebool -P httpd_can_network_connect_db on

Note that the -P option makes the setting persistent across reboots of the system.

If access is denied for a particular service, use the getsebool and grep utilities to see if any booleans are available to allow access. For example, use the getsebool -a grep ftp command to search for FTP related booleans:

$ getsebool -a | grep ftp ftpd_anon_write –> off ftpd_full_access –> off ftpd_use_cifs –> off ftpd_use_nfs –> off

ftpd_connect_db –> off httpd_enable_ftp_server –> off tftp_anon_write –> off Show more

To get a list of booleans and to find out if they are enabled or disabled, use the getsebool -a command. To get a list of booleans including their meaning, and to find out if they are enabled or disabled, install the selinux-policy-devel package and use the semanage boolean -l command as root.

Port numbers

Depending on policy configuration, services can only be allowed to run on certain port numbers. Attempting to change the port a service runs on without changing policy may result in the service failing to start. For example, run the semanage port -l grep http command as root to list http related ports:

semanage port -l | grep http

http_cache_port_t tcp 3128, 8080, 8118 http_cache_port_t udp 3130 http_port_t tcp 80, 443, 488, 8008, 8009, 8443 pegasus_http_port_t tcp 5988 pegasus_https_port_t tcp 5989 Show more

The http_port_t port type defines the ports Apache HTTP Server can listen on, which in this case, are TCP ports 80, 443, 488, 8008, 8009, and 8443. If an administrator configures httpd.conf so that httpd listens on port 9876 (Listen 9876), but policy is not updated to reflect this, the following command fails:

systemctl start httpd.service

Job for httpd.service failed. See ‘systemctl status httpd.service’ and ‘journalctl -xn’ for details.

systemctl status httpd.service

httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled) Active: failed (Result: exit-code) since Thu 2013-08-15 09:57:05 CEST; 59s ago Process: 16874 ExecStop=/usr/sbin/httpd $OPTIONS -k graceful-stop (code=exited, status=0/SUCCESS) Process: 16870 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE) Show more

An SELinux denial message similar to the following is logged to /var/log/audit/audit.log:

type=AVC msg=audit(1225948455.061:294): avc: denied { name_bind } for pid=4997 comm=”httpd” src=9876 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket

To allow httpd to listen on a port that is not listed for the http_port_t port type, use the semanage port command to assign a different label to the port:

semanage port -a -t http_port_t -p tcp 9876

The -a option adds a new record; the -t option defines a type; and the -p option defines a protocol. The last argument is the port number to add.

Corner cases, evolving or broken applications, and compromised systems

Applications may contain bugs, causing SELinux to deny access. Also, SELinux rules are evolving - SELinux may not have seen an application running in a certain way, possibly causing it to deny access, even though the application is working as expected. For example, if a new version of PostgreSQL is released, it may perform actions the current policy does not account for, causing access to be denied, even though access should be allowed.

For these situations, after access is denied, use the audit2allow utility to create a custom policy module to allow access. You can report missing rules in the SELinux policy by filing a support case on the Red Hat Customer Portal. Mention the selinux-policy component and include the output of the audit2allow -w -a and audit2allow -a commands in the case.

If an application asks for major security privileges, it could be a signal that the application is compromised. Use intrusion detection tools to inspect such suspicious behaviour.

The Solution Engine on the Red Hat Customer Portal can also provide guidance in the form of an article containing a possible solution for the same or very similar problem you have. Select the relevant product and version and use SELinux-related keywords, such as selinux or avc, together with the name of your blocked service or application, for example: selinux samba.

19.3.4. Creating a local SELinux policy module

Adding specific SELinux policy modules to an active SELinux policy can fix certain problems with the SELinux policy. You can use this procedure to fix a specific Known Issue described in Red Hat release notes, or to implement a specific Red Hat Solution.

Warning Use only rules provided by Red Hat. Red Hat does not support creating SELinux policy modules with custom rules, because this falls outside of the Production Support Scope of Coverage. If you are not an expert, contact your Red Hat sales representative and request consulting services.

Prerequisites

The setools-console and audit packages for verification. Procedure

Open a new .cil file with a text editor, for example:

vim .cil

To keep your local modules better organised, use the local_ prefix in the names of local SELinux policy modules.

Insert the custom rules from a Known Issue or a Red Hat Solution.

Important Do not write your own rules. Use only the rules provided in a specific Known Issue or Red Hat Solution.

For example, to implement the SELinux denies cups-lpd read access to cups.sock in RHEL solution, insert the following rule:

(allow cupsd_lpd_t cupsd_var_run_t (sock_file (read)))

The example solution has been fixed permanently for RHEL in RHBA-2021:4420. Therefore, the parts of this procedure specific to this solution have no effect on updated RHEL 8 and 9 systems, and are included only as examples of syntax.

You can use either of the two SELinux rule syntaxes, Common Intermediate Language (CIL) and m4. For example, (allow cupsd_lpd_t cupsd_var_run_t (sock_file (read))) in CIL is equivalent to the following in m4:

module local_cupslpd-read-cupssock 1.0;

require { type cupsd_var_run_t; type cupsd_lpd_t; class sock_file read; }

#============= cupsd_lpd_t ============== allow cupsd_lpd_t cupsd_var_run_t:sock_file read; Show more

Save and close the file. Install the policy module:

semodule -i .cil

If you want to remove a local policy module which you created by using semodule -i, refer to the module name without the .cil suffix. To remove a local policy module, use semodule -r .

Restart any services related to the rules:

systemctl restart

Verification

List the local modules installed in your SELinux policy:

semodule -lfull | grep “local_”

400 local_module cil

Because local modules have priority 400, you can filter them from the list also by using that value, for example, by using the semodule -lfull grep -v ^100 command.

Search the SELinux policy for the relevant allow rules:

sesearch -A –source= --target= --class= --perm=,

Where is the source SELinux type, is the target SELinux type, is the security class or object class name, and and are the specific permissions of the rule.

For example, to implment the SELinux denies cups-lpd read access to cups.sock in RHEL Red Hat Knowledgbase solution:

sesearch -A –source=cupsd_lpd_t –target=cupsd_var_run_t –class=sock_file –perm=read

allow cupsd_lpd_t cupsd_var_run_t:sock_file { append getattr open read write };

The last line should now include the read operation.

Verify that the relevant service runs confined by SELinux:

Identify the process related to the relevant service:

$ systemctl status

Check the SELinux context of the process listed in the output of the previous command:

$ ps -efZ grep

Verify that the service does not cause any SELinux denials:

ausearch -m AVC -i -ts recent

The -i option interprets the numeric values into human-readable text. Additional resources How to create custom SELinux policy module wisely Knowledgebase article Troubleshooting problems related to SELinux 19.3.5. SELinux denials in the Audit log The Linux Audit system stores log entries in the /var/log/audit/audit.log file by default. To list only SELinux-related records, use the ausearch command with the message type parameter set to AVC and AVC_USER at a minimum, for example: # ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR An SELinux denial entry in the Audit log file can look as follows: type=AVC msg=audit(1395177286.929:1638): avc: denied { read } for pid=6591 comm="httpd" name="webpages" dev="0:37" ino=2112 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:nfs_t:s0 tclass=dir The most important parts of this entry are: avc: denied - the action performed by SELinux and recorded in Access Vector Cache (AVC) { read } - the denied action pid=6591 - the process identifier of the subject that tried to perform the denied action comm="httpd" - the name of the command that was used to invoke the analyzed process httpd_t - the SELinux type of the process nfs_t - the SELinux type of the object affected by the process action tclass=dir - the target object class The previous log entry can be translated to: SELinux denied the httpd process with PID 6591 and the httpd_t type to read from a directory with the nfs_t type. The following SELinux denial message occurs when the Apache HTTP Server attempts to access a directory labeled with a type for the Samba suite: type=AVC msg=audit(1226874073.147:96): avc: denied { getattr } for pid=2465 comm="httpd" path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file { getattr } - the getattr entry indicates the source process was trying to read the target file’s status information. This occurs before reading files. SELinux denies this action because the process accesses the file and it does not have an appropriate label. Commonly seen permissions include getattr, read, and write. path="/var/www/html/file1" - the path to the object (target) the process attempted to access. scontext="unconfined_u:system_r:httpd_t:s0" - the SELinux context of the process (source) that attempted the denied action. In this case, it is the SELinux context of the Apache HTTP Server, which is running with the httpd_t type. tcontext="unconfined_u:object_r:samba_share_t:s0" - the SELinux context of the object (target) the process attempted to access. In this case, it is the SELinux context of file1. This SELinux denial can be translated to: SELinux denied the httpd process with PID 2465 to access the /var/www/html/file1 file with the samba_share_t type, which is not accessible to processes running in the httpd_t domain unless configured otherwise. Additional resources auditd(8) and ausearch(8) man pages on your system 19.3.6. Additional resources Basic SELinux Troubleshooting in CLI (Red Hat Knowledgebase) What is SELinux trying to tell me? The 4 key causes of SELinux errors (Fedora People) [1] Text files that include DNS information, such as hostname to IP address mappings.

Updated: