SELinux: Basic Configuration and Modes

Introduction

Security-Enhanced Linux (SELinux) is a mandatory access control (MAC) security mechanism built into the Linux kernel that provides an additional layer of system security beyond traditional discretionary access control (DAC). Originally developed by the National Security Agency (NSA), SELinux has become a critical component of enterprise Linux distributions, particularly Red Hat Enterprise Linux, CentOS, and Fedora.

SELinux enforces security policies that define how processes, users, and files interact with each other and system resources. By implementing the principle of least privilege at the kernel level, SELinux significantly reduces the potential damage from security vulnerabilities, misconfigurations, and compromised applications.

This comprehensive guide explores SELinux fundamentals, configuration options, operational modes, and best practices. Whether you're a system administrator new to SELinux or looking to deepen your understanding of this powerful security framework, this guide provides the knowledge and practical techniques needed to effectively implement and manage SELinux in production environments.

Understanding SELinux and Security Context

What Is SELinux?

Security-Enhanced Linux (SELinux) is a Linux kernel security module that provides a mechanism for supporting mandatory access control (MAC) security policies. Unlike traditional Unix permissions that rely on user discretion, SELinux enforces system-wide security policies that cannot be overridden by users or applications.

How SELinux Works

SELinux operates using several key concepts:

1. Security Contexts (Labels)

Every file, process, port, and system object has a security context with four components:

user:role:type:level
  • User: SELinux user (different from Linux user)
  • Role: Defines which SELinux users can access the object
  • Type: Primary mechanism for access control (type enforcement)
  • Level: Multi-Level Security (MLS) and Multi-Category Security (MCS)

Example: system_u:object_r:httpd_sys_content_t:s0

2. Type Enforcement

The most important SELinux feature, type enforcement uses types (domains for processes, types for files) to determine access:

  • Processes run in specific domains (e.g., httpd_t for Apache)
  • Files are labeled with specific types (e.g., httpd_sys_content_t for web content)
  • Policy rules define which domains can access which types

3. Policy Rules

SELinux policies contain rules that explicitly allow or deny access:

allow httpd_t httpd_sys_content_t:file { read getattr open };

This rule allows the Apache process (httpd_t domain) to read files labeled as httpd_sys_content_t.

SELinux Operational Modes

SELinux operates in three distinct modes:

Enforcing Mode

  • SELinux policies are enforced
  • Access violations are denied and logged
  • Provides active protection
  • Recommended for production systems

Permissive Mode

  • SELinux policies are not enforced
  • Access violations are logged but allowed
  • Useful for troubleshooting and policy development
  • No actual security protection

Disabled Mode

  • SELinux is completely disabled
  • No policies loaded or enforced
  • No logging of violations
  • Not recommended for production systems

Why SELinux Matters

SELinux provides critical security benefits:

  • Containment: Limits damage from compromised applications
  • Mandatory access control: Cannot be circumvented by users or applications
  • Zero-day protection: Reduces exploit effectiveness even before patches available
  • Compliance: Required for many security frameworks and government certifications
  • Fine-grained control: Precise control over system resource access
  • Defense in depth: Additional security layer beyond traditional permissions

Common SELinux Misconceptions

Myth: "SELinux is too complex and should be disabled" Reality: Modern tools simplify SELinux management, and disabling removes critical security protections

Myth: "SELinux breaks applications" Reality: Properly labeled applications work seamlessly; issues indicate configuration problems

Myth: "SELinux is only for government/military" Reality: Any organization handling sensitive data benefits from SELinux

Prerequisites

Before configuring SELinux, ensure you have:

System Requirements

  • Operating System: RHEL, CentOS, Fedora, or other SELinux-capable distribution
  • Kernel: Linux kernel 2.6 or later with SELinux support
  • Root Access: Administrative privileges required
  • Disk Space: Adequate space for policy files and logs

Required Knowledge

  • Basic Linux system administration
  • Understanding of file permissions and ownership
  • Command-line proficiency
  • Basic understanding of system services
  • Familiarity with log analysis

Software Requirements

Most SELinux tools come pre-installed on RHEL/CentOS systems:

  • selinux-policy: SELinux reference policy
  • policycoreutils: SELinux core utilities
  • policycoreutils-python-utils: Python utilities for SELinux
  • setroubleshoot-server: SELinux troubleshooting tools
  • setools-console: SELinux policy analysis tools

Verification and Installation

Check if SELinux is installed:

rpm -qa | grep selinux

