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 (usually s0)

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.

Permanent (semanage fcontext)

# Add permanent context rule
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"

# Apply the rule (relabel)
sudo restorecon -Rv /srv/web/

# View custom rules
sudo semanage fcontext -l -C

# Delete custom rule
sudo semanage fcontext -d "/srv/web(/.*)?"

Restoring Default Contexts

# Restore single file
sudo restorecon -v /path/to/file

# Restore directory recursively
sudo restorecon -Rv /var/www/

# Full system relabel (reboot required)
sudo touch /.autorelabel
sudo reboot

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

Samba

# Share home directories
sudo setsebool -P samba_enable_home_dirs on

# Export any filesystem
sudo setsebool -P samba_export_all_rw on

SSH

# Allow SSH agent forwarding
sudo setsebool -P ssh_sysadm_login 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

Common Port Types

Type Default Ports Service

http_port_t

80, 443, 8080

Apache, Nginx

ssh_port_t

22

SSH

postgresql_port_t

5432

PostgreSQL

mysqld_port_t

3306

MySQL/MariaDB

dns_port_t

53

DNS

smtp_port_t

25, 465, 587

Mail

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.

sealert (GUI-friendly)

# If setroubleshoot is installed
sealert -a /var/log/audit/audit.log

# Real-time monitoring
sealert -b

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

NFS Home Directories

# Problem: Users can't access NFS-mounted homes
# Solution:
sudo setsebool -P use_nfs_home_dirs on

Policy Modules

Listing Modules

# All modules
sudo semodule -l

# With priorities
sudo semodule -lfull

# Custom modules only
sudo semodule -l | grep -v "^[a-z]"

Managing Modules

# Disable module
sudo semodule -d module_name

# Enable module
sudo semodule -e module_name

# Remove module
sudo semodule -r module_name

# Install module
sudo semodule -i mymodule.pp

Creating Custom Policy

# 1. Generate from denials
sudo ausearch -m avc -ts today | audit2allow -M mycustom

# 2. Review the policy (important!)
cat mycustom.te

# 3. If acceptable, install
sudo semodule -i mycustom.pp

SELinux Users

Mapping Linux Users

# View mappings
sudo semanage login -l

# Map Linux user to SELinux user
sudo semanage login -a -s user_u regularuser

# View SELinux users
sudo semanage user -l

User Types

SELinux User Linux Users Capabilities

unconfined_u

Admins, root

Full access (SELinux allows all)

staff_u

Trusted users

Can sudo to sysadm_r

user_u

Regular users

Limited, no sudo

guest_u

Guests

Very limited, no networking

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

Important Files

File Purpose

/etc/selinux/config

Main configuration (mode, policy type)

/var/log/audit/audit.log

Audit log (denials logged here)

/etc/selinux/targeted/contexts/files/

File context definitions

/sys/fs/selinux/

SELinux pseudo-filesystem

See Also