clickhouse
numpy
+
+
+
scipy
+
+
fortran
+
postgres
+
+
+
https
+
+
haiku
+
+
+
+
qdrant
+
play
+
+
+
+
==
+
+
js
+
+
gin
+
gitlab
{}
+
choo
hapi
+
+
fauna
+
+
+
+
+
+
marko
->
rails
+
rollup
fiber
mvn
::
+
cosmos
+
+
spring
+
mxnet
clickhouse
mocha
+
+
+
windows
+
+
//
+
bsd
spacy
+
redis
bsd
sse
+
julia
+
+
+
+
Back to Blog
SELinux Deep Dive Guide for Rocky Linux
Rocky Linux Security SELinux

SELinux Deep Dive Guide for Rocky Linux

Published Jul 27, 2025

Master SELinux on Rocky Linux with this comprehensive guide. Learn policies, contexts, troubleshooting, custom rules, and best practices for robust mandatory access control.

28 min read
0 views
Table of Contents

Security-Enhanced Linux (SELinux) is a powerful mandatory access control (MAC) system integrated into Rocky Linux that provides an additional layer of security beyond traditional discretionary access control. This comprehensive guide delves deep into SELinux, covering everything from basic concepts to advanced policy creation and troubleshooting techniques.

Understanding SELinux Fundamentals

What is SELinux?

SELinux is a Linux kernel security module that provides a mechanism for supporting access control security policies. It implements mandatory access control (MAC) using Linux Security Modules (LSM) in the Linux kernel.

Key Concepts

  • Mandatory Access Control (MAC): System-enforced access control based on security labels
  • Security Context: Labels assigned to processes, files, and other objects
  • Policy: Rules defining allowed interactions between labeled objects
  • Domain: Security context for processes
  • Type: Security context for files and objects

SELinux vs Traditional Linux Security

FeatureTraditional DACSELinux MAC
Control TypeDiscretionaryMandatory
Based OnUser identitySecurity labels
OverrideUsers can changeOnly admin can change
GranularityFile permissionsFine-grained policies
DefaultAllow unless deniedDeny unless allowed

SELinux Architecture and Components

Core Components

# SELinux kernel module
ls -la /sys/fs/selinux/

# Policy store
ls -la /etc/selinux/

# SELinux utilities
rpm -qa | grep selinux

# Main components:
# - Security Server (kernel space)
# - Access Vector Cache (AVC)
# - Security Policy
# - Object Managers
# - Policy Management Tools

Policy Types

# List available policies
semodule -l

# Common policy types:
# targeted - Default policy, confines targeted processes
# minimum - Minimal policy for specific services
# mls - Multi-Level Security policy
# strict - Strict policy confining all processes

SELinux Subsystems

  1. Type Enforcement (TE): Primary access control mechanism
  2. Role-Based Access Control (RBAC): Controls user access to domains
  3. Multi-Level Security (MLS): Hierarchical security levels
  4. Multi-Category Security (MCS): Category-based separation

SELinux Modes and States

SELinux Modes

# Check current mode
getenforce

# Check mode and policy
sestatus

# Set mode temporarily
sudo setenforce 0  # Permissive
sudo setenforce 1  # Enforcing

# Modes:
# Enforcing - SELinux enforces policy (blocks and logs)
# Permissive - SELinux logs but doesn't block
# Disabled - SELinux is completely disabled

Configuring SELinux Mode

# Edit configuration file
sudo nano /etc/selinux/config

# Set default mode
SELINUX=enforcing
# Options: enforcing, permissive, disabled

SELINUXTYPE=targeted
# Options: targeted, minimum, mls

# Apply changes (requires reboot)
sudo reboot

Mode Management

# Check detailed status
sestatus -v

# Temporary mode change
sudo setenforce Permissive
sudo setenforce Enforcing

# Check if SELinux is enabled
if [ $(getenforce) != "Disabled" ]; then
    echo "SELinux is enabled"
fi

# Boot parameters
# enforcing=0 - Boot in permissive mode
# selinux=0 - Disable SELinux

Working with SELinux Contexts

Understanding Contexts

# View file context
ls -lZ /etc/passwd
# -rw-r--r--. root root system_u:object_r:passwd_file_t:s0 /etc/passwd

# Context format: user:role:type:level
# user - SELinux user
# role - SELinux role
# type - SELinux type (most important)
# level - SELinux level (MLS/MCS)

