Free — no signup required

Audit Logs: Reading AVC Denials

2 min read

"Permission Denied" — But Why?

When you see a "Permission Denied" error and the standard Unix permissions look correct, the LSM is almost certainly the cause. The kernel records every LSM denial through the Linux Audit subsystem, which writes structured log entries to /var/log/audit/audit.log on systems with auditd running, or to the kernel ring buffer (accessible via journalctl -k) on systems without it.

SELinux denials are called AVC denials — AVC stands for Access Vector Cache, the kernel data structure that caches policy decisions for performance. A raw AVC denial looks intimidating but follows a consistent structure:

type=AVC msg=audit(1700000000.123:456): avc:  denied  { read } for  pid=1234 comm="httpd" name="index.html" dev="sda1" ino=98765 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:user_home_t:s0 tclass=file permissive=0

Breaking this down field by field:

Field Value Meaning
avc: denied — This was blocked (not just logged)
{ read } read The specific permission that was denied
comm="httpd" httpd The process name that attempted the action
pid=1234 1234 The process ID
name="index.html" index.html The target object name
scontext= httpd_t:s0 Source context — the process's label
tcontext= user_home_t:s0 Target context — the file's label
tclass=file file The object class (file, dir, tcp_socket, etc.)
permissive=0 0 0 = enforcing (blocked), 1 = permissive (logged only)

Practical diagnostic tools: ausearch queries the audit log for AVC events — recent ones, or filtered down to a specific process — without you having to grep raw log lines by hand. The sealert tool (from the setroubleshoot-server package on RHEL systems) is particularly valuable — it translates raw AVC denials into plain English explanations and suggests specific restorecon or semanage commands to fix them.

For AppArmor, denials appear in /var/log/syslog or journalctl with the prefix apparmor=:

kernel: [12345.678] audit: type=1400 audit(1700000000.123:456): apparmor="DENIED" operation="open" profile="/usr/sbin/nginx" name="/etc/shadow" pid=5678 comm="nginx" requested_mask="r" denied_mask="r" fsuid=33 ouid=0

The fields are analogous: profile is the confining profile, name is the target path, requested_mask is what was attempted, denied_mask is what was blocked.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free