Install missing tools (CentOS/RHEL 8+):

sudo dnf install policycoreutils policycoreutils-python-utils setroubleshoot-server setools-console

For CentOS/RHEL 7:

sudo yum install policycoreutils policycoreutils-python setroubleshoot-server setools-console

Verify SELinux kernel support:

cat /sys/fs/selinux/enforce

If the file exists, SELinux is supported.

Step-by-Step SELinux Configuration

Step 1: Check Current SELinux Status

View detailed SELinux status:

sestatus

Expected output:

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
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      33

Quick status check:

getenforce

Returns: Enforcing, Permissive, or Disabled

View current security context:

id -Z

Example output: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

Step 2: Understand SELinux Configuration Files

Main configuration file:

cat /etc/selinux/config

Content:

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing

# SELINUXTYPE= can take one of these values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

Policy types explained:

  • targeted: Default policy, protects network-facing services
  • minimum: Minimal protection, only critical services
  • mls: Multi-Level Security for classified environments

Step 3: Change SELinux Modes

Temporarily change to permissive mode (until reboot):

sudo setenforce 0

Temporarily change to enforcing mode:

sudo setenforce 1

Verify the change:

getenforce

Permanently change SELinux mode:

Edit /etc/selinux/config:

sudo nano /etc/selinux/config

Change the SELINUX line:

SELINUX=enforcing  # or permissive or disabled

Reboot for permanent changes to take effect:

sudo reboot

WARNING: Changing from disabled to enabled requires relabeling the entire filesystem on next boot.

Step 4: Enable SELinux from Disabled State

If SELinux is currently disabled:

  1. Edit configuration:

    sudo nano /etc/selinux/config
    

    Change to:

    SELINUX=permissive
    SELINUXTYPE=targeted
    
  2. Reboot the system:

    sudo reboot
    
  3. After reboot, system will relabel all files (may take time)

  4. Verify permissive mode is working:

    sestatus
    
  5. Check logs for issues:

    sudo grep "SELinux" /var/log/messages
    
  6. If no critical issues, switch to enforcing:

    sudo nano /etc/selinux/config
    

    Change to:

    SELINUX=enforcing
    
  7. Reboot again:

    sudo reboot
    

Step 5: Manage SELinux Contexts

View file security contexts:

ls -Z /var/www/html/

Example output:

-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html

View process contexts:

ps auxZ | grep httpd

View port contexts:

sudo semanage port -l | grep http

Change file context temporarily:

sudo chcon -t httpd_sys_content_t /var/www/html/newfile.html

Change file context permanently:

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html/newfile.html"
sudo restorecon -v /var/www/html/newfile.html

Restore default contexts:

sudo restorecon -Rv /var/www/html/

Options:

  • -R: Recursive
  • -v: Verbose
  • -F: Force reset

Step 6: Manage SELinux Booleans

SELinux booleans allow runtime modification of policy behavior without rewriting policies.

List all booleans:

getsebool -a

Search for specific boolean:

getsebool -a | grep httpd

Check specific boolean:

getsebool httpd_can_network_connect

Enable boolean temporarily (until reboot):

sudo setsebool httpd_can_network_connect on

Enable boolean permanently:

sudo setsebool -P httpd_can_network_connect on

Common useful booleans:

# Allow httpd to connect to network
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 to send mail
sudo setsebool -P httpd_can_sendmail on

# Allow FTP full access
sudo setsebool -P ftpd_full_access on

# Allow Samba to share home directories
sudo setsebool -P samba_enable_home_dirs on

Step 7: Manage SELinux Port Labeling

View port labels:

sudo semanage port -l

Add custom port for service (e.g., Apache on port 8080):

sudo semanage port -a -t http_port_t -p tcp 8080

Modify existing port label:

sudo semanage port -m -t http_port_t -p tcp 8080

Delete port label:

sudo semanage port -d -t http_port_t -p tcp 8080

View custom modifications:

sudo semanage port -l -C

Step 8: Create Custom SELinux Policies

For recurring denials, create custom policies:

  1. Identify the denial in logs:

    sudo ausearch -m avc -ts recent
    
  2. Generate policy module:

    sudo grep denied /var/log/audit/audit.log | audit2allow -M mypolicy
    
  3. Review the generated policy:

    cat mypolicy.te
    
  4. Install the policy module:

    sudo semodule -i mypolicy.pp
    
  5. Verify installation:

    sudo semodule -l | grep mypolicy
    

Remove custom module:

sudo semodule -r mypolicy

