SELinux Deep Dive
Quick Reference
# Current status
getenforce
sestatus
# Temporarily disable (survives until reboot)
sudo setenforce 0
# Check what's being blocked RIGHT NOW
sudo ausearch -m avc -ts recent
# Quick fix: Let SELinux learn from denials
sudo ausearch -m avc -ts today | audit2allow -M myfix
sudo semodule -i myfix.pp
Core Concepts
Modes
| Mode | Behavior | When to Use |
|---|---|---|
Enforcing |
Denies and logs violations |
Production |
Permissive |
Logs but allows violations |
Troubleshooting, policy development |
Disabled |
Completely off (requires reboot) |
Never in production |
# Check current mode
getenforce
# Temporarily set permissive (until reboot)
sudo setenforce 0
# Temporarily set enforcing
sudo setenforce 1
# Permanent change (requires reboot)
sudo vi /etc/selinux/config
# SELINUX=enforcing|permissive|disabled
Switching from Disabled to Enforcing requires filesystem relabel: touch /.autorelabel && reboot
|
Labels (Contexts)
Everything has a security context: user:role:type:level
# View file context
ls -Z /var/www/html/
# Output: system_u:object_r:httpd_sys_content_t:s0 index.html
# View process context
ps -eZ | grep httpd
# Output: system_u:system_r:httpd_t:s0 /usr/sbin/httpd
# View user context
id -Z
# Output: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Key components:
-
Type (
httpd_t,httpd_sys_content_t) - Most important for troubleshooting -
Role (
system_r,unconfined_r) - What the subject can do -
User (
system_u,unconfined_u) - SELinux user (not Linux user) -
Level (
s0) - MLS/MCS sensitivity (usuallys0)
File Contexts
Viewing Contexts
# Single file
ls -Z /path/to/file
# Recursive
ls -RZ /var/www/
# Default context for path (from policy)
matchpathcon /var/www/html/index.html
Changing Contexts
Temporary (chcon)
# Change type
sudo chcon -t httpd_sys_content_t /var/www/html/custom.html
# Change recursively
sudo chcon -R -t httpd_sys_content_t /var/www/custom/
# Copy context from reference file
sudo chcon --reference /var/www/html/index.html /var/www/html/new.html
chcon changes are lost on relabel. Use semanage fcontext for permanent changes.
|
Booleans
Pre-defined on/off switches for common scenarios.
Managing Booleans
# List all booleans
getsebool -a
# Search for specific booleans
getsebool -a | grep httpd
semanage boolean -l | grep httpd
# Get single boolean with description
semanage boolean -l | grep httpd_can_network_connect
# Set temporarily (until reboot)
sudo setsebool httpd_can_network_connect on
# Set permanently
sudo setsebool -P httpd_can_network_connect on
# View only modified booleans
semanage boolean -l -C
Common Booleans by Service
Apache/HTTPD
# Allow httpd to connect to network (proxy, database)
sudo setsebool -P httpd_can_network_connect on
# Allow httpd to connect to databases
sudo setsebool -P httpd_can_network_connect_db on
# Allow httpd scripts to write
sudo setsebool -P httpd_unified on
# Allow user home directories
sudo setsebool -P httpd_enable_homedirs on
# Allow CGI execution
sudo setsebool -P httpd_enable_cgi on
NFS
# Allow services to use NFS home dirs
sudo setsebool -P use_nfs_home_dirs on
# Allow httpd to use NFS
sudo setsebool -P httpd_use_nfs on
Port Contexts
Services can only bind to ports with correct SELinux label.
Managing Ports
# List all port labels
sudo semanage port -l
# Search for specific service
sudo semanage port -l | grep http
# http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
# Add custom port
sudo semanage port -a -t http_port_t -p tcp 8080
# Modify existing port (if already labeled)
sudo semanage port -m -t http_port_t -p tcp 8080
# Delete custom port
sudo semanage port -d -t http_port_t -p tcp 8080
# View custom rules only
sudo semanage port -l -C
Troubleshooting
The Holy Trinity
When SELinux blocks something:
# 1. Check recent denials
sudo ausearch -m avc -ts recent
# 2. Get human-readable explanation
sudo ausearch -m avc -ts recent | audit2why
# 3. Generate fix (if appropriate)
sudo ausearch -m avc -ts recent | audit2allow -M myfix
Reading AVC Denials
# Raw denial format
type=AVC msg=audit(1234567890.123:456): avc: denied { read } for pid=1234 comm="httpd" name="index.html" dev="sda1" ino=789 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
Key fields:
-
denied { read }- What operation was blocked -
comm="httpd"- Process that was blocked -
name="index.html"- Target object -
scontext=…httpd_t…- Source (process) context -
tcontext=…user_home_t…- Target (file) context -
tclass=file- Class of object
ausearch Options
# Recent denials
sudo ausearch -m avc -ts recent
# Today's denials
sudo ausearch -m avc -ts today
# Specific time range
sudo ausearch -m avc -ts 10:00:00 -te 11:00:00
# Specific process
sudo ausearch -m avc -c httpd
# Specific user
sudo ausearch -m avc -ua apache
audit2why
# Explain why denial occurred
sudo ausearch -m avc -ts recent | audit2why
# Output explains:
# - If boolean would fix it
# - If context is wrong
# - If custom policy needed
audit2allow
# Show what policy would allow this
sudo ausearch -m avc -ts recent | audit2allow
# Generate loadable policy module
sudo ausearch -m avc -ts recent | audit2allow -M myfix
# Load the module
sudo semodule -i myfix.pp
# Remove module later if needed
sudo semodule -r myfix
Don’t blindly run audit2allow. It may grant excessive permissions. Always review the generated policy.
|
Common Scenarios
Web Server with Custom Directory
# Problem: Apache can't read /srv/www/
# Solution:
# 1. Set permanent context
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
# 2. Apply context
sudo restorecon -Rv /srv/www/
# 3. Verify
ls -Z /srv/www/
Web Server Needs Network Access
# Problem: PHP can't connect to external API
# Solution:
sudo setsebool -P httpd_can_network_connect on
Custom SSH Port
# Problem: sshd won't start on port 2222
# Solution:
# 1. Add port label
sudo semanage port -a -t ssh_port_t -p tcp 2222
# 2. Restart SSH
sudo systemctl restart sshd
Container with Host Mounts
# Problem: Container can't read host directory
# Solution:
# 1. Label for container access
sudo semanage fcontext -a -t container_file_t "/data/container(/.*)?"
sudo restorecon -Rv /data/container/
# Or use :Z/:z with podman/docker
podman run -v /data/container:/data:Z image
Policy Modules
Listing Modules
# All modules
sudo semodule -l
# With priorities
sudo semodule -lfull
# Custom modules only
sudo semodule -l | grep -v "^[a-z]"
SELinux Users
Performance Considerations
# Check if SELinux is causing performance issues
# Look for high audit rates
sudo aureport -a --summary
# If audit log growing rapidly, may need policy fixes
ls -lh /var/log/audit/audit.log
Reference
Essential Commands
# Status
getenforce # Current mode
sestatus # Full status
# Mode
setenforce 0|1 # Permissive|Enforcing
# Contexts
ls -Z # File contexts
ps -eZ # Process contexts
id -Z # Current user context
# Booleans
getsebool -a # List all
setsebool -P bool on|off # Set permanently
# File contexts
semanage fcontext -l # List rules
semanage fcontext -a -t type "path(/.*)?" # Add rule
restorecon -Rv /path # Apply rules
# Ports
semanage port -l # List ports
semanage port -a -t type -p tcp port # Add port
# Troubleshooting
ausearch -m avc -ts recent # Recent denials
audit2why # Explain denial
audit2allow -M fix # Generate policy