Managing SELinux: A Comprehensive Guide to Mandatory Access Control on Linux

SELinux (Security-Enhanced Linux) is a Linux kernel security module that provides a mechanism for supporting access control security policies, including Mandatory Access Control (MAC). Unlike traditional Discretionary Access Control (DAC), where owners can grant or deny permissions, SELinux imposes system-wide policies that even root cannot bypass without policy modification. It operates by labeling every file, process, and port with a security context and then enforcing rules based on interactions between these contexts.

Understanding SELinux Operation

When SELinux is active, the kernel performs checks in addition to standard Linux permissions. These checks involve:

  1. Security Contexts (Labels): Each file, directory, process, and network port is assigned a security label, known as a security context. This context contains information like the SELinux user, role, type, and sensitivity level (e.g., system_u:object_r:httpd_sys_content_t:s0). Processes can only interact with objects (files, other processes, ports) if their respective contexts allow it according to the loaded SELinux policy.
  2. Policy Enforcement for Programs: Beyond file access, SELinux policies also dictate what actions a program is allowed to perform. These granular permissions can be controlled through SELinux booleans, which act as on/off switches for specific policy rules or functionalities. For example, a boolean might control whether an FTP server can write to anonymous user directories.

SELinux States and Configuration

SELinux can operate in one of three primary states, configured in the /etc/selinux/config file:

  • SELINUX=enforcing: This is the default and most secure mode. SELinux actively enforces the policy, blocking any unauthorized actions and logging denial messages.
  • SELINUX=permissive: In this mode, SELinux does not enforce the policy, meaning no actions are blocked. However, it still logs denial messages, which is useful for troubleshooting and developing new policies without breaking existing applications.
  • SELINUX=disabled: SELinux is completely turned off. No policies are loaded, and no security contexts are applied or checked. This state requires a system reboot to take effect.

To change the SELinux state at boot, modify the SELINUX variable in /etc/selinux/config and then reboot the system.

# /etc/selinux/config
# SELINUX=disabled
SELINUX=enforcing
# SELINUX=permissive

You can check the current SELinux enforcement mode at runtime using the getenforce command:

$ getenforce
Enforcing

To switch between enforcing and permissive modes without a reboot, use the setenforce command:

# setenforce 0  # Switches to Permissive mode
# setenforce 1  # Switches to Enforcing mode

Note that setenforce cannot switch to a disabled state or enable SELinux if it's already disabled.

SELinux denials and warnings are logged in /var/log/audit/audit.log (if the auditd service is running) and often summarized in /var/log/messages, especially if the setroubleshoot-server package is installed.

Managing Security Contexts

Viewing Security Contexts

Security contexts are crucial for SELinux. You can view them for files, directories, and processes:

  • For files and directories: Use the -Z option with ls.
$ ls -Z /var/www/html/index.html
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html

$ ls -Zd /var/www/html/
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/

  • For processes: Use the -Z option with ps.
$ ps axZ | grep httpd
system_u:system_r:httpd_t:s0   876 ?        Ss     0:00 /usr/sbin/httpd
system_u:system_r:httpd_t:s0   877 ?        S      0:00 /usr/sbin/httpd

Modifying Security Contexts

Sometimes, files or directories might have incorrect security contexts, leading to access denied errors. There are two primary ways to modify them:

Temporary Modification (chcon)

The chcon command changes a file's security context temporarily. These changes do not persist across an SELinux relabel (e.g., during boot if .autorelabel exists) or a filesystem check.

# chcon -t public_content_t /srv/ftp_uploads/my_file.txt
# chcon -R -t public_content_t /srv/shared_data/ # Recursively apply to a directory

Here, -t specifies the type component of the security context. public_content_t is a common type for files intended to be publicly accessible by services like FTP or HTTP.

Persistent Modification (semanage fcontext and restorecon)

For permanent changes, you need to update the SELinux filesystem context mapping rules. These rules are stored in the SELinux policy database and specify what context files should have based on their path. The semanage fcontext command manages these rules, and restorecon applies them.

1. View existing filesystem context rules:

# semanage fcontext -l | grep httpd

2. Add a new rule to specify a security context for a path. For example, to label a custom web directory /srv/mywebsite with the httpd_sys_content_t type:

# semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"

The (/.*)? regular expression ensures that all files and subdirectories within /srv/mywebsite also inherit this context.

3. Apply the new or modified rules to the actual filesystem:

# restorecon -RvvF /srv/mywebsite/

  • -R: Recursively applies changes.
  • -v: Shows progress verbosely.
  • -F: Forces the restoration even if no changes are detected (useful for debugging).

If you need the entire filesystem to be relabeled on the next boot (e.g., after major policy changes or if contexts become heavily corrupted), create the .autorelabel file in the root directory:

# touch /.autorelabel
# reboot

Controlling Functionality with SELinux Booleans

SELinux booleans are on/off switches that modify the behavior of the SELinux policy, allowing or disallowing specific application functionalities without writing complex custom policies. This is commonly used for services like FTP, HTTP, Samba, etc.

1. List all SELinux booleans and their current states:

$ getsebool -a

To filter for specific booleans, for example, those related to FTP (ftpd):

$ getsebool -a | grep ftpd
ftpd_anon_write --> off
ftpd_connect_fusefs --> off
ftpd_connect_ntfs --> off
...

2. Change the state of a boolean. For example, to allow anonymous users to write files to FTP directories, you would enable the ftpd_anon_write boolean:

# setsebool -P ftpd_anon_write on

  • -P: Makes the change persistent across reboots. Without -P, the change is temporary.
  • on or off: Sets the boolean state.

Managing SELinux Network Port Labels

SELinux also controls which network ports processes can bind to and communicate over. This is managed through port labeling, where specific port numbers are assigned SELinux types.

1. List existing SELinux port mappings:

# semanage port -l | grep ssh
ssh_port_t                     tcp      22

2. Add a new port mapping. For instance, to allow a custom SSH daemon listening on port 2222, you would add this port to the ssh_port_t type:

# semanage port -a -t ssh_port_t -p tcp 2222

  • -a: Add a new record.
  • -t ssh_port_t: Assign the ssh_port_t type.
  • -p tcp: Specify the protocol (TCP or UDP).
  • 2222: The port number.

You can also modify (-m) or delete (-d) existing port definitions.

Troubleshooting with setroubleshoot

When SELinux denies an action, it logs an Access Vector Cache (AVC) denial message in /var/log/audit/audit.log. These messages can be cryptic. The setroubleshoot-server package (and its client setroubleshoot-plugins) helps interpret these messages by providing human-readable exlpanations and often suggesting solutions.

If setroubleshoot-server is installed and running, SELinux denial messages will also be processed and summarized in /var/log/messages, often including recommended commands to adjust policies or contexts to allow the blocked action.

Tags: selinux Linux Security Mandatory Access Control Security Contexts SELinux Booleans

Posted on Sat, 16 May 2026 21:29:20 +0000 by garydt