Server

SELinux Without setenforce 0

By Prabath Thalangama· October 24, 2026· 3 min read
#linux#selinux#security#troubleshooting

Introduction

setenforce 0 "fixes" the problem the way unplugging the smoke detector fixes a fire. Almost every real SELinux denial has a one-line proper fix: a boolean, a file context, or a port label. This is the workflow.

Concepts

SELinux labels every process and file with a context (user:role:type:level). The type is what matters day to day: httpd_t (the web server process), httpd_sys_content_t (files it's allowed to serve), httpd_log_t, etc. The policy is a giant allow-list of "type X may do action Y to type Z". A denial means no rule allowed it.

Modes: Enforcing (block + log), Permissive (allow + log — for debugging), Disabled (off entirely, requires a relabel to re-enable).

getenforce
sestatus

The workflow

1. Find the denial

# Recent AVC denials, human-readable
sudo ausearch -m avc -ts recent
sudo ausearch -m avc -ts today | audit2why      # explains WHY each was denied

# Live
sudo tail -f /var/log/audit/audit.log | grep AVC
# On systems with setroubleshoot, journalctl -e shows a plain-English hint + fix

An AVC line names the source type (scontext), target type (tcontext), the class (file, tcp_socket), and the permission (read, name_connect).

2. Is it a boolean?

Many common cases are toggles:

getsebool -a | grep httpd
# httpd_can_network_connect --> off        <- this is why your app can't reach a backend
sudo setsebool -P httpd_can_network_connect on

-P persists it. Other frequent ones: httpd_can_network_connect_db, nis_enabled, haproxy_connect_any, nfs_export_all_rw, domain_can_mmap_files.

3. Is it a file-context problem?

Serving content from a non-default path (/srv/www instead of /var/www)? The files have the wrong type.

ls -Z /srv/www/index.html                       # shows the current type
# Tell the policy this path should be web content, then apply it
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
sudo restorecon -Rv /srv/www

semanage fcontext records the rule (survives a full relabel); restorecon applies it now. Never use chcon for permanent fixes — a relabel wipes it.

4. Is it a non-standard port?

sudo semanage port -l | grep http_port_t
sudo semanage port -a -t http_port_t -p tcp 8443     # let httpd bind 8443

5. Genuinely need a new rule (last resort)

sudo ausearch -m avc -ts recent | audit2allow -M mypolicy
# review mypolicy.te — make sure it's not allowing something absurd
sudo semodule -i mypolicy.pp

Only after confirming it isn't a boolean or context issue. A hand-rolled module that allows httpd_t to write shadow_t is worse than setenforce 0.

Verification and troubleshooting

# Reproduce in permissive mode to collect ALL denials at once (not just the first)
sudo semanage permissive -a httpd_t
# ...run the failing operation...
sudo ausearch -m avc -ts recent
sudo semanage permissive -d httpd_t
  • Fixed one denial, hit another — the operation had several. Use the per-domain permissive trick above to see them all in one pass.
  • restorecon didn't change the label — no semanage fcontext rule matches that path. Add the rule first (step 3), then restorecon.
  • Denial with no AVC in the log — a dontaudit rule is suppressing it. sudo semodule -DB disables dontaudit temporarily, reproduce, then sudo semodule -B to restore.
  • App works in permissive but audit2allow module doesn't fix enforcing — the module is incomplete (denials cascade). Re-collect in permissive mode after installing the module and iterate, or find the real boolean.
  • Everything is denied after re-enabling SELinux from Disabled — the filesystem was never relabeled. sudo fixfiles -F onboot && reboot, or touch /.autorelabel && reboot.
  • setsebool didn't persist across reboot — you forgot -P.
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.