
Learn how to manage SELinux contexts on RHEL 9 and CentOS 9 for improved security. This guide covers SELinux contexts, CLI commands, troubleshooting, and best
Compare SELinux and fapolicyd on RHEL 8/9. Learn the core differences between Mandatory Access Control (SELinux) and Application Whitelisting (fapolicyd), why both are essential for a robust defense-in-depth strategy, and how to manage their policies for ultimate system hardening.
In today’s complex threat landscape, securing a Red Hat Enterprise Linux (RHEL) server requires a robust, multi-layered approach. While traditional Discretionary Access Control (DAC)—the standard Linux file permissions—provides a foundational layer, it’s insufficient for modern security requirements, especially in highly regulated environments.
For years, Security-Enhanced Linux (SELinux) has been the cornerstone of security hardening on RHEL, providing a powerful Mandatory Access Control (MAC) framework. However, RHEL 8 and 9 introduced a new and complementary tool: the File Access Policy Daemon (fapolicyd). This newcomer often raises questions: Is one replacing the other? Which one is better?
The answer is simple: you need both. |
SELinux and fapolicyd are not competing technologies; they are complementary security layers that address different aspects of application and file control. Understanding their distinct roles and how they work in concert is crucial for creating a truly robust, defense-in-depth security posture on your RHEL systems.
This comprehensive guide delves into the core differences between SELinux and fapolicyd, explains their unique functions, and demonstrates how to leverage both tools to achieve maximum security and compliance on RHEL 8 and 9.
To grasp the synergy between SELinux and fapolicyd, we must first examine the two primary models of access control in Linux:
|
|
SELinux is a kernel-level security module that implements Mandatory Access Control (MAC) by assigning security labels, known as contexts, to every process, file, and system object.
🟢 What SELinux Does |
The primary function of SELinux is to confine processes and limit their access to files and other resources. Its enforcement decision is based on the context type—not traditional user IDs or file paths.
|
|
|
| Component | Description | Example |
| Context | A label assigned to all subjects and objects. Format: user:role:type:level. | system_u:object_r:httpd_sys_content_t:s0 |
| Type | The most important part of the context, defining the object’s role/purpose. | httpd_t (for the Apache process), sshd_exec_t (for the sshd executable) |
| Domain | The type for a process, confining its actions. | httpd_t |
| Policy | A set of rules that defines which types can access which other types. | allow httpd_t httpd_sys_content_t : file { read write }; |
🖥️ SELinux CLI Examples |
To check the SELinux mode:
$ getenforce
Enforcing
To view the SELinux context of a file:
ls -Z /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
To set the correct context for a non-standard web directory:
semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
restorecon -Rv /srv/www
The File Access Policy Daemon (fapolicyd) is a crucial, modern layer of security introduced in RHEL 8. It utilizes the fanotify kernel interface to monitor file access events and, more specifically, to enforce an application whitelisting policy.
🟢 What fapolicyd Does |
The core mission of fapolicyd is to answer the question: “Is this application trusted to run?” It operates on an implicit deny principle for execution: only applications explicitly listed and verified as trusted are allowed to execute.
|
|
|
| Component | Description | Location |
| Trust Database | A list of binaries and libraries known to be legitimate, typically installed by the system package manager (DNF/RPM), including their hashes. | Internal DB, managed by fapolicyd-cli |
| Policy Rules | User-defined rules to allow or deny execution based on path, MIME type, user, or trust status. | Files in /etc/fapolicyd/rules.d/ |
| Enforcement | Blocks execution attempts of untrusted files. | Kernel-level (via fanotify) |
🖥️ fapolicyd CLI Examples |
To check the status of the daemon:
sudo systemctl status fapolicyd
To manually trust a file not installed via DNF (e.g., a custom script):
sudo /usr/sbin/fapolicyd-cli --file add /opt/custom/app/run.sh --trust-file custom-apps
sudo /usr/sbin/fapolicyd-cli --update
To audit for any denial events:
sudo ausearch -m FANOTIFY -i
The true strength of RHEL security comes from running SELinux and fapolicyd in parallel. They form a Defense-in-Depth strategy where each layer covers vulnerabilities the other might miss.
| Feature | SELinux | fapolicyd |
| Primary Goal | Mandatory Access Control (MAC) & Process Isolation. | Application Whitelisting & Integrity Enforcement. |
| What it Checks | Context (Type) of the subject (process) and the object (file). | Trust (Integrity/Hash, Origin) of the executable file. |
| Decision Point | During process operation (e.g., file read/write, network connection). | Before a file is executed (open/execute event). |
| Protection Against | Compromised running processes (lateral movement, privilege escalation). | Execution of unknown, unauthorized, or tampered binaries/scripts. |
| Best Analogy | The Warden: Controls what a prisoner (process) can touch inside the jail cell (domain). | The Bouncer: Decides who (executable) is allowed to enter the club (system) in the first place, checking their ID (hash). |
🛡️ The Synergy in Action |
|
|
|
|
|
|
Effectively leveraging both tools requires them to be in their strongest state: enforcing.
🧩 SELinux Management |
Ensure SELinux is set to enforcing in the configuration file and verify the status:
# Check current status
sudo getenforce
# Check policy context of a service process (e.g., web server)
ps -eZ | grep httpd
system_u:system_r:httpd_t:s0 ... /usr/sbin/httpd
🧩 Common Management Task: Changing Contexts |
If you move a file to a non-standard location and SELinux blocks access, you must set the correct context and make the change persistent.
# 1. Temporarily change context for /var/log/custom/app.log to be written by httpd
chcon -t httpd_log_t /var/log/custom/app.log
# 2. Make the change persistent for reboots/relabels
semanage fcontext -a -t httpd_log_t "/var/log/custom(/.*)?"
restorecon -Rv /var/log/custom
🧩 fapolicyd Management |
fapolicyd is typically installed and started by default on security-focused RHEL installations (like those meeting DISA STIG requirements), but it must be configured for non-RPM-installed applications.
# Install (if not present)
dnf install fapolicyd
# Enable and start the service
systemctl enable --now fapolicyd
🧩 Common Management Task: Trusting a Custom Application |
For an application that is compiled locally or installed outside of DNF, you must explicitly trust its binaries.
# Trust all executable files inside a custom directory
sudo /usr/sbin/fapolicyd-cli --file add /opt/myapp/bin/ --trust-file my_app_trust
sudo /usr/sbin/fapolicyd-cli --update
🧩 Customizing Policy Rules |
For more fine-grained control, you can define rules in the /etc/fapolicyd/rules.d/ directory. Rules are processed sequentially, and the first match is used. A typical rule file looks like this:
# Rule 10: Allow all trusted programs to execute
allow perm=execute trust=1 : all
# Rule 20: Deny execution of untrusted scripts in /tmp
deny perm=execute trust=0 : dir=/tmp ftype=%languages
# Rule 30: Deny all other untrusted executions (The Catch-all)
deny perm=execute trust=0 : all
After modifying a rule file, you must run fagenrules to compile the policy and restart the service:
fagenrules --check
fagenrules --load
systemctl restart fapolicyd
On RHEL 8 and RHEL 9, the coexistence of SELinux and fapolicyd represents a significant advancement in endpoint security and system hardening.
|
|
Disabling either component sacrifices a critical security boundary. By enabling and correctly configuring both, system administrators and security professionals can build highly resilient, compliant, and robust RHEL environments capable of mitigating sophisticated modern threats. The effort invested in learning to manage these tools is a fundamental requirement for mastering the security of modern Linux operating systems.
Did you find this article helpful? Your feedback is invaluable to us! Feel free to share this post with those who may benefit, and let us know your thoughts in the comments section below.

Learn how to manage SELinux contexts on RHEL 9 and CentOS 9 for improved security. This guide covers SELinux contexts, CLI commands, troubleshooting, and best

Learn how to list and secure your SSH MACs, Ciphers, and KexAlgorithms for enhanced security. This guide provides step-by-step instructions for checking and configuring these

Learn how to enable, write, and configure SELinux policy modules for custom applications. Includes step-by-step instructions, file context management, CLI examples, and best practices for
