SELinux Denials: ausearch, sealert and audit2allow - 夜莺博客

SELinux Denials: ausearch, sealert and audit2allow

SELinux gets disabled on production servers because it "blocks things" - when in fact it blocks exactly one thing, and the audit log says which. Solving denials in the right order (label, boolean, then local policy) takes minutes and keeps the enforcement guarantees; jumping straight to audit2allow produces a permissive local module that quietly widens the policy. This is the workflow that gets a blocked service running without turning SELinux off.

Step 1: does a denial actually exist?

# ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent
# dmesg | grep -i -e type=1300 -e type=1400

SELinux decisions are cached in the Access Vector Cache, so AVC is the message type to search for. No output means the audit daemon may not be running - start it and reproduce the failure. If denials are still invisible, they may be suppressed by dontaudit rules; temporarily disable those rules, reproduce, then re-enable them:

# semodule -DB      # disable dontaudit rules, all denials now logged
# semodule -B       # re-enable after investigation

If you want a definitive answer on whether SELinux is involved at all, switch to permissive mode, reproduce, and check getenforce. Permissive logs without blocking.

Step 2: read the denial properly

type=AVC msg=audit(1553609555.619:127): avc:  denied  { write } for  pid=4097 comm="passwd"
path="/root/test" dev="dm-0" ino=17142697
scontext=unconfined_u:unconfined_r:passwd_t:s0-s0:c0.c1023
tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0

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

The pair to decode is scontext (the domain asking) and tcontext (the type of the object being accessed). Almost every denial is one of three stories: the object has the wrong label, a boolean is off, or the domain genuinely needs an extra rule.

Step 3: labels first, booleans second

Wrong-label problems are the most common and the cheapest to fix:

# ls -Z /var/www/html/index.html
# matchpathcon -V /data/uploads
# semanage fcontext -a -t httpd_sys_rw_content_t "/data/uploads(/.*)?"
# restorecon -Rv /data/uploads

If files were copied from another system or created before the policy existed, restorecon alone often ends the incident. Next, check whether a boolean already covers the requirement:

# getsebool -a | grep httpd
# setsebool -P httpd_can_network_connect on

-P persists across reboots; without it the fix disappears at the next restart, which is how "it broke again" tickets are born.

Step 4: a local module, when it is genuinely needed

# ausearch -m AVC --raw | audit2allow -M my-service
# semodule -i my-service.pp
# semodule -l | grep my-service

Review the generated .te file before installing it. Prefer the narrowest rule you can express, tag the module with a comment, and consider a priority install (semodule -X 300 -i my-service.pp) so your local module wins over a stock one. Use semanage permissive -a httpd_t to make a single domain permissive while you work, rather than switching the whole system to permissive.

Habits that keep SELinux on

  • Never disable SELinux to fix a symptom; the same change pushed to a hardened fleet will fail again with no audit trail.
  • Keep the policy module in configuration management so it is not lost when a host is rebuilt.
  • Treat audit2allow output as a proposal: check whether a label change or a boolean, not a rule, is the real answer.
  • Watch for repeated AVCs after a package upgrade - new binaries can land in a different type than the policy expects.

Related: Linux performance troubleshooting guide, nginx stream module TCP/UDP load balancing, and Linux server operations guide.

原文链接:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/10/html/using_selinux/troubleshooting-problems-related-to-selinux