Getting Started with SELinux and AppArmor

Standard Linux permissions answer “which user can access this file,” but they say nothing about what a compromised process should be allowed to do. That’s the gap Mandatory Access Control systems like SELinux and AppArmor fill — and it’s why “just disable SELinux” is such bad advice.

SELinux: Label Everything

SELinux (used by RHEL, Fedora, CentOS) assigns a security context/label to every file and process, and policy rules define exactly which labeled processes can interact with which labeled resources — regardless of standard Unix permissions. A web server process can be confined to only reading files labeled httpd_sys_content_t, even if it’s technically running as root.

# Check current mode: Enforcing, Permissive, or Disabled
getenforce

# View the security context of a file
ls -Z /var/www/html/index.html

# Fix a mislabeled file (common after moving content into place)
sudo restorecon -Rv /var/www/html

# See what SELinux blocked recently
sudo ausearch -m avc -ts recent

AppArmor: Path-Based Confinement

AppArmor (default on Ubuntu, Debian, SUSE) takes a simpler, path-based approach — profiles list exactly which files and capabilities a specific binary is allowed to touch, without SELinux’s global labeling system:

sudo aa-status                    # list loaded profiles and their mode
sudo aa-complain /usr/sbin/nginx  # switch a profile to logging-only mode
sudo aa-enforce /usr/sbin/nginx   # switch back to enforcing

Why “Just Disable It” Is the Wrong Answer

Disabling SELinux or AppArmor because a service “isn’t working” removes a real security layer that specifically limits blast radius when something does get compromised. The correct fix is almost always to update the policy or fix file labels, not to turn the whole system off — audit2allow on SELinux systems will even generate the correct policy exception for you from the denial logs.