In the landscape of Linux security, discretionary access control (DAC) systems—relying on user ownership and file permissions (e.g., rwx)—have long been the default. However, DAC has limitations: it trusts users to manage their own permissions, leaving systems vulnerable to misconfigurations or compromised accounts. Enter SELinux (Security-Enhanced Linux), a mandatory access control (MAC) framework developed by the NSA. SELinux enforces granular, policy-driven access rules at the kernel level, independent of user identity, to mitigate threats like privilege escalation, data leaks, and unauthorized process interactions. This blog demystifies SELinux, covering its core concepts, practical usage, troubleshooting workflows, and best practices to help you leverage it for robust system security.
Table of Contents
- Understanding SELinux Basics
- 1.1 What is SELinux?
- 1.2 DAC vs. MAC: Why SELinux Matters
- Core SELinux Concepts
- 2.1 SELinux Modes: Enforcing, Permissive, Disabled
- 2.2 SELinux Contexts: The “Labels” of Access Control
- 2.3 SELinux Policies: Rule Sets for Authorization
- Practical SELinux Usage
- 3.1 Checking SELinux Status
- 3.2 Changing SELinux Modes
- 3.3 Managing SELinux Contexts
- Common Practices: Troubleshooting & Policy Management
- 4.1 Analyzing SELinux Denials
- 4.2 Using
sealertfor Automated Diagnosis - 4.3 Modifying Policies with Booleans
- Best Practices for SELinux
- Conclusion
- References
1. Understanding SELinux Basics
1.1 What is SELinux?
SELinux is a Linux kernel module that provides MAC, a security model where access to resources (files, processes, network ports) is controlled by policies enforced by the kernel, not just user permissions. It was designed to limit damage from attacks by confining processes to the minimum privileges required (principle of least privilege).
1.2 DAC vs. MAC: Why SELinux Matters
- DAC (Discretionary Access Control): The default Linux security model, where access is determined by user ownership and mode bits (e.g.,
chmod 755). Users withrootprivileges can bypass DAC entirely, making systems vulnerable to privilege escalation. - MAC (Mandatory Access Control): SELinux adds a second layer, enforcing rules based on predefined policies. Even
rootis subject to SELinux policies, preventing unrestricted access.
2. Core SELinux Concepts
2.1 SELinux Modes: Enforcing, Permissive, Disabled
SELinux operates in three modes, configurable system-wide:
| Mode | Behavior |
|---|---|
| Enforcing | Actively enforces policies; denies unauthorized access and logs denials. |
| Permissive | Logs policy violations but does not enforce them (ideal for testing/troubleshooting). |
| Disabled | SELinux is inactive; no policy enforcement or logging. Not recommended for production. |
2.2 SELinux Contexts: The “Labels” of Access Control
Every process, file, directory, and network port in SELinux is assigned a context—a string of metadata that defines its role in the security policy. Contexts follow the format:
user:role:type:level
- User: Identifies the SELinux user (e.g.,
unconfined_ufor regular users,system_ufor system processes). - Role: Defines the access role (e.g.,
object_rfor files,system_rfor processes). - Type: The most critical component; determines allowed interactions (e.g.,
httpd_tfor Apache processes,httpd_sys_content_tfor web files). - Level: Used in Multi-Level Security (MLS) policies to enforce data classification (e.g.,
s0for unclassified).
Example: A web file might have the context unconfined_u:object_r:httpd_sys_content_t:s0.
2.3 SELinux Policies: Rule Sets for Authorization
Policies are pre-defined rule sets that dictate how subjects (processes) interact with objects (files, ports). Common policy types:
- Targeted: Default on most distributions (RHEL, CentOS, Fedora). Confines only critical system processes (e.g.,
httpd,sshd) while leaving others unconfined. - Strict: Confines all processes, including user applications (rarely used today).
- MLS/MCS: Enforces Multi-Level Security (classification labels) or Multi-Category Security (fine-grained category tags) for high-security environments.
3. Practical SELinux Usage
3.1 Checking SELinux Status
Use sestatus to view the current SELinux state, policy type, and mode:
sestatus
Sample Output:
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Memory protection checking: actual (secure)
Max kernel policy version: 33
To check only the enforcement mode, use getenforce:
getenforce # Output: Enforcing, Permissive, or Disabled
3.2 Changing SELinux Modes
Temporary Mode Changes (Runtime)
Use setenforce to switch modes temporarily (resets after reboot):
setenforce 0 # Switch to Permissive mode (log denials, don't block)
setenforce 1 # Switch to Enforcing mode (block and log denials)
Permanent Mode Changes (Persistent)
To persist mode changes across reboots, edit /etc/selinux/config:
sudo vi /etc/selinux/config
Set SELINUX= to one of:
enforcing: Enforce policies.permissive: Log denials only.disabled: Disable SELinux (requires reboot).
Note: Disabling SELinux requires a reboot and is not recommended for production.
3.3 Managing SELinux Contexts
SELinux contexts determine access. Use these tools to view and modify contexts:
View Contexts
-
For files/directories:
ls -Zls -Z /var/www/html # List SELinux contexts of web filesOutput:
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html -
For processes:
ps -Zps -Z | grep httpd # View context of Apache processesOutput:
system_u:system_r:httpd_t:s0 1234 ? 00:00:00 httpd
Modify Contexts Temporarily with chcon
chcon changes a file’s context temporarily (resets after restorecon or system relabel). Use it for testing:
# Change context of /var/www/custom/file.html to httpd_sys_content_t (web-accessible)
sudo chcon -t httpd_sys_content_t /var/www/custom/file.html
Modify Contexts Permanently with semanage and restorecon
For permanent context changes, use semanage fcontext to define a rule, then restorecon to apply it:
# Add a permanent rule: all files under /var/www/custom/ inherit httpd_sys_content_t
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/custom(/.*)?"
# Apply the rule to existing files
sudo restorecon -Rv /var/www/custom/
-a: Add a rule.-t: Specify the target type./var/www/custom(/.*)?: Regex to match the directory and its subdirectories.restorecon -Rv: Recursively (-R) restore contexts and verbose (-v) output.
4. Common Practices: Troubleshooting & Policy Management
4.1 Analyzing SELinux Denials
When SELinux blocks access, it logs “AVC (Access Vector Cache) denials” to:
/var/log/audit/audit.log(viaauditdservice, default on RHEL/CentOS)./var/log/messages(fallback ifauditdis disabled).
Use ausearch to filter denials:
# Search for AVC denials in the last hour
sudo ausearch -m AVC -ts recent
Sample Audit Log Entry:
type=AVC msg=audit(1620000000.123:456): avc: denied { read } for pid=1234 comm="httpd" name="file.html" dev="sda1" ino=789 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0
scontext: Subject (process) context (httpd_t= Apache).tcontext: Target (file) context (default_t= not web-accessible).{ read }: Action denied.
4.2 Using sealert for Automated Diagnosis
sealert (part of setroubleshoot-server) parses audit logs and suggests fixes for denials:
# Generate a report from audit.log
sudo sealert -a /var/log/audit/audit.log
# Or analyze a specific denial by UUID (from ausearch output)
sudo sealert -l 12345678-1234-1234-1234-1234567890ab
Sample sealert Output:
SELinux is preventing httpd from reading access to file file.html.
***** Plugin catchall (100. confidence) suggests **************************
If you want to allow httpd to read access to the file.html file
Then you need to change the label on file.html
Do
# semanage fcontext -a -t httpd_sys_content_t '/var/www/custom/file.html'
# restorecon -v '/var/www/custom/file.html'
4.3 Modifying Policies with Booleans
SELinux booleans are toggleable settings that modify policy behavior without rewriting rules. Use getsebool and setsebool to manage them:
# List all booleans related to Apache
sudo getsebool -a | grep httpd
# Example output: httpd_can_network_connect --> off
Enable a boolean temporarily:
# Allow Apache to connect to the network (temporarily)
sudo setsebool httpd_can_network_connect on
Enable a boolean permanently (survives reboot) with -P:
# Allow Apache to connect to the network permanently
sudo setsebool -P httpd_can_network_connect on
5. Best Practices for SELinux
- Keep SELinux in Enforcing Mode: Disabling SELinux removes a critical security layer. Use Permissive mode only for troubleshooting.
- Use Permanent Context Changes: Prefer
semanage fcontextoverchconto avoid context resets. - Leverage Booleans First: Use booleans to adjust policy behavior before writing custom rules.
- Log Everything: Ensure
auditdis running to capture denials in/var/log/audit/audit.log. - Relabel Files After Mode Changes: If switching from Disabled to Enforcing, relabel the filesystem with
sudo fixfiles -F onboot(reboot required). - Document Changes: Track
semanage,setsebool, and context modifications for compliance and troubleshooting. - Update Policies: Regularly update
selinux-policypackages to patch vulnerabilities.
6. Conclusion
SELinux is a powerful tool for hardening Linux systems, but its reputation for complexity often leads users to disable it. By mastering contexts, modes, and troubleshooting workflows (e.g., sealert, ausearch), you can enforce granular access controls without sacrificing usability. Remember: SELinux is not a barrier but a guardrail—embrace it to protect against zero-day exploits, misconfigurations, and insider threats.
7. References
- Red Hat SELinux Documentation
- CentOS SELinux Wiki
- SELinux Project Wiki
man sestatus,man semanage,man sealert(Linux man pages)
Let me know if you need further clarification on any section—happy securing! 🛡️