This article explains how to enforce Mandatory Access Control using SELinux on Ubuntu systems, including installation, configuration, and policy management.
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.
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:
You can also verify the current SELinux context assignments in the root directory:
Copy
Ask AI
jeremy@kodekLOUD:~$ ls -Z /? bin ? lib64 ? mnt ? run? boot ? home ? lost+found ? proc...
To enable SELinux, execute:
Copy
Ask AI
sudo selinux-activate
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.
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:
Copy
Ask AI
GRUB_CMDLINE_LINUX="security=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:
Copy
Ask AI
jeremy@kodekLOUD:~$ ls -a /. bin.usr-is-merged etc lib.usr-is-merged opt sbin swap.img var.. boot home lost+found proc sbin.usr-is-merged root snap.autolabel cdrom lib media mnt run srv tmp usr
Now, reboot your system to allow SELinux to relabel the filesystem. The relabeling process might take some time depending on the number of files:
Copy
Ask AI
sudo reboot
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:
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:
Copy
Ask AI
getenforce
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:
Copy
Ask AI
sudo audit2why --all | less
The output might include entries like:
Copy
Ask AI
type=AVC msg=audit(1716410944.847:111): avc: denied { execute } for pid=922 comm="run-parts" name="1-landscape-sysinfo.wrapper" dev="dm-0" ino=284986 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:usr_t:s0 tclass=file permissive=1 Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access.
Although similar audit entries might be repeated, a single occurrence generally provides enough insight into the issue.
To view the context for the SSH daemon executable:
Copy
Ask AI
ls -Z /usr/sbin/sshd
Expected output:
Copy
Ask AI
system_u:object_r:sshd_exec_t:s0 /usr/sbin/sshd
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.
After operating in permissive mode and gathering necessary logs, you can generate a custom SELinux policy module from the audit logs. Run:
Copy
Ask AI
sudo audit2allow --all -M mymodule
The command output will include a message similar to:
Copy
Ask AI
********************* IMPORTANT *********************To make this policy package active, execute:semodule -i mymodule.pp
To load the custom policy module, execute:
Copy
Ask AI
sudo semodule -i mymodule.pp
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.
To temporarily switch SELinux from permissive to enforcing mode, execute:
Copy
Ask AI
sudo setenforce 1getenforce
Expected output:
Copy
Ask AI
Enforcing
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:
Copy
Ask AI
sudo vim /etc/selinux/config
Then change:
Copy
Ask AI
SELINUX=permissive
to:
Copy
Ask AI
SELINUX=enforcing
Save the file and reboot the system to apply the changes.
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:
Copy
Ask AI
module mymodule 1.0;require { type sshd_t; type tmp_t; type getty_t; type systemd_journal_init_t; type policykit_t; type mount_exec_t; type kmod_t; type var_t; type systemd_journal_t; type systemd_runtime_notify_t; type xdg_cache_t; type fixed_disk_device_t; type fsadm_exec_t; type mount_runtime_t; type var_lib_t; type mount_t; type systemd_hostnamed_t; type var_log_t; type etc_runtime_t; type lib_t; type system_dbusd_t; type usr_t;};class dir { add_name search watch write };class dbus send_msg;
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:
Copy
Ask AI
allow sshd_t var_log_t:file { append create getattr ioctl open };
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:
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:
Copy
Ask AI
ls -Z /var/log/auth.logsudo chcon -u unconfined_u /var/log/auth.log
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:
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:
Copy
Ask AI
sudo mkdir /var/wwwsudo touch /var/www/{1..10}ls -Z /var/www/# Files may initially be labeled as:# unconfined_u:object_r:var_t:s0sudo restorecon -R /var/www/ls -Z /var/www/
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:
Copy
Ask AI
sudo semanage fcontext --add --type var_log_t /var/www/10# You might encounter:# libsemanage.add_user: user sddm not in password filesudo restorecon /var/www/10
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 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!