SELinux Troubleshooting

SELinux Troubleshooting #

Here’s a little guide on how to find if SELinux is blocking something and how to add an exception to the policy.

SELinux Modes #

SELinux operates in three modes:

# Check SELinux status and mode
sestatus

Understanding the Three Modes #

  1. Enforcing: SELinux policy is enforced
  2. Permissive: SELinux policy violations are logged but not blocked
  3. Disabled: SELinux is completely disabled

Check if SELinux is the problem #

# Temporarily set to permissive mode and test
setenforce 0
# Test your application
# If it works now, SELinux was blocking it
setenforce 1

Troubleshooting Workflow #

When an application fails and you are certain that SELinux is blocking it, e.g. you turned SELinux off or into permissive mode and the application worked, you can do the following:

Step 1: Examine Recent Audit Logs #

# Check recent SELinux denials
tail -f /var/log/audit/audit.log | grep AVC

Step 2: Analyze the Denial with audit2why #

# Analyze recent denials
tail /var/log/audit/audit.log | audit2why

# Analyze specific denial by timestamp or pattern
grep "1675516978.657:437" /var/log/audit/audit.log | audit2why

# Analyze all denials for a specific service
grep "nginx" /var/log/audit/audit.log | audit2why

Step 3: Generate and Apply Policy #

# Generate a policy module for nginx
grep "nginx" /var/log/audit/audit.log | audit2allow -M nginx_custom

# Review the generated policy
cat nginx_custom.te

# Install the policy module
semodule -i nginx_custom.pp

# Verify module installation
semodule -l | grep nginx_custom

Policy Module Management #

# List installed modules with versions
semodule -l -v

# Remove a module
semodule -r my_custom_policy

# Upgrade a module
semodule -u my_custom_policy.pp

# Disable a module (don't remove)
semodule -d my_custom_policy

# Enable a disabled module
semodule -e my_custom_policy

Port Context Management #

If you want to run an application like nginx on a non-default port (e.g., port 9090 instead of the standard port 80), SELinux will block the application from binding to that port. This is because SELinux has predefined port contexts that specify which services can use which ports.

To resolve this, you need to add the custom port to the appropriate SELinux context:

# List port contexts
semanage port -l | grep http

# Add a new port for HTTP
semanage port -a -t http_port_t -p tcp 9090

# Modify existing port context
semanage port -m -t http_port_t -p tcp 9090

# Delete port context
semanage port -d -t http_port_t -p tcp 9090

# List only custom port contexts
semanage port -l -C

File Labels and Contexts #

SELinux assigns security contexts (labels) to every file and directory. Understanding and managing these labels is crucial for troubleshooting file access issues.

Viewing File Labels #

# View labels of files and directories
ls -Z /var/www/html/
ls -laZ /etc/httpd/conf/

# View label of a specific file
ls -Z /var/www/html/index.html

# View labels recursively
find /var/www/html/ -exec ls -ldZ {} \;

Changing File Labels #

# Change file context temporarily (until next restorecon)
chcon -t httpd_exec_t /opt/myapp/bin/myapp

# Copy context from another file
chcon --reference=/var/www/html/index.html /opt/myapp/index.html

# Change context recursively
chcon -R -t httpd_exec_t /opt/myapp/

# Restore original context from policy
restorecon /opt/myapp/config.conf

# Restore contexts recursively with verbose output
restorecon -Rv /var/www/html/

Managing Default File Contexts #

# View current file context rules
semanage fcontext -l | grep httpd

# Add new file context rule
semanage fcontext -a -t httpd_config_t "/opt/myapp/conf(/.*)?"

# Modify existing context rule
semanage fcontext -m -t httpd_exec_t "/opt/myapp/bin/myapp"

# Delete context rule
semanage fcontext -d "/opt/myapp/bin/myapp"

# Apply context rules to files (after adding semanage rules)
restorecon -R /opt/myapp/

Conclusion #

I’ve solved every SELinux problem I’ve ever had with the tips I’ve shared above. Happy hunting!