SELinux Troubleshooting
Quick Reference
# Check SELinux status
getenforce
sestatus
# Temporarily disable (for testing only)
setenforce 0 # Permissive
setenforce 1 # Enforcing
# Check AVC denials
ausearch -m AVC -ts recent
journalctl -t setroubleshoot
# Fix file contexts
restorecon -Rv /path/to/files
# Check boolean
getsebool httpd_can_network_connect
# Set boolean
setsebool -P httpd_can_network_connect on
# Generate policy from denials
audit2allow -a -M mypolicy
semodule -i mypolicy.pp
Understanding SELinux
What is SELinux?
Security-Enhanced Linux (SELinux) is a Mandatory Access Control (MAC) system:
-
Label-based - Every file, process, port has a security context
-
Policy-driven - Rules define what access is allowed
-
Default deny - Anything not explicitly allowed is denied
-
Fine-grained - Controls specific operations, not just file permissions
SELinux Modes
| Mode | Description | Use Case |
|---|---|---|
Enforcing |
Denies access and logs violations |
Production systems |
Permissive |
Allows access but logs violations |
Troubleshooting, policy development |
Disabled |
SELinux completely off |
Not recommended (breaks relabeling) |
Security Contexts
# Format: user:role:type:level
# Example file context
ls -Z /var/www/html/
# -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
# Example process context
ps -eZ | grep httpd
# system_u:system_r:httpd_t:s0 httpd
# Components:
# user - SELinux user (system_u, unconfined_u)
# role - Role for RBAC (object_r for files)
# type - Most important! Determines access (httpd_t, httpd_sys_content_t)
# level - MLS/MCS sensitivity level (s0)
Checking SELinux Status
Current Mode
# Quick check
getenforce
# Returns: Enforcing, Permissive, or Disabled
# Detailed status
sestatus
# SELinux status: enabled
# SELinuxfs mount: /sys/fs/selinux
# SELinux root directory: /etc/selinux
# Loaded policy name: targeted
# Current mode: enforcing
# Mode from config file: enforcing
Finding SELinux Denials
Using ausearch
# Recent denials
ausearch -m AVC -ts recent
# Today's denials
ausearch -m AVC -ts today
# Denials for specific command
ausearch -m AVC -c httpd
# Denials for specific time range
ausearch -m AVC -ts 10:00 -te 11:00
# Denials for specific type
ausearch -m AVC | grep httpd_t
Using journalctl
# setroubleshoot messages
journalctl -t setroubleshoot
# All SELinux-related
journalctl | grep -i selinux
# Follow real-time
journalctl -f | grep -i avc
Using audit.log
# Direct log access
cat /var/log/audit/audit.log | grep AVC
# Using grep for specific type
grep "httpd_t" /var/log/audit/audit.log
# Parse AVC messages
ausearch -m AVC -ts today | audit2why
Understanding AVC Messages
# Example AVC denial:
# type=AVC msg=audit(1234567890.123:456): avc: denied { read } for
# pid=1234 comm="httpd" name="config.txt" dev="sda1" ino=12345
# scontext=system_u:system_r:httpd_t:s0
# tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file
# Breakdown:
# denied { read } - Operation that was denied
# comm="httpd" - Process name
# name="config.txt" - Target file/resource
# scontext=...httpd_t - Source (process) context
# tcontext=...user_home_t - Target (file) context
# tclass=file - Object class
Fixing Common Issues
Wrong File Context
Most common issue: files have wrong SELinux type.
# Check expected context
semanage fcontext -l | grep /var/www
# Check actual context
ls -Z /var/www/html/
# Restore default context
restorecon -Rv /var/www/html/
# Restore single file
restorecon -v /var/www/html/index.html
Files in Non-Standard Location
# Apache serving from /data/www instead of /var/www
# Add context rule
semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
# Apply the context
restorecon -Rv /data/www
# Verify
ls -Z /data/www/
# List custom context rules
semanage fcontext -l -C
Process Needs Network Access
# httpd can't connect to network (for proxying)
# Check related booleans
getsebool -a | grep httpd | grep network
# Enable network connection
setsebool -P httpd_can_network_connect on
# For database connections
setsebool -P httpd_can_network_connect_db on
SELinux Booleans
What are Booleans?
Booleans are on/off switches for policy features:
# List all booleans
getsebool -a
# List booleans with descriptions
semanage boolean -l
# Search for specific service
getsebool -a | grep httpd
getsebool -a | grep samba
# Check specific boolean
getsebool httpd_can_network_connect
Common Booleans
# Web server (httpd)
httpd_can_network_connect # Connect to any port
httpd_can_network_connect_db # Connect to databases
httpd_can_network_relay # Act as relay/proxy
httpd_enable_homedirs # Serve ~/public_html
httpd_use_nfs # Access NFS mounts
httpd_use_cifs # Access CIFS/SMB mounts
httpd_execmem # Execute memory (PHP, etc.)
# Samba
samba_enable_home_dirs # Share home directories
samba_export_all_ro # Export all files read-only
samba_export_all_rw # Export all files read-write
# NFS
nfs_export_all_ro # Export all read-only
nfs_export_all_rw # Export all read-write
use_nfs_home_dirs # Use NFS for home dirs
# SSH
ssh_sysadm_login # Allow sysadm_r to login
# FTP
ftpd_anon_write # Anonymous FTP write
ftpd_full_access # FTP access to all files
Managing File Contexts
View File Contexts
# Single file
ls -Z /var/www/html/index.html
# Directory listing
ls -laZ /var/www/html/
# Check default context rule
semanage fcontext -l | grep "/var/www"
# Check context for path
matchpathcon /var/www/html/
matchpathcon /etc/httpd/
Add Custom Context
# Add context rule for new directory
semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
# Apply context
restorecon -Rv /srv/www
# Add context rule for specific file
semanage fcontext -a -t httpd_sys_rw_content_t "/srv/www/uploads(/.*)?"
restorecon -Rv /srv/www/uploads
Modify Context Rule
# Modify existing rule
semanage fcontext -m -t httpd_sys_rw_content_t "/srv/www(/.*)?"
restorecon -Rv /srv/www
Managing Port Contexts
View Port Labels
# All port labels
semanage port -l
# Specific service
semanage port -l | grep http
semanage port -l | grep ssh
# Search by port number
semanage port -l | grep "8080"
Add Port Label
# Add TCP port
semanage port -a -t http_port_t -p tcp 8080
# Add UDP port
semanage port -a -t dns_port_t -p udp 5353
# Add port range
semanage port -a -t http_port_t -p tcp 8080-8090
Creating Custom Policies
Using audit2allow
# Generate policy from recent denials
audit2allow -a
# Generate loadable module
audit2allow -a -M mymodule
# Creates mymodule.pp and mymodule.te
# Review what would be allowed
audit2allow -a -w # With explanations
# Install the module
semodule -i mymodule.pp
Troubleshooting Workflow
Step-by-Step Process
# 1. Identify the problem
# Application fails, check logs
# 2. Check if SELinux is blocking
ausearch -m AVC -ts recent
# 3. Understand the denial
ausearch -m AVC -ts recent | audit2why
# 4. Try common fixes first:
# - Check file contexts
# - Check booleans
# - Check port labels
# 5. If custom policy needed
audit2allow -a -M myfix
semodule -i myfix.pp
# 6. Verify fix works
# Test application
ausearch -m AVC -ts recent # Should be empty
Using setroubleshoot
# Install setroubleshoot
# RHEL/CentOS
sudo dnf install setroubleshoot-server
# View suggestions
sealert -a /var/log/audit/audit.log
# Real-time notification
# setroubleshoot daemon provides desktop notifications
# and detailed solutions in /var/log/messages
Permissive Mode Testing
# Switch to permissive to test
setenforce 0
# Run application, collect denials
ausearch -m AVC -ts recent
# Generate policy
audit2allow -a -M testpolicy
# Review policy before installing
cat testpolicy.te
# Switch back to enforcing
setenforce 1
# Install policy if appropriate
semodule -i testpolicy.pp
Common Scenarios
Web Server Custom Content
# Scenario: Apache serving from /data/websites
# 1. Add context rule
semanage fcontext -a -t httpd_sys_content_t "/data/websites(/.*)?"
# 2. For writable directories (uploads)
semanage fcontext -a -t httpd_sys_rw_content_t "/data/websites/uploads(/.*)?"
# 3. Apply contexts
restorecon -Rv /data/websites
# 4. Enable network if needed
setsebool -P httpd_can_network_connect on
Container/Podman Issues
# Scenario: Podman container can't access host files
# 1. Check volume mount has correct label
podman run -v /data:/data:Z myimage # Private label
podman run -v /data:/data:z myimage # Shared label
# 2. Or use container-specific booleans
setsebool -P container_manage_cgroup on
# 3. Check container SELinux status
ps -eZ | grep container
Quick Command Reference
# Status
getenforce # Current mode
sestatus # Detailed status
setenforce 0|1 # Set permissive|enforcing
# Finding denials
ausearch -m AVC -ts recent # Recent denials
ausearch -m AVC -ts today # Today's denials
journalctl -t setroubleshoot # Setroubleshoot messages
# File contexts
ls -Z /path # View context
semanage fcontext -l | grep PATH # List rules
semanage fcontext -a -t TYPE "PATH" # Add rule
restorecon -Rv /path # Apply context
chcon -t TYPE /path # Temporary change
# Booleans
getsebool -a | grep KEYWORD # List booleans
setsebool -P BOOLEAN on|off # Set persistent
# Ports
semanage port -l | grep TYPE # List ports
semanage port -a -t TYPE -p tcp PORT # Add port
# Policy modules
audit2allow -a -M module # Create module
semodule -i module.pp # Install module
semodule -l # List modules
semodule -r module # Remove module