Chapter Objective: Describe how SELinux enforces mandatory access control, manage its modes, file contexts, and booleans, and troubleshoot access denials.
Key commands: getenforce, setenforce, ls -Z, restorecon, semanage
What Is SELinux?
Standard Linux permissions (Chapter 11 of RH124) are discretionary access control (DAC) — the owner of a resource decides who can access it. SELinux (Security-Enhanced Linux) adds a second, independent layer: mandatory access control (MAC), enforced by the kernel according to a system-wide policy that even root can't simply override by ownership alone.
/etc/shadow, regardless of standard file permissions.
Every process and every file carries an SELinux context (also called a label). Access is only allowed if policy explicitly permits that combination of process context and target context — everything not explicitly allowed is denied by default.
SELinux Modes
| Mode | Behavior |
|---|---|
| Enforcing | Policy is actively enforced; denied actions are blocked and logged |
| Permissive | Denials are logged but NOT blocked — useful for testing and troubleshooting |
| Disabled | SELinux is completely off; no labeling, no enforcement, no logging |
# Show the current mode
getenforce
# Temporarily switch to permissive (lost on reboot)
sudo setenforce 0
# Switch back to enforcing
sudo setenforce 1
# Show detailed current status
sestatus
# Permanent setting: /etc/selinux/config
SELINUX=enforcing
disabled (rather than permissive) stops SELinux from labeling new files at all. Re-enabling it later typically requires a full filesystem relabel, which is disruptive. Prefer permissive for troubleshooting — it still logs what SELinux would have blocked.
File Contexts
# Show SELinux context alongside normal ls -l output
ls -Z /var/www/html/index.html
# Example output
unconfined_u:object_r:httpd_sys_content_t:s0 index.html
| Component | Meaning |
|---|---|
unconfined_u | SELinux user |
object_r | Role |
httpd_sys_content_t | Type — the component that matters most day to day |
s0 | Sensitivity level (relevant mainly in MLS configurations) |
httpd_t can only access files labeled with types policy allows it to touch, like httpd_sys_content_t — regardless of standard file permissions.
Restoring and Changing Contexts
# Restore a file's context to what policy expects (the usual fix)
sudo restorecon /var/www/html/index.html
# Restore recursively
sudo restorecon -Rv /var/www/html/
# Manually set a specific context (temporary — lost on restorecon/relabel)
sudo chcon -t httpd_sys_content_t /var/www/html/index.html
# Set a PERMANENT custom context rule, then apply it
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"
sudo restorecon -Rv /srv/web
chcon changes a file's current context but doesn't update the underlying policy — a future restorecon or full relabel will revert it. For a permanent, correct fix, use semanage fcontext to change the expected policy, then run restorecon to apply it.
SELinux Booleans
Booleans are on/off switches that toggle specific pieces of SELinux policy at runtime, without writing custom policy — the sanctioned way to enable a known, supported exception to default behavior.
# List all booleans and their current state
getsebool -a
# Show just one boolean
getsebool httpd_can_network_connect
# Enable a boolean temporarily (lost on reboot)
sudo setsebool httpd_can_network_connect on
# Enable it AND make the change persistent across reboots
sudo setsebool -P httpd_can_network_connect on
-P is a common mistake — the change works immediately but silently disappears on the next reboot, making a fix look "broken again" later for no apparent reason.
Port Labeling
SELinux also controls which network ports a service is allowed to bind to, independent of standard permissions or the firewall.
# List port type associations
semanage port -l | grep http
# Allow httpd to bind to a NON-standard port (e.g. 8081)
sudo semanage port -a -t http_port_t -p tcp 8081
Troubleshooting Denials
# Search the audit log specifically for SELinux denials
sudo ausearch -m avc -ts recent
# If installed, get a human-readable explanation and suggested fix
sudo sealert -a /var/log/audit/audit.log
# Generate a custom policy module to allow a specific denied action
# (use cautiously — understand what you're permitting)
sudo audit2allow -a -M mypolicy
sudo semodule -i mypolicy.pp
audit2allow on every denial and installing the resulting module can quietly widen your security posture more than intended. Understand what a denial actually represents before generating a policy to permit it — sometimes the correct fix is a context or boolean, not a brand-new allow rule.
Key Terms for Chapter 6
- DAC / MAC
- Discretionary Access Control (standard permissions) versus Mandatory Access Control (SELinux policy)
- SELinux context (label)
- The user, role, type, and sensitivity tag attached to every process and file
- type enforcement
- The primary SELinux mechanism, restricting access based on process and object type
- enforcing / permissive / disabled
- The three SELinux modes, controlling whether denials are blocked, only logged, or absent entirely
- restorecon
- Restores a file's SELinux context to what policy expects
- SELinux boolean
- A runtime on/off switch toggling a specific piece of policy behavior
- AVC denial
- A logged record of SELinux blocking an action, found via
ausearchor the audit log
Review Questions
- What is the difference between DAC (standard permissions) and MAC (SELinux)?
- Why is
permissivemode generally safer to use for troubleshooting thandisabled? - In an SELinux context like
system_u:object_r:httpd_sys_content_t:s0, which field matters most for everyday type enforcement decisions? - What is the difference between
chconandsemanage fcontextin terms of permanence? - What flag must you remember when using
setseboolif you want the change to survive a reboot? - A service refuses to bind to a non-default port even though the firewall allows it. What SELinux-specific step should you check?
- Why should you be cautious about blindly applying whatever
audit2allowgenerates?