BlogLinux & scripting

SELinux on OpenShift: stop chmod 777-ing your way out

Read AVC denials, write a targeted policy module, and keep SCCs strict instead of granting privileged.

Aug 19, 2025·11 min readAdvanced

Something breaks, a log says 'Permission denied' on a file whose mode is clearly 0644, and within thirty seconds someone types setenforce 0. The problem 'goes away' — because you just turned off the seatbelt. SELinux denials are readable and the real fix is usually three commands, so it's worth learning to read them instead of reaching for the switch.

Every denial is logged as an AVC (Access Vector Cache) record. That record tells you exactly what was blocked and in which context:

bash — read the deniallive
ausearch -m AVC -ts recent
time->Tue Jun 10 10:42:01 2025
type=AVC avc: denied { read } for pid=2114 comm="nginx"
name="index.html" scontext=...:httpd_t tcontext=...:user_home_t
 
ausearch -m AVC -ts recent | audit2why
Was caused by: the file has the wrong SELinux type.
the fix is a file context, not setenforce 0

Read it left to right: the subject nginx (httpd_t) was denied read on a file labelled user_home_t. SELinux isn't confused — a web server has no business reading a file typed as someone's home directory. The label is wrong, so fix the label.

How SELinux decides
1
Subject
process context
2
Object
file context
3
Policy
is this pair allowed?
4
AVC
allow or deny + log

Fix the label, not the enforcement

Set the correct context so it persists across a relabel — chcon alone is temporary and gets wiped by the next restorecon. Use semanage fcontext to record the rule, then restorecon to apply it. When the app genuinely needs a capability, a boolean is the sanctioned switch.

fix.sh
# persistent: teach the policy the correct type for this path
semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
restorecon -Rv /srv/www
# some needs are just a boolean away — no custom policy required
setsebool -P httpd_can_network_connect on
setenforce 0 is not a fix
It disables protection host-wide until the next reboot, and hides every future denial while it is off. If you must debug, use permissive mode for a single domain (semanage permissive -a httpd_t) so the rest of the system stays enforcing.

On OpenShift and Kubernetes

Containers get SELinux too. On OpenShift, Security Context Constraints (SCCs) assign each pod an MCS category pair, so two containers on the same node literally cannot read each other's volume files even as root. When a mounted volume throws permission errors, the culprit is almost always the label — set seLinuxOptions or let the platform relabel the mount rather than loosening the SCC.

Where this goes next

Once reading denials is routine, generate a proper module for the legitimate ones: ausearch ... | audit2allow -M myapp builds a loadable policy you can review and ship, instead of a pile of booleans nobody remembers enabling.

Go deeper in a courseLinux hardeningSSH, nftables, SELinux, auditd and CIS — harden a default install.View course

Related posts