# View process context
ps auxZ | grep nginx
# system_u:system_r:httpd_t:s0

# View current user context
id -Z

Context Components

# List SELinux users
semanage user -l

# List SELinux roles
seinfo -r

# List SELinux types
seinfo -t

# List type attributes
seinfo -a

# Show context mappings
semanage login -l

Changing Contexts

# Temporary context change
chcon -t httpd_sys_content_t /var/www/html/index.html

# Recursive context change
chcon -R -t httpd_sys_content_t /var/www/html/

# Copy context from reference
chcon --reference=/var/www/html/existing.html /var/www/html/new.html

# View context changes
matchpathcon /var/www/html/index.html

Managing SELinux Policies

Policy Modules

# List loaded modules
semodule -l

# Install policy module
sudo semodule -i mymodule.pp

# Remove policy module
sudo semodule -r mymodule

# Disable policy module
sudo semodule -d mymodule

# Enable policy module
sudo semodule -e mymodule

# Rebuild policy
sudo semodule -B

Policy Information

# Show policy version
sestatus | grep "Policy version"

# Show loaded policy name
sestatus | grep "Loaded policy name"

# Query policy capabilities
seinfo --common

# Show policy statistics
seinfo --stats

# List all types
seinfo -t | less

# Search for specific type
seinfo -t | grep httpd

Policy Management Tools

# SELinux policy analysis
sesearch --allow --source httpd_t --target httpd_sys_content_t

# Find rules for a domain
sesearch --allow --source httpd_t

# Find rules for a type
sesearch --allow --target passwd_file_t

# Analyze policy denials
audit2why < /var/log/audit/audit.log

# Generate policy from denials
audit2allow -a

SELinux Booleans

Understanding Booleans

# List all booleans
getsebool -a

# List booleans with descriptions
semanage boolean -l

# Check specific boolean
getsebool httpd_enable_cgi

# Search for booleans
getsebool -a | grep httpd
semanage boolean -l | grep ftp

Managing Booleans

# Set boolean temporarily
sudo setsebool httpd_enable_cgi on
sudo setsebool httpd_enable_cgi off

# Set boolean permanently
sudo setsebool -P httpd_enable_cgi on

# Toggle boolean
sudo setsebool httpd_can_network_connect_db=!

# Set multiple booleans
sudo setsebool -P httpd_enable_cgi=on httpd_can_sendmail=on

Common Booleans

# Web server booleans
httpd_can_network_connect  # Allow httpd network connections
httpd_can_network_connect_db  # Allow httpd database connections
httpd_enable_cgi  # Allow httpd to execute CGI scripts
httpd_read_user_content  # Allow httpd to read user content

# FTP booleans
ftpd_anon_write  # Allow anonymous FTP writes
ftpd_full_access  # Allow FTP full file system access

# Samba booleans
samba_enable_home_dirs  # Allow Samba to share home directories
samba_export_all_rw  # Allow Samba to export all files

# SSH booleans
ssh_sysadm_login  # Allow ssh logins as sysadm_r:sysadm_t

File Context Management

Default File Contexts

# View default contexts
semanage fcontext -l

# Search for specific path
semanage fcontext -l | grep /var/www

# Check expected context
matchpathcon /var/www/html/

# Verify file contexts
restorecon -v /var/www/html/index.html

# Dry run restore
restorecon -n -v /var/www/html/

Managing File Contexts

# Add custom file context
sudo semanage fcontext -a -t httpd_sys_content_t "/webdata(/.*)?"

# Modify existing context
sudo semanage fcontext -m -t httpd_sys_rw_content_t "/var/www/uploads(/.*)?"

# Delete file context
sudo semanage fcontext -d "/oldpath(/.*)?"

# Apply file contexts
sudo restorecon -Rv /webdata/

# Relabel entire file system
sudo touch /.autorelabel
sudo reboot

Context Patterns

# Common context patterns
# Web content
semanage fcontext -a -t httpd_sys_content_t "/custom/website(/.*)?"

# Writable web content  
semanage fcontext -a -t httpd_sys_rw_content_t "/custom/uploads(/.*)?"

# CGI scripts
semanage fcontext -a -t httpd_sys_script_exec_t "/custom/cgi-bin(/.*)?"

# Database files
semanage fcontext -a -t mysqld_db_t "/custom/mysql(/.*)?"

# Log files
semanage fcontext -a -t httpd_log_t "/custom/logs(/.*)?"

File Context Equivalence

