Linux·7 min read·

SELinux for Beginners: Understanding Enforcing, Permissive, and Targeted

SELinux denies by default where file permissions allow everything. Understand enforcing, permissive, targeted policy, and how to read a denial calmly.

NB

Netbay Engineering

Netbay Engineering

On this page

Most admins meet SELinux as an error: a service that should work returns permission denied, someone suggests setenforce 0, and the problem vanishes — along with a large share of the server's protection. That reflex is the security equivalent of chmod 777. SELinux stops being mysterious once you learn its small vocabulary: modes describe behavior, policy describes rules, labels describe everything on disk, and four commands resolve the overwhelming majority of real denials.

Every access passes two gates PROCESS label: httpd_t GATE 1: DAC mode bits rwx GATE 2: MAC SELinux policy FILE httpd_sys_content_t root cannot skip gate 2 DENY: EACCES DENY: AVC logged DAC is per-file and optional; MAC is system-wide and non-negotiable

Two Locks on Every File

Traditional Unix permissions are discretionary access control (DAC): a file's owner decides who reads, writes, or executes it, and root bypasses the whole scheme. Any process runs with the full power of the user that launched it, so a compromised web server can read anything its user can. SELinux adds mandatory access control (MAC) on top of DAC: the kernel checks every access against a system-wide policy that no user, including root, can override at runtime.

Everything carries a label — processes like httpd_t, files like httpd_sys_content_t, ports like http_port_t. The policy states which label may perform which action on which other label. A compromised web server confined as httpd_t reads files labeled for web content and little else, even while running as root.

Enforcing, Permissive, Disabled

bash
getenforce
sestatus
sudo setenforce 1
sudo setenforce 0
  • Enforcing: the kernel blocks policy violations and logs each one. This is the production target.
  • Permissive: violations are logged but permitted. It is a diagnostic mode, not a fix.
  • Disabled: the kernel skips SELinux entirely; re-enabling later requires a full filesystem relabel at boot.

setenforce changes the running mode only; the boot-time default lives in /etc/selinux/config, where SELINUX=enforcing should stay. Use permissive briefly, on purpose, to collect the denials a new workload generates — then return to enforcing with those specific gaps closed.

What Targeted Policy Means

RHEL-family distributions ship the targeted policy. Network-facing daemons — sshd, httpd, named, postfix, chronyd — run confined under strict rules, while ordinary user processes and most local tools run unconfined, limited only by DAC. That is a deliberate trade: writing correct policy for every process on the system is unmanageable, so the policy concentrates on the processes an attacker can reach from the network. Targeted is the right default for servers and what virtually every EL deployment runs; there is no practical reason to change it.

Reading Your First Denial

When a confined process crosses policy, the kernel records an AVC (Access Vector Cache) denial and the application sees EACCES. The service log will say permission denied with no hint why, which is exactly why you go to the audit trail instead of guessing.

bash
sudo ausearch -m avc -ts recent
sudo journalctl -t setroubleshoot -n 20

The ausearch output names the source context, the target object and its label, and the specific permission that was denied — that triple is the diagnosis. With the setroubleshoot packages installed, the journal also carries plain-language summaries with suggested fixes, which are usually right.

Fix Labels and Booleans, Not the Policy

Two tools resolve almost every legitimate denial without touching the policy itself.

bash
sudo dnf install -y policycoreutils-python-utils
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
sudo restorecon -Rv /srv/www
sudo setsebool -P httpd_can_network_connect on

Serving web content from a non-standard path? The files carry the wrong label: teach the policy the path with semanage fcontext, then apply labels with restorecon. Need a confined service to use a well-understood capability, like making outbound network connections? Flip its boolean with setsebool -P, which persists across reboots. What you should almost never do is disable enforcement to make an error disappear — and if a custom rule is truly required, generate a minimal module from real denials with audit2allow rather than broad-stroke exceptions.

Takeaway: SELinux is two gates instead of one, a vocabulary of labels, and a small toolkit for the rare legitimate exception. You can meet it on a throwaway box: deploy a Rocky Linux 9 VPS on Netbay in under 60 seconds, serve httpd from a custom path, and practice reading the denial before you fix it — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance