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.

🔵 Why It Matters Even if a process is compromised and running as root, SELinux policy can still block it from doing things outside its expected role — for example, preventing a compromised web server process from reading /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

ModeBehavior
EnforcingPolicy is actively enforced; denied actions are blocked and logged
PermissiveDenials are logged but NOT blocked — useful for testing and troubleshooting
DisabledSELinux 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
⚠️ Warning — Disabled Is Not the Same as Permissive Switching fully to 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
ComponentMeaning
unconfined_uSELinux user
object_rRole
httpd_sys_content_tType — the component that matters most day to day
s0Sensitivity level (relevant mainly in MLS configurations)
✅ Tip — Type Enforcement Is What You'll Use Most Nearly all everyday SELinux troubleshooting comes down to the type field. A web server process running as 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
⚠️ Warning — chcon Doesn't Survive a Relabel 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
✅ Tip — Always Reach for -P Forgetting -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
🔵 Note If a service refuses to start on a custom port with a permission-denied-style error, and standard file/firewall checks look fine, SELinux port labeling is a common culprit worth checking next.

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
⚠️ Warning — audit2allow Isn't a Reflexive Fix Blindly running 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 ausearch or the audit log

Review Questions

  1. What is the difference between DAC (standard permissions) and MAC (SELinux)?
  2. Why is permissive mode generally safer to use for troubleshooting than disabled?
  3. In an SELinux context like system_u:object_r:httpd_sys_content_t:s0, which field matters most for everyday type enforcement decisions?
  4. What is the difference between chcon and semanage fcontext in terms of permanence?
  5. What flag must you remember when using setsebool if you want the change to survive a reboot?
  6. A service refuses to bind to a non-default port even though the firewall allows it. What SELinux-specific step should you check?
  7. Why should you be cautious about blindly applying whatever audit2allow generates?