Advanced SELinux Hardening Tips

1. Use Confined Users

Create confined Linux user:

sudo useradd -Z user_u username

Map Linux user to SELinux user:

sudo semanage login -a -s user_u username

View user mappings:

sudo semanage login -l

Confine administrative users:

sudo semanage login -a -s staff_u adminuser

2. Implement Multi-Category Security (MCS)

Label files with categories:

sudo chcon -l s0:c0,c1 /path/to/file

Run process with specific category:

runcon -l s0:c0,c1 command

3. Audit SELinux Policy

Search for type enforcement rules:

sesearch -A -s httpd_t -t httpd_sys_content_t

Find which processes can access a type:

sesearch -A -t httpd_sys_content_t

Check for specific permission:

sesearch -A -s httpd_t -c file -p write

4. Implement File Context Equivalency

Make one directory context equivalent to another:

sudo semanage fcontext -a -e /var/www/html /srv/website
sudo restorecon -Rv /srv/website

5. Monitor SELinux Denials in Real-Time

Watch audit log:

sudo tail -f /var/log/audit/audit.log | grep denied

Use sealert for human-readable alerts:

sudo sealert -a /var/log/audit/audit.log

Set up automatic email alerts:

Install and configure setroubleshoot-server, which automatically sends alerts.

6. Optimize SELinux Performance

Disable unnecessary booleans:

Review and disable booleans not needed for your environment.

Use targeted policy:

Avoid MLS policy unless specifically required.

Minimize custom policies:

Use built-in policy features when possible.

7. Implement Confined Services

Ensure critical services run confined:

ps -eZ | grep -E '(httpd|nginx|mysqld|postfix)'

Verify they show specific domain (e.g., httpd_t), not unconfined_t.

8. Regular Policy Updates

Keep SELinux policies current:

sudo dnf update selinux-policy\*

Verification and Testing

Verify SELinux is Enforcing

Check status:

getenforce
sestatus

Verify policy is loaded:

sudo semodule -l

Test File Context Application

Create test file:

sudo touch /var/www/html/test.html

Check automatic labeling:

ls -Z /var/www/html/test.html

Should show httpd_sys_content_t

Test context restoration:

sudo chcon -t user_home_t /var/www/html/test.html
ls -Z /var/www/html/test.html
sudo restorecon -v /var/www/html/test.html
ls -Z /var/www/html/test.html

Test SELinux Denials

Attempt unauthorized action:

sudo -u apache touch /root/test

Check for denial:

sudo ausearch -m avc -ts recent

Verify Boolean Changes

Change boolean and verify:

getsebool httpd_can_network_connect
sudo setsebool httpd_can_network_connect on
getsebool httpd_can_network_connect

Monitor System Behavior

Check for unexpected denials:

sudo ausearch -m avc -ts today

Use setroubleshoot:

sudo sealert -a /var/log/audit/audit.log

Troubleshooting Common Issues

Issue 1: Service Won't Start After Enabling SELinux

Symptoms: Service fails to start with permission errors

Solutions:

  1. Check for denials:

    sudo ausearch -m avc -ts recent | grep service_name
    
  2. Use sealert for suggestions:

    sudo sealert -a /var/log/audit/audit.log
    
  3. Verify file contexts:

    ls -Z /path/to/service/files
    sudo restorecon -Rv /path/to/service/files
    
  4. Check for required booleans:

    getsebool -a | grep service_name
    

Issue 2: Web Server Can't Access Files

Symptoms: Apache/Nginx returns 403 errors

Solutions:

  1. Check file contexts:

    ls -Z /var/www/html/
    
  2. Apply correct context:

    sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"
    sudo restorecon -Rv /var/www/html/
    
  3. For user directories:

    sudo setsebool -P httpd_enable_homedirs on
    

Issue 3: Custom Port Not Working

Symptoms: Service can't bind to non-standard port

Solutions:

  1. Check current port labels:

    sudo semanage port -l | grep http
    
  2. Add custom port:

    sudo semanage port -a -t http_port_t -p tcp 8080
    
  3. Verify addition:

    sudo semanage port -l | grep 8080
    

Issue 4: System Won't Boot After Enabling SELinux

Symptoms: System hangs or fails to boot

Solutions:

  1. Boot into permissive mode:

    • Edit GRUB boot parameters
    • Add: enforcing=0
  2. After boot, check for issues:

    sudo ausearch -m avc -ts today
    
  3. Fix issues, then re-enable:

    sudo setenforce 1
    

