Chapter 16: SELinux

Troubleshooting SELinux denials

Eventually something breaks and SELinux is the reason. The skill is not memorising every type and boolean, but following the same short routine each time: prove that SELinux is involved, read the denial, decide which of the three adjustments it calls for, change as little as possible, and test again with SELinux enforcing.

The routine

From denial to fix: Step through diagnosing an SELinux problem.

1 · Is it SELinux? A quick, safe experiment:

[root@servera ~]# curl -s -o /dev/null -w "%{http_code}\n" http://localhost/moved.html
403
[root@servera ~]# setenforce 0; getenforce
Permissive
[root@servera ~]# curl -s -o /dev/null -w "%{http_code}\n" http://localhost/moved.html
200
[root@servera ~]# setenforce 1; getenforce
Enforcing

It works in permissive mode, so SELinux was blocking. (If it fails the same way, SELinux is not the problem, and you save yourself an hour. Always switch back.)

2 · Read the denial. Denials are logged by the audit daemon (auditd) in /var/log/audit/audit.log as AVC records ("Access Vector Cache"):

[root@servera ~]# grep AVC /var/log/audit/audit.log | tail -1 | cut -c1-260
type=AVC msg=audit(1791050803.921:146): avc:  denied  { open } for  pid=2279 comm="httpd" path="/srv/web/moved.html" dev="sda2" ino=32383 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=file permissive=0

Reading an AVC record: Select a part of the log line.

The same information in plain words comes from sealert, part of the setroubleshoot-server package:

[root@servera ~]# sealert -a /var/log/audit/audit.log | head -6
found 2 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------

SELinux is preventing /usr/sbin/httpd from open access on the file /srv/web/moved.html.

*****  Plugin catchall_labels (83.8 confidence) suggests   *******************

Each suggestion lists commands to try, with a confidence. Read them, do not paste them blindly. ausearch -m AVC -ts recent is the classic search tool too (on this lab image add -if /var/log/audit/audit.log; without the auditd service running there is no audit log, and the denials end up only in the journal or the kernel messages).

3 · Decide which kind. Look at tcontext and tclass:

4 · Smallest fix. One change, then test.

5 · Test in enforcing mode, and check the log for new denials. The job is done when the original action works and the machine is still enforcing.

Custom policy modules: the last resort

If a legitimate program really needs something the policy does not allow, audit2allow can turn the denials into a policy module:

# ausearch -c 'httpd' --raw | audit2allow -M my-httpd
# semodule -X 300 -i my-httpd.pp

This adds permissions the policy authors did not intend. Use it only after you have ruled out the label, boolean and port explanations, and read the generated rules (my-httpd.te) before installing. semodule -l lists installed modules, and semodule -r NAME removes one.

Try it

Check your understanding