# Create context equivalence
sudo semanage fcontext -a -e /var/www /custom/www

# List equivalences
semanage fcontext -l | grep -E '^/'

# Remove equivalence
sudo semanage fcontext -d -e /var/www /custom/www

Process and Port Management

Process Contexts

# View all process contexts
ps auxZ

# View specific process context
ps -eZ | grep httpd

# Run command in specific context
runcon -t httpd_t /usr/bin/id

# Transition context
runcon system_u:system_r:httpd_t:s0 /usr/sbin/httpd

# Check process transitions
sesearch --allow --source init_t --target httpd_t --class process

Domain Transitions

# View domain transitions
sesearch -T -s httpd_t

# Check executable entry points
sesearch --allow --target httpd_exec_t --class file --perm entrypoint

# View process transition rules
sesearch --allow --source initrc_t --target httpd_t --class process --perm transition

Port Contexts

# List all port contexts
semanage port -l

# Search for specific port
semanage port -l | grep 80

# Add custom port
sudo semanage port -a -t http_port_t -p tcp 8080

# Modify port context
sudo semanage port -m -t http_port_t -p tcp 8888

# Delete port context
sudo semanage port -d -t http_port_t -p tcp 8080

# Common port types:
# http_port_t - HTTP service ports
# ssh_port_t - SSH service ports
# smtp_port_t - SMTP service ports
# mysqld_port_t - MySQL service ports

Troubleshooting SELinux Issues

Identifying SELinux Denials

# Check for recent denials
sudo ausearch -m avc -ts recent

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

# Check for denials in messages
sudo grep "SELinux" /var/log/messages

# Use sealert for detailed analysis
sudo sealert -a /var/log/audit/audit.log

# Check setroubleshoot messages
sudo journalctl -t setroubleshoot

Analyzing Denials

# Parse denial message
echo "type=AVC msg=audit(1234567890.123:456): avc:  denied  { read } for  pid=1234 comm="httpd" name="index.html" dev="dm-0" ino=12345 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0" | audit2why

# Generate allow rules
sudo audit2allow -a

# Generate policy module
sudo audit2allow -a -M myfix

# Create and analyze local policy
sudo grep denied /var/log/audit/audit.log | audit2allow -M local
cat local.te  # Review generated policy

Common Troubleshooting Steps

# 1. Verify SELinux is the issue
setenforce 0
# Test application
setenforce 1

# 2. Check file contexts
ls -lZ /path/to/file
restorecon -v /path/to/file

# 3. Check process context
ps auxZ | grep process_name

# 4. Check booleans
getsebool -a | grep relevant_service

# 5. Check port contexts
semanage port -l | grep port_number

# 6. Generate and review policy
audit2allow -a -l -r

Using setroubleshoot

# Install setroubleshoot
sudo dnf install setroubleshoot-server

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

# Get detailed report for specific alert
sudo sealert -l "*"

# Browser-based analysis
sudo sealert -b

# Email notifications
sudo nano /etc/setroubleshoot/setroubleshoot.conf
# recipients = root@localhost

Creating Custom SELinux Policies

Policy Development Workflow

# 1. Create policy directory
mkdir ~/selinux-policy
cd ~/selinux-policy

# 2. Generate initial policy
sudo grep denied /var/log/audit/audit.log | grep myapp | audit2allow -m myapp > myapp.te

# 3. Review and edit policy
nano myapp.te

# 4. Compile policy module
make -f /usr/share/selinux/devel/Makefile myapp.pp

# 5. Install policy module
sudo semodule -i myapp.pp

# 6. Test and refine
# Repeat steps 2-5 as needed

Writing Policy Modules

Create myapp.te:

policy_module(myapp, 1.0.0)

########################################
# Declarations
#

type myapp_t;
type myapp_exec_t;
init_daemon_domain(myapp_t, myapp_exec_t)

type myapp_log_t;
logging_log_file(myapp_log_t)

type myapp_var_run_t;
files_pid_file(myapp_var_run_t)

type myapp_data_t;
files_type(myapp_data_t)

########################################
# myapp local policy
#

# Allow myapp to read system state
kernel_read_system_state(myapp_t)

# Allow myapp to read /etc files
files_read_etc_files(myapp_t)

# Allow myapp to write logs
allow myapp_t myapp_log_t:file { create_file_perms append_file_perms };
allow myapp_t myapp_log_t:dir { rw_dir_perms setattr_dir_perms };
logging_log_filetrans(myapp_t, myapp_log_t, { file dir })

# Allow myapp to create pid file
manage_files_pattern(myapp_t, myapp_var_run_t, myapp_var_run_t)
files_pid_filetrans(myapp_t, myapp_var_run_t, file)

# Allow myapp to manage its data
manage_dirs_pattern(myapp_t, myapp_data_t, myapp_data_t)
manage_files_pattern(myapp_t, myapp_data_t, myapp_data_t)

# Network access
corenet_tcp_bind_generic_node(myapp_t)
corenet_tcp_bind_generic_port(myapp_t)
allow myapp_t self:tcp_socket create_stream_socket_perms;

File Context Module

Create myapp.fc:

# myapp executable
/usr/local/bin/myapp    --    gen_context(system_u:object_r:myapp_exec_t,s0)

# myapp data directory
/var/lib/myapp(/.*)?          gen_context(system_u:object_r:myapp_data_t,s0)

# myapp log directory
/var/log/myapp(/.*)?          gen_context(system_u:object_r:myapp_log_t,s0)

# myapp pid file
/var/run/myapp\.pid     --    gen_context(system_u:object_r:myapp_var_run_t,s0)

Interface Module

Create myapp.if:

## <summary>My application policy</summary>

########################################
## <summary>
##     Execute myapp in the myapp domain.
## </summary>
## <param name="domain">
##     <summary>
##     Domain allowed to transition.
##     </summary>
## </param>
#
interface(`myapp_domtrans',`
    gen_require(`
        type myapp_t, myapp_exec_t;
    ')

    corecmd_search_bin($1)
    domtrans_pattern($1, myapp_exec_t, myapp_t)
')

########################################
## <summary>
##     Read myapp log files.
## </summary>
## <param name="domain">
##     <summary>
##     Domain allowed access.
##     </summary>
## </param>
#
interface(`myapp_read_log',`
    gen_require(`
        type myapp_log_t;
    ')

    logging_search_logs($1)
    read_files_pattern($1, myapp_log_t, myapp_log_t)
')

Building and Installing

# Create Makefile
cat > Makefile << 'EOF'
TARGETS = myapp
MODULES = ${TARGETS:=.pp}

all: ${MODULES}

%.pp: %.te %.fc %.if
	make -f /usr/share/selinux/devel/Makefile $@

install: all
	semodule -i ${MODULES}

clean:
	rm -f *.pp *.tc *.mod

EOF

# Build policy
make

# Install policy
sudo make install

# Apply file contexts
sudo restorecon -Rv /usr/local/bin/myapp /var/lib/myapp /var/log/myapp

SELinux for Common Services

Web Server (Apache/Nginx)

# Common booleans
sudo setsebool -P httpd_can_network_connect on
sudo setsebool -P httpd_can_network_connect_db on
sudo setsebool -P httpd_enable_cgi on
sudo setsebool -P httpd_read_user_content on

# File contexts
sudo semanage fcontext -a -t httpd_sys_content_t "/custom/www(/.*)?"
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/custom/www/uploads(/.*)?"
sudo semanage fcontext -a -t httpd_sys_script_exec_t "/custom/www/cgi-bin(/.*)?"
sudo restorecon -Rv /custom/www/

# Custom ports
sudo semanage port -a -t http_port_t -p tcp 8080

Database Services

# MariaDB/MySQL
sudo setsebool -P mysql_connect_any on
sudo semanage fcontext -a -t mysqld_db_t "/custom/mysql(/.*)?"
sudo semanage port -a -t mysqld_port_t -p tcp 3307
sudo restorecon -Rv /custom/mysql/

# PostgreSQL
sudo setsebool -P postgresql_can_rsync on
sudo semanage fcontext -a -t postgresql_db_t "/custom/pgsql(/.*)?"
sudo semanage port -a -t postgresql_port_t -p tcp 5433

File Sharing Services

# Samba
sudo setsebool -P samba_enable_home_dirs on
sudo setsebool -P samba_export_all_rw on
sudo semanage fcontext -a -t samba_share_t "/shares/public(/.*)?"
sudo restorecon -Rv /shares/public/

# NFS
sudo setsebool -P nfs_export_all_rw on
sudo setsebool -P nfs_export_all_ro on
sudo semanage fcontext -a -t nfs_t "/exports(/.*)?"

Container Services

# Docker/Podman
sudo setsebool -P container_manage_cgroup on
sudo setsebool -P container_use_cephfs on

# Custom container storage
sudo semanage fcontext -a -t container_var_lib_t "/custom/containers(/.*)?"
sudo restorecon -Rv /custom/containers/

Advanced SELinux Configurations

Multi-Level Security (MLS)

# Switch to MLS policy
sudo nano /etc/selinux/config
# SELINUXTYPE=mls

# Set up MLS ranges
sudo semanage user -m -r s0-s15:c0.c1023 user_u

# Assign MLS levels to files
sudo chcon -l s0:c0,c1 /path/to/file

# Create MLS categories
sudo semanage user -m -L s0 -r s0-s0:c0.c100 limited_u

Custom User Domains

# Create new SELinux user
sudo semanage user -a -R "staff_r system_r" -r s0-s0:c0.c1023 myuser_u

# Map Linux user to SELinux user
sudo semanage login -a -s myuser_u mylinuxuser

# Create custom role
# In policy module:
role myrole_r;
role myrole_r types myapp_t;

Confined Users

# List user mappings
semanage login -l

# Confine existing user
sudo semanage login -a -s user_u regularuser

# Create confined admin
sudo semanage login -a -s staff_u -r s0-s0:c0.c1023 adminuser

# User types:
# unconfined_u - Unconfined user
# user_u - Regular confined user
# staff_u - Admin confined user
# sysadm_u - System admin user
# system_u - System processes

Policy Constraints

# View constraints
seinfo --constrain

# Common constraints:
# - Process transitions
# - File access controls
# - Network restrictions
# - IPC limitations

# Example constraint in policy:
constrain file { create relabelto relabelfrom } 
    ( u1 == u2 or t1 == can_change_object_identity );

SELinux Best Practices

Development and Testing

  1. Use Permissive Mode during development
  2. Test thoroughly before enforcing
  3. Document all custom policies
  4. Use version control for policy modules
  5. Test on non-production systems first

Production Deployment

  1. Always run in Enforcing mode
  2. Monitor audit logs regularly
  3. Keep policies minimal
  4. Use booleans before custom policies
  5. Regular policy reviews

Security Guidelines

# Regular audits
# Check for unconfined domains
sesearch --allow --source unconfined_t

# Find world-writable files
find / -type f -perm -002 -exec ls -lZ {} \; 2>/dev/null

# Check for mislabeled files
sudo fixfiles -v check

# Verify policy integrity
sudo semodule -v

Maintenance Tasks

# Regular maintenance script
#!/bin/bash

# Update file contexts
echo "Checking file contexts..."
sudo restorecon -Rnv /var/www/ /home/

# Check for policy denials
echo "Recent SELinux denials:"
sudo ausearch -m avc -ts today

# Verify booleans
echo "Non-default booleans:"
sudo getsebool -a | grep -v '> off$' | grep -v 'on$'

# Check policy modules
echo "Custom policy modules:"
sudo semodule -l | grep -v '^[[:space:]]*100[[:space:]]'

Performance Considerations

SELinux Impact

# Measure AVC cache performance
cat /sys/fs/selinux/avc/cache_stats

# Check policy load time
time sudo semodule -R

# Monitor SELinux overhead
perf record -e avc:selinux_audited -a sleep 10
perf report

Optimization Techniques

  1. Minimize policy size - Remove unused modules
  2. Optimize file contexts - Use equivalence where possible
  3. Cache tuning - Adjust AVC cache size if needed
  4. Reduce audit logging - Use audit rules efficiently
# Disable unused modules
sudo semodule -d unused_module

# Set AVC cache threshold
echo 512 > /sys/fs/selinux/avc/cache_threshold

# Optimize audit rules
sudo auditctl -a never,exit -F arch=b64 -S all -F subj_type=httpd_t

Monitoring Performance

# SELinux statistics
sestatus -v

# AVC statistics
avcstat

# Policy statistics
seinfo --stats

# Audit performance
aureport --summary

Conclusion

SELinux provides robust mandatory access control for Rocky Linux systems, significantly enhancing security when properly configured. While it has a learning curve, mastering SELinux is essential for maintaining secure production environments.

Key takeaways:

  • Start with understanding contexts and policies
  • Use existing booleans and contexts when possible
  • Create custom policies only when necessary
  • Always test in permissive mode first
  • Monitor and analyze audit logs regularly
  • Keep policies documented and version controlled

With practice and the right approach, SELinux becomes a powerful ally in system security rather than an obstacle.