Issue 5: Relabeling Takes Too Long

Symptoms: Filesystem relabeling during boot is very slow

Solutions:

  1. Create autorelabel flag:

    sudo touch /.autorelabel
    sudo reboot
    
  2. Or relabel while running:

    sudo fixfiles -F onboot
    sudo reboot
    
  3. For specific paths only:

    sudo restorecon -Rv /specific/path
    

Issue 6: Unknown Denials

Symptoms: Denials without clear cause

Solutions:

  1. Use audit2why:

    sudo ausearch -m avc -ts recent | audit2why
    
  2. Get detailed explanation:

    sudo sealert -l <alert_id>
    
  3. Check dontaudit rules:

    sudo semodule -DB  # Temporarily disable dontaudit
    # Reproduce issue
    sudo semodule -B   # Re-enable dontaudit
    

Best Practices for SELinux Management

1. Deployment Strategy

  • Never disable SELinux: Use permissive mode for troubleshooting instead
  • Start with permissive: New deployments should begin in permissive mode
  • Gradual enforcement: Move to enforcing after resolving all denials
  • Test thoroughly: Test in non-production before enforcing in production
  • Plan relabeling: Schedule filesystem relabeling during maintenance windows

2. Operational Practices

  • Monitor regularly: Set up automated monitoring of SELinux denials
  • Use standard paths: Adhere to FHS to leverage default contexts
  • Leverage booleans: Use booleans before creating custom policies
  • Minimal custom policies: Rely on default policy when possible
  • Document changes: Maintain records of all SELinux customizations

3. Troubleshooting Workflow

  1. Identify the denial in audit logs
  2. Use sealert/audit2why for analysis
  3. Check for existing booleans that solve the issue
  4. Verify file contexts are correct
  5. Only create custom policy as last resort
  6. Test solutions in permissive mode first

4. Security Hardening

  • Enforce on all systems: Run production systems in enforcing mode
  • Confine users: Use confined users for interactive accounts
  • Audit custom policies: Regularly review custom policy modules
  • Minimize permissions: Apply principle of least privilege
  • Keep updated: Regularly update SELinux policies

5. Policy Management

  • Use policy modules: Create separate modules for different customizations
  • Version control: Track custom policies in version control
  • Policy documentation: Document why custom policies were created
  • Review regularly: Audit custom policies quarterly
  • Remove unused: Delete obsolete custom policy modules

6. Compliance and Auditing

  • Enable auditing: Ensure audit daemon is running
  • Log retention: Maintain SELinux logs per compliance requirements
  • Regular reviews: Monthly review of SELinux denials and customizations
  • Security assessments: Include SELinux configuration in security audits
  • Policy compliance: Verify policy meets organizational security standards

7. Training and Documentation

  • Team training: Ensure administrators understand SELinux fundamentals
  • Runbooks: Maintain documentation for common SELinux tasks
  • Incident procedures: Document response procedures for SELinux issues
  • Knowledge sharing: Share solutions to unique SELinux challenges
  • Stay current: Follow SELinux project updates and best practices

Conclusion

SELinux provides robust mandatory access control that significantly enhances Linux system security. While often perceived as complex, SELinux becomes manageable and valuable once you understand its fundamental concepts and operational modes. This comprehensive guide has covered everything from basic configuration to advanced policy management, providing you with the knowledge to effectively implement and maintain SELinux in production environments.

Key takeaways:

  • Essential security layer: SELinux provides critical protection beyond traditional permissions
  • Three operational modes: Enforcing, permissive, and disabled each serve specific purposes
  • Context-based security: Understanding security contexts is fundamental to SELinux
  • Gradual implementation: Start with permissive mode, resolve issues, then enforce
  • Built-in solutions: Leverage booleans and default policies before creating custom rules
  • Continuous monitoring: Regular monitoring and maintenance ensure optimal security

By following the practices outlined in this guide, you implement a powerful security mechanism that protects against both known and zero-day threats. SELinux is particularly effective at containing compromised applications, preventing privilege escalation, and protecting sensitive data through fine-grained access controls.

Remember that SELinux is not a replacement for other security measures but a complementary layer in a comprehensive defense-in-depth strategy. Combined with proper system hardening, network security, and security monitoring, SELinux significantly strengthens your overall security posture. Invest time in understanding and properly configuring SELinux—the security benefits far outweigh the initial learning curve, and modern troubleshooting tools make SELinux management increasingly accessible to administrators at all skill levels.