SELinux Introduction: Your First Step to Reading Denial Logs

SELinux Introduction: Your First Step to Reading Denial Logs

What Is SELinux?

SELinux (Security-Enhanced Linux) is a mandatory access control (MAC) system built into the Linux kernel. It adds an extra layer of security on top of standard Unix permissions (DAC). On RHEL, CentOS, and Fedora systems it is enabled by default — blocking processes like Apache or PostgreSQL from accessing files they should not touch.

Standard chmod / chown (DAC) only asks: "Is this the file owner? Is the process in the right group?" SELinux additionally enforces: "Does this process type have policy permission to perform this operation on this resource type?"

Operating Modes

Mode Behavior
Enforcing Policy violations are denied and logged. Normal production mode.
Permissive Violations are logged but not denied. Use for troubleshooting.
Disabled SELinux completely off. Requires reboot to change.

Switching to Disabled requires editing /etc/selinux/config and rebooting. Returning to Enforcing afterward may require a full filesystem relabel.

How to Check the Current Mode

getenforce gives you the quickest answer. sestatus provides the full picture.

$ getenforce
Enforcing
$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux mount point:            /sys/fs/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

Check both Current mode (runtime) and Mode from config file (what survives a reboot).

Switching to Permissive Temporarily

setenforce changes the mode at runtime without a reboot. The change reverts on the next reboot.

$ sudo setenforce 0   # Switch to Permissive
$ sudo setenforce 1   # Switch back to Enforcing

Troubleshooting rule of thumb: Run setenforce 0, then reproduce the problem. If it disappears, SELinux is the culprit. Switch back to Enforcing immediately after confirming.

How to Read AVC Denial Logs

When SELinux blocks an action, it records an AVC (Access Vector Cache) log entry. The primary log file is /var/log/audit/audit.log.

type=AVC msg=audit(1748780400.123:1234): avc: denied { read } for pid=1122 comm="httpd" name="app.conf" dev="sda1" ino=56789 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0

Key fields explained:

Field Meaning In the example above
denied { read } Denied operation read access denied
comm="httpd" Process name Apache
name="app.conf" Target file name app.conf
scontext=...httpd_t... Source context (process) httpd_t type
tcontext=...user_home_t... Target context (file) user_home_t type
tclass=file Resource class regular file
permissive=0 Enforcing mode active actually denied

The most common root cause is a type mismatch between scontext and tcontext. When httpd_t tries to access a file labeled user_home_t, SELinux blocks it. The file should be labeled httpd_sys_content_t.

Check a File's Context

$ ls -Z /var/www/html/app.conf
unconfined_u:object_r:user_home_t:s0 /var/www/html/app.conf

This file carries the user_home_t label, which is why httpd_t cannot read it. The correct label for web content is httpd_sys_content_t.

Filtering Denial Logs with ausearch

Rather than grepping /var/log/audit/audit.log directly, use ausearch for efficient filtering.

# Recent AVC denials (last 10 minutes)
$ sudo ausearch -m AVC -ts recent

# All AVC denials since midnight today
$ sudo ausearch -m AVC --start today

# Filter by process name
$ sudo ausearch -m AVC -ts recent -c httpd

# Filter by file name
$ sudo ausearch -m AVC --start today | grep "app.conf"

-ts recent covers the last 10 minutes. --start today covers since midnight.

Using audit2why to Understand Denials

audit2why translates AVC log entries into plain English explanations. Pipe ausearch output into it.

$ sudo ausearch -m AVC -ts recent | audit2why
type=AVC msg=audit(1748780400.123:1234): avc: denied { read } for pid=1122 comm="httpd" ...

	Was caused by:
		Missing type enforcement (TE) allow rule.

		You can use audit2allow to generate a loadable module to allow this access.

"Missing type enforcement (TE) allow rule" means there is no policy rule granting this access.

audit2why explains the cause — it does not fix anything. Use audit2allow if you need to generate a policy module, but avoid doing so in production without fully understanding what you are allowing.

Common Fix Patterns

Restore File Context to Default

Files copied from another location often inherit the wrong context. restorecon applies the correct default context based on the file's path in the filesystem policy.

# Restore a single file
$ sudo restorecon -v /var/www/html/app.conf
Relabeled /var/www/html/app.conf from unconfined_u:object_r:user_home_t:s0 to system_u:object_r:httpd_sys_content_t:s0

# Restore a directory recursively
$ sudo restorecon -Rv /var/www/html/

Set Context Manually with chcon

Use chcon to change a file's context temporarily. Note that restorecon or a full relabel will overwrite this change.

$ sudo chcon -t httpd_sys_content_t /var/www/html/app.conf

Adjust Policy with Booleans

SELinux policies include Booleans — named on/off switches for specific behaviors. For example, to allow Apache to serve files from user home directories:

# List current Booleans related to httpd
$ getsebool -a | grep httpd

# Enable a Boolean persistently (-P keeps it after reboot)
$ sudo setsebool -P httpd_enable_homedirs on

Prefer fixing file contexts or adjusting Booleans over disabling SELinux entirely. Disabling removes a real security layer and is almost never the right answer.

Summary: Troubleshooting Checklist

  1. getenforce — confirm the mode is Enforcing
  2. setenforce 0, reproduce the issue — if it disappears, SELinux is the cause
  3. sudo ausearch -m AVC -ts recent | audit2why — identify the denial
  4. ls -Z — check the file's current context
  5. restorecon -v to restore the correct context, or setsebool to adjust policy
  6. setenforce 1 — switch back to Enforcing

Never disable SELinux as a workaround. Most issues are fixed by correcting file contexts with restorecon or enabling the right Boolean with setsebool.

Next Reading