SELinux vs Fapolicyd on RHEL 8/9: What’s the Difference and Why You Need Both

SELinux vs fapolicyd RHEL 8/9

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.

Table of Contents

🔈Introduction

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.


✅ Understanding the Pillars of RHEL Security

To grasp the synergy between SELinux and fapolicyd, we must first examine the two primary models of access control in Linux:

  • Discretionary Access Control (DAC): The familiar User/Group/Other (UGO) permissions (rwx) and the root user concept. DAC is discretionary because the owner of a file can change its permissions. This is the first, but weakest, security layer.
  • Mandatory Access Control (MAC): A non-discretionary model where security policies are centrally managed and enforced system-wide by the kernel, regardless of the file owner. Both SELinux and fapolicyd operate within this MAC framework, but they enforce policies based on different criteria.

✅ SELinux: Mandatory Access Control by Context

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.

  • Context-Based Enforcement: SELinux uses a policy to define rules that govern interactions between subjects (processes, identified by their domain type, e.g., httpd_t) and objects (files, identified by their file type, e.g., httpd_sys_content_t).
  • Principle of Least Privilege: By default, all access is denied unless an explicit rule in the policy permits it. This is why a compromised service running in a confined SELinux domain (e.g., a web server) cannot simply read a user’s home directory (user_home_t) or a database file (mysqld_db_t), even if the traditional DAC permissions would allow it.
  • Process Isolation: It prevents lateral movement and privilege escalation by separating processes into different security domains. A vulnerability in one application cannot easily be leveraged to attack another.

🔄 Key Components of SELinux

ComponentDescriptionExample
ContextA label assigned to all subjects and objects. Format: user:role:type:level.system_u:object_r:httpd_sys_content_t:s0
TypeThe 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)
DomainThe type for a process, confining its actions.httpd_t
PolicyA 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
				
			

✅ fapolicyd: Application Whitelisting and Integrity Control

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.

  • Application Whitelisting: Unlike SELinux, which focuses on what a process can do once it’s running, fapolicyd focuses on if the program is allowed to start in the first place. This is a powerful preventative control against execution of unknown, unauthorized, or malicious binaries, scripts, and libraries.
  • Integrity Checking: fapolicyd is tightly integrated with the system’s RPM database. Files installed via dnf or yum are automatically added to its Trust Database, which includes their SHA-256 hash and size. If a trusted file is modified after installation, its hash will change, and fapolicyd will deny its execution, thus preventing tampered binaries from running.
  • Trust-Based Decisions: Decisions are based on the file’s integrity (hash check), origin (installed via RPM/DNF), and user-defined policies (e.g., path or MIME type).

🔄 Key Components of fapolicyd

ComponentDescriptionLocation
Trust DatabaseA 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 RulesUser-defined rules to allow or deny execution based on path, MIME type, user, or trust status.Files in /etc/fapolicyd/rules.d/
EnforcementBlocks 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
				
			

🤝 Why You Need Both: A Layered Defense

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.

FeatureSELinuxfapolicyd
Primary GoalMandatory Access Control (MAC) & Process Isolation.Application Whitelisting & Integrity Enforcement.
What it ChecksContext (Type) of the subject (process) and the object (file).Trust (Integrity/Hash, Origin) of the executable file.
Decision PointDuring process operation (e.g., file read/write, network connection).Before a file is executed (open/execute event).
Protection AgainstCompromised running processes (lateral movement, privilege escalation).Execution of unknown, unauthorized, or tampered binaries/scripts.
Best AnalogyThe 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

  • Preventing Initial Compromise: An attacker might introduce a malicious binary via a vulnerable service.
    • Fapolicyd’s Role: Since the binary was not installed via DNF, it is considered untrusted and will be denied execution immediately.
  • Containing a Compromised Process:Imagine the attacker somehow bypasses fapolicyd or exploits a trusted application.
    • SELinux’s Role: Even though the malicious code is now running, it is confined to the specific SELinux domain of the compromised service. It cannot access critical system files (etc_t) or user data (user_home_t) because the SELinux policy denies that type of cross-domain access.
  • Integrity Violation: A package’s installed binary is maliciously modified on disk (e.g., a rootkit).
    • Fapolicyd’s Role: The next time the tampered binary tries to execute, fapolicyd performs a hash check against the Trust Database. The hashes won’t match, and execution is denied, preventing the rootkit from launching.

▶️ Implementing and Managing Dual Enforcement

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
				
			

🏁 Conclusion

On RHEL 8 and RHEL 9, the coexistence of SELinux and fapolicyd represents a significant advancement in endpoint security and system hardening.

  • SELinux provides run-time confinement and process isolation, preventing a breach from becoming a full system compromise.
  • Fapolicyd provides pre-execution control and software integrity assurance, preventing unauthorized or tampered code from ever launching.

 

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.


📕 Related Posts

Leave a Reply

Logged in as admingeek. Edit your profile. Log out? Required fields are marked *