Skip to main content
In this lesson, we’ll explore how to enforce Mandatory Access Control (MAC) using the SELinux security module. SELinux is enabled by default on Red Hat and CentOS systems, while Ubuntu uses AppArmor as its default security module. Before installing or configuring SELinux on a system set up by others, always verify which security module is active. In this guide, we assume that your Ubuntu system does not have SELinux enabled. We’ll walk you through disabling AppArmor, installing SELinux tools, and configuring SELinux from scratch.

Disabling AppArmor

Since AppArmor is enabled by default on Ubuntu systems, you must stop its service to avoid conflicts with SELinux:
After stopping the service, ensure that AppArmor does not automatically start on boot.

Installing SELinux and AuditD

To get started with SELinux, install the SELinux utilities along with the AuditD package. The SELinux package includes essential tools and default security policies, and AuditD logs system events—a critical resource when building custom SELinux policies. Below is a sample installation output. Your output may vary:
Similarly, when AuditD is configured, you might observe:

Verifying and Activating SELinux

To verify whether SELinux is enabled on your system, run:
If SELinux is disabled, the output will resemble:
You can also verify the current SELinux context assignments in the root directory:
To enable SELinux, execute:
This command modifies the GRUB bootloader to include the parameter necessary to load the SELinux module at boot. The output will inform you about generating the GRUB configuration and activate SELinux—after which a system reboot is recommended.

Configuring the Bootloader

After activating SELinux, verify the bootloader settings. In the /etc/default/grub file, you should see the following line instructing the kernel to load SELinux:
Once you confirm the configuration, note the presence of an autorelabel file in the root filesystem. This file tells SELinux to relabel every file upon reboot. For example, listing the root directory including hidden files shows:
Now, reboot your system to allow SELinux to relabel the filesystem. The relabeling process might take some time depending on the number of files:
During the first boot after enabling SELinux, the bootloader pauses for 30 seconds to allow intervention if necessary. Once complete, subsequent boots will operate normally. After rebooting, verify SELinux status by running:
Expected output:

Understanding SELinux Modes

SELinux operates in two primary modes:
  • Permissive: In this mode, SELinux logs policy violations without enforcing them. It is ideal for “training” your policies.
  • Enforcing: Here, SELinux actively enforces policies and may deny actions that do not comply with the defined rules.
To check the current mode, run:
When operating in permissive mode, actions that should be blocked are only logged. For instance, accessing via SSH may trigger AVC (Access Vector Cache) messages in the audit log. To inspect these messages, use:
The output might include entries like:
Although similar audit entries might be repeated, a single occurrence generally provides enough insight into the issue.

Examining Process and File Contexts

You can verify SELinux contexts for running processes and files. For example, to inspect the contexts of SSH daemons, run:
Sample output:
To view the context for the SSH daemon executable:
Expected output:
When a file labeled with sshd_exec_t is executed, SELinux transitions the process into the sshd_t domain, where its type enforcement rules become active.

Generating and Loading a Custom SELinux Policy

After operating in permissive mode and gathering necessary logs, you can generate a custom SELinux policy module from the audit logs. Run:
The command output will include a message similar to:
To load the custom policy module, execute:
If you see a warning such as “libsemanage.add_user: user sddm not in password file”, it is a known issue. You can safely ignore it if you are not using sddm.

Switching to Enforcing Mode

To temporarily switch SELinux from permissive to enforcing mode, execute:
Expected output:
For initial testing, it is advisable to use temporary enforcement. Once you are sure that your custom policies cover all the necessary actions, make the change permanent by modifying /etc/selinux/config. Open the configuration file with:
Then change:
to:
Save the file and reboot the system to apply the changes.

Reviewing the Custom Policy Module

After loading the custom module, two files are created:
  • A binary package (mymodule.pp)
  • A human-readable policy file (mymodule.te)
The .te file contains the type enforcement rules. An excerpt might look like:
Review this file carefully before deploying the policies in production.

Understanding and Reviewing SELinux Type Enforcement

The custom module includes specific rules for the sshd_t domain. For instance, it allows the SSH daemon to access files labeled with var_log_t:
This rule ensures that processes running in the sshd_t domain, such as the SSH daemon, can write to log files like /var/log/auth.log, which are labeled as var_log_t. You can verify these contexts with the following commands:
Expected outputs:
This level of fine-grained control helps restrict processes to specific files, reducing potential risks if a process (such as an NGINX web server) is compromised.

Changing SELinux File Contexts with chcon and restorecon

A file’s SELinux context is composed of three parts: user, role, and type. To manually change a file’s context, use the chcon command. For example, to view and modify the context of /var/log/auth.log:
To change the role and type:
Manual changes made with chcon may be overridden during a complete filesystem relabel.
To restore the default context, use the restorecon command. For example, to fix the context of /var/log/auth.log based on /var/log/dmesg as a reference:

Fixing Contexts for Web Content

If you create a new directory for your website under /var/www and add files, they may initially have an incorrect SELinux type (such as var_t). To correct this recursively:
After running restorecon -R /var/www/, the files should be relabeled correctly (for example, as httpd_sys_content_t), which is appropriate for web content. Note that restorecon by default only restores the type, not the user or role. If needed, use the force option to restore all parts of the label. To permanently assign a default label to a specific file (e.g., /var/www/10), add a rule with semanage:
For directories and their contents, remember to wrap the path in quotes if it contains special characters. Refer to the SELinux documentation for additional examples.

SELinux Booleans and Port Bindings

SELinux booleans act as switches to enable or disable related security policies. To list supported booleans and their current settings, run:
To set the virt_use_nfs boolean, execute:
SELinux also manages which ports a daemon is allowed to bind to. To list all allowed port bindings:
For instance, SSH is typically restricted to port 22. To allow SSH to bind to an additional port (such as 2222), run:
To later remove this port binding:
Any warnings regarding the user sddm may be safely ignored if you are not using sddm.

Conclusion

SELinux offers a robust mechanism for enforcing security policies by confining processes and controlling file access through detailed security contexts. While the setup and testing process can seem complex initially, running in permissive mode allows you to identify and adjust potential issues before switching to enforcing mode for full protection. With continuous study and practice, you can develop tailored SELinux policies that significantly reduce the risk of common attacks. Enjoy your journey to a more secure system!

Watch Video

Practice Lab