SELinux custom policy troubleshooting notes
These were working notes for diagnosing SELinux denials affecting services such as Dovecot and systemd-machined. What is kept here is the policy-development workflow; generated rules from the old environment are not reproduced because they were specific to its labels and services.
Recommended troubleshooting flow
Reproduce the denied operation, then inspect recent AVC records:
$ ausearch -m AVC,USER_AVC -ts recentUse audit2why to understand the denial:
$ ausearch -m AVC -ts recent | audit2whyaudit2allow can suggest policy, but its output is not automatically correct:
$ ausearch -m AVC -ts recent | audit2allow -RReview the suggested interfaces and permissions before adding them.
Check labeling first
A denial involving generic types such as default_t is often a sign of mislabeling. Inspect:
$ ls -lZ /path/to/object $ matchpathcon /path/to/object
Define persistent corrections with semanage fcontext, then apply with restorecon.
Avoid the automatic-fix anti-pattern
Do not pipe an audit log into audit2allow -M and immediately install the generated module. It can grant permissions caused by bad labels, unrelated historical events or an application bug.
References
- Red Hat - Writing a custom SELinux policy: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/using_selinux/writing-a-custom-selinux-policy_using-selinux
- SELinux Project: https://selinuxproject.org/
Current practice (checked 2026-10)
- Still valid: the flow above (check labels first, read
audit2why, treataudit2allowoutput as a suggestion) is what the current Red Hat documentation recommends; it states thataudit2allowshould not be the first option when a denial appears. - Message types: search for
AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR, not only AVC records. - sealert: where the setroubleshoot packages are installed,
sealert -l "*"prints each denial with an analysis and a proposed fix, andjournalctl -t setroubleshootshows the same events when auditd is not running. - Hidden denials: if the operation fails without any AVC, a
dontauditrule is hiding it. Disable those rules temporarily withsemodule -DB, reproduce, then restore them withsemodule -B.
Sources: