SELinux

SELinux (Security-Enhanced Linux) is the default MAC system on RHEL, Fedora, and CentOS. It labels every file, process, and network port with a security context, then enforces rules about which labels can interact with which. Even if an attacker exploits a web server running as root, SELinux confines it to what httpd is allowed to do.

Security Contexts and Labels

What is a SELinux label? Every object (file, process, socket) gets a security context: a 4-part label. Format: user:role:type:level. The type is the most important part for policy — rules say "processes of type X can perform operation Y on objects of type Z." Labels are stored as extended attributes on files (xattr) and assigned to processes at exec time.
# See process labels: ps -Z # LABEL PID COMMAND # system_u:system_r:httpd_t:s0 1234 httpd # system_u:system_r:sshd_t:s0 5678 sshd # unconfined_u:unconfined_r:unconfined_t:s0 9012 bash # See file labels: ls -Z /var/www/html/ # system_u:object_r:httpd_sys_content_t:s0 index.html # system_u:object_r:httpd_sys_content_t:s0 style.css ls -Z /etc/passwd # system_u:object_r:passwd_file_t:s0 /etc/passwd # Get context of a specific file: stat -c "%C" /etc/httpd/conf/httpd.conf # system_u:object_r:httpd_config_t:s0

Reading AVC Denial Messages

# AVC = Access Vector Cache — where SELinux logs denials # View denials in audit log: ausearch -m AVC -ts recent # Example denial: # type=AVC msg=audit(1234567890.123:456): avc: denied { read } # for pid=1234 comm="httpd" name="secret.txt" # dev="sda1" ino=5678 # scontext=system_u:system_r:httpd_t:s0 # tcontext=system_u:object_r:admin_home_t:s0 # tclass=file permissive=0 # Decoded: # process: httpd (httpd_t) # tried to: read # the file: secret.txt # which has type: admin_home_t # result: DENIED (httpd_t cannot read admin_home_t files) # Human-readable: sealert -a /var/log/audit/audit.log

Fixing SELinux Denials

# Option 1: Fix the file label (usually correct approach) # Wrong label on a web file: ls -Z /var/www/html/myfile.txt # unconfined_u:object_r:user_home_t:s0 myfile.txt ← wrong! # Fix the label: restorecon -v /var/www/html/myfile.txt # Relabeled: user_home_t -> httpd_sys_content_t # Recursively fix a directory: restorecon -Rv /var/www/html/ # Change file type permanently: chcon -t httpd_sys_content_t /var/www/html/myfile.txt # Option 2: Enable a boolean (predefined policy switch) getsebool -a | grep httpd # httpd_can_network_connect --> off # httpd_can_sendmail --> off # httpd_enable_cgi --> on # Allow httpd to connect to network (e.g., proxy to backend): setsebool -P httpd_can_network_connect 1 # -P = persistent across reboots # Option 3: Write a custom policy module audit2allow -M mypolicy < /var/log/audit/audit.log semodule -i mypolicy.pp

SELinux Modes

# Three modes: getenforce # Enforcing = policy enforced, denials logged # Permissive = not enforced but denials logged (testing mode) # Disabled = completely off (requires reboot to change) # Switch to permissive (for debugging — useful to see what WOULD be denied): setenforce 0 # temporary getenforce # Permissive setenforce 1 # back to enforcing # Permanent mode (/etc/selinux/config): # SELINUX=enforcing # SELINUXTYPE=targeted (targeted = only specific processes confined) # Per-process permissive mode (leave rest enforcing): semanage permissive -a httpd_t # make just httpd_t permissive semanage permissive -l # list permissive domains