Kingsfordweg 151, 1043GR Amsterdam, The Netherlands ● 24/7 support — support@novogara.com
Knowledge base

SELinux and AppArmor

The internet's advice when something does not work is to turn SELinux off. That advice removes a working security layer to avoid reading one log line.

What they do

Normal Unix permissions say who owns a file. Mandatory access control says what a program may do, regardless of who runs it. Your web server can read web content and cannot read /etc/shadow, even as root, even if the permissions would otherwise allow it.

That is what contains a compromise. Without it, a remote code execution in your web application is limited only by file permissions; with it, the attacker is stuck inside a profile that does not permit much.

  • SELinux — RHEL, Rocky, AlmaLinux, Fedora. Labels on everything, policy per label.
  • AppArmor — Ubuntu, Debian, SUSE. Profiles per executable, by path. Simpler to read.

Reading an SELinux denial

Something fails with a permission error that makes no sense. Check:

ausearch -m AVC -ts recent

or more readably:

sealert -a /var/log/audit/audit.log

The output names the process, the file and the permission that was refused, and usually suggests the fix. Nine times out of ten it is a label: a file in an unusual place with the wrong context.

ls -lZ /srv/www — see the labels

semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
restorecon -Rv /srv/www — set them permanently

For a non-standard port:

semanage port -a -t http_port_t -p tcp 8080

And many common cases are just a boolean away: setsebool -P httpd_can_network_connect on.

AppArmor

aa-status — which profiles are loaded and in what mode

journalctl -k | grep apparmor — denials

Put a single profile into complain mode while you work on it, rather than disabling the lot:

aa-complain /etc/apparmor.d/usr.sbin.nginx

Then aa-logprof walks you through the denials and writes the rules.

Permissive, not disabled

If you genuinely must relax it while debugging, use permissive mode:

setenforce 0

That logs what would have been denied without blocking it, so you collect exactly the information you need to write the policy. Fully disabling SELinux means relabelling the whole filesystem to turn it back on, which is why people never do.

Where it pays off

A contained web server compromise is an incident; an uncontained one is a rebuild. Combined with an unprivileged service user and the systemd sandboxing in running your application as a service, you have three independent layers, none of which is expensive. See also a compromised server for what the alternative looks like.


Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base