netsapiensis

rocky-selinux

0
0
# Install this skill:
npx skills add netsapiensis/claude-code-skills --skill "rocky-selinux"

Install specific skill from multi-skill repository

# Description

SELinux management on Rocky Linux 8/9 including modes, file contexts, booleans, port labeling, and troubleshooting with audit2why/audit2allow. Use when troubleshooting permission denials, configuring SELinux for services, managing file contexts, or diagnosing AVC denials.

# SKILL.md


name: rocky-selinux
description: SELinux management on Rocky Linux 8/9 including modes, file contexts, booleans, port labeling, and troubleshooting with audit2why/audit2allow. Use when troubleshooting permission denials, configuring SELinux for services, managing file contexts, or diagnosing AVC denials.


Rocky Linux SELinux Management

SELinux policy management, file contexts, booleans, port labeling, and troubleshooting for Rocky Linux 8/9.

Prerequisite: See rocky-foundation for OS detection and safety tier definitions.

Critical Rule

NEVER recommend disabling SELinux. Always troubleshoot and fix SELinux issues properly.

WRONG:

# WRONG -- NEVER do any of these:
setenforce 0                          # Disables enforcement
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
echo 0 > /sys/fs/selinux/enforce

CORRECT:

# CORRECT -- Troubleshoot and fix the actual issue
# 1. Check what's being denied
ausearch -m AVC -ts recent            # [READ-ONLY]
# 2. Understand why
audit2why < /var/log/audit/audit.log  # [READ-ONLY]
# 3. Apply the proper fix (context, boolean, or policy module)

SELinux Status and Modes

# Check current status  # [READ-ONLY]
getenforce                            # Quick: Enforcing/Permissive/Disabled
sestatus                              # Detailed status
sestatus -v                           # Verbose with context info

# Temporarily set permissive (for debugging only)  # [CONFIRM]
setenforce 0                          # Permissive (logs but doesn't block)
setenforce 1                          # Enforcing (restore when done debugging)

Permanent mode is set in /etc/selinux/config:

# /etc/selinux/config
SELINUX=enforcing     # enforcing | permissive | disabled
SELINUXTYPE=targeted  # Always 'targeted' on Rocky

WARNING: Changing from disabled to enforcing requires a full filesystem relabel on next boot:

# Force relabel on next boot  # [CONFIRM]
touch /.autorelabel
reboot                                # [CONFIRM]
# Relabel can take a long time on large filesystems

File Contexts

Viewing Contexts

# View file contexts  # [READ-ONLY]
ls -Z /var/www/html/
ls -Zd /opt/myapp/
stat -c '%C' /var/www/html/index.html

# View default context rules  # [READ-ONLY]
semanage fcontext -l | grep /var/www
semanage fcontext -l | grep httpd
matchpathcon /var/www/html/index.html    # Rocky 8
# On Rocky 9, use:
selabel_lookup /var/www/html/index.html  # Or: restorecon -nv /path

Setting File Contexts

CORRECT -- use semanage fcontext + restorecon:

# Add a custom context rule  # [CONFIRM]
semanage fcontext -a -t httpd_sys_content_t "/opt/myapp/public(/.*)?"

# Apply the rule to existing files  # [CONFIRM]
restorecon -Rv /opt/myapp/public/

# Verify  # [READ-ONLY]
ls -Z /opt/myapp/public/

WRONG -- using chcon:

# WRONG: chcon changes are lost on restorecon or relabel
chcon -R -t httpd_sys_content_t /opt/myapp/public/
# Next restorecon or relabel will revert this!

# CORRECT: semanage fcontext persists permanently
semanage fcontext -a -t httpd_sys_content_t "/opt/myapp/public(/.*)?"
restorecon -Rv /opt/myapp/public/

Common File Context Types

Context Type Purpose
httpd_sys_content_t Web content (read-only by httpd)
httpd_sys_rw_content_t Web content (read-write by httpd)
httpd_log_t Web server logs
httpd_config_t Web server configuration
mysqld_db_t MariaDB/MySQL data files
var_log_t Log files in /var/log
etc_t Configuration files
user_home_t User home directory content
ssh_home_t SSH keys (~/.ssh)
cert_t TLS/SSL certificates
container_file_t Container-accessible files

Manage Custom Context Rules

# List custom rules  # [READ-ONLY]
semanage fcontext -l -C            # -C shows only custom (local) rules

# Modify existing rule  # [CONFIRM]
semanage fcontext -m -t httpd_sys_rw_content_t "/opt/myapp/uploads(/.*)?"

# Delete custom rule  # [CONFIRM]
semanage fcontext -d "/opt/myapp/public(/.*)?"

# Restore default contexts for a path  # [CONFIRM]
restorecon -Rv /var/www/html/

Booleans

SELinux booleans toggle pre-defined policy rules on/off.

# List all booleans  # [READ-ONLY]
getsebool -a
getsebool -a | grep httpd

# Check specific boolean  # [READ-ONLY]
getsebool httpd_can_network_connect

# Set boolean temporarily (lost on reboot)  # [CONFIRM]
setsebool httpd_can_network_connect on

# Set boolean permanently  # [CONFIRM]
setsebool -P httpd_can_network_connect on

Common Booleans by Service

Web server (httpd/nginx):

# Allow httpd to make network connections (e.g., reverse proxy)  # [CONFIRM]
setsebool -P httpd_can_network_connect on

# Allow httpd to connect to databases  # [CONFIRM]
setsebool -P httpd_can_network_connect_db on

# Allow httpd to send email  # [CONFIRM]
setsebool -P httpd_can_sendmail on

# Allow httpd to read user home directories  # [CONFIRM]
setsebool -P httpd_enable_homedirs on

# Allow httpd to execute CGI scripts  # [CONFIRM]
setsebool -P httpd_enable_cgi on

# Allow httpd to use NFS-mounted content  # [CONFIRM]
setsebool -P httpd_use_nfs on

SSH:

# Allow SSH to use non-standard port  # [CONFIRM]
# (Also need semanage port -- see Port Labeling section)
setsebool -P ssh_sysadm_login on

Samba/NFS:

setsebool -P samba_enable_home_dirs on   # [CONFIRM]
setsebool -P use_nfs_home_dirs on        # [CONFIRM]

Port Labeling

SELinux restricts which ports services can bind to.

# List port labels  # [READ-ONLY]
semanage port -l | grep http
semanage port -l | grep ssh
semanage port -l | grep -w 8080

# Allow httpd on custom port  # [CONFIRM]
semanage port -a -t http_port_t -p tcp 8080

# Allow SSH on custom port  # [CONFIRM]
semanage port -a -t ssh_port_t -p tcp 2222

# Allow OpenSearch ports  # [CONFIRM]
semanage port -a -t http_port_t -p tcp 9200
semanage port -a -t http_port_t -p tcp 9300

# Remove custom port label  # [CONFIRM]
semanage port -d -t http_port_t -p tcp 8080

# List custom port rules  # [READ-ONLY]
semanage port -l -C

WRONG -- only changing the service config without SELinux:

# WRONG: Changed nginx to port 8080 but forgot SELinux
# nginx.conf: listen 8080;
# Result: nginx fails to bind, AVC denial in audit log

# CORRECT: Update SELinux port label first, then change config
semanage port -a -t http_port_t -p tcp 8080      # [CONFIRM]
# Then update nginx.conf and restart

Troubleshooting SELinux Denials

Step-by-Step Troubleshooting

Step 1: Identify the denial

# Recent AVC denials  # [READ-ONLY]
ausearch -m AVC -ts recent
ausearch -m AVC --start today
ausearch -m AVC -c httpd              # Filter by command

# Or from audit.log directly  # [READ-ONLY]
grep "type=AVC" /var/log/audit/audit.log | tail -20

# SELinux denial messages in journal  # [READ-ONLY]
journalctl -t setroubleshoot --since "1 hour ago"

Step 2: Understand the denial

# Use audit2why for human-readable explanation  # [READ-ONLY]
ausearch -m AVC -ts recent | audit2why

# Or from the full log  # [READ-ONLY]
audit2why < /var/log/audit/audit.log

# sealert for detailed analysis (if setroubleshoot installed)  # [READ-ONLY]
sealert -a /var/log/audit/audit.log

Step 3: Apply the fix

The fix depends on what audit2why tells you:

audit2why says Fix
"was caused by missing file context" semanage fcontext + restorecon
"setsebool" Set the recommended boolean
"was caused by a missing type" May need a custom policy module
"was caused by incorrect file context" restorecon -Rv /path

Step 4: Verify the fix

# Clear the denial by restarting the service  # [CONFIRM]
systemctl restart httpd

# Check no new denials  # [READ-ONLY]
ausearch -m AVC -ts recent

Creating Custom Policy Modules (Last Resort)

Only when file contexts and booleans don't solve the issue:

# Generate a policy module from denials  # [READ-ONLY] (generation only)
ausearch -m AVC -ts recent | audit2allow -M mypolicy

# Review the generated policy  # [READ-ONLY]
cat mypolicy.te

# Install the policy module  # [CONFIRM]
semodule -i mypolicy.pp

# List installed custom modules  # [READ-ONLY]
semodule -l | grep mypolicy

# Remove a custom module  # [CONFIRM]
semodule -r mypolicy

WARNING: Never blindly pipe audit2allow output into semodule. Always review the .te file first to understand what permissions you're granting.

Process Domain Troubleshooting

# Check what domain a process is running in  # [READ-ONLY]
ps -eZ | grep nginx
ps -eZ | grep httpd

# Check if a process is confined  # [READ-ONLY]
ps -eZ | grep unconfined_t        # These are not confined

# View transitions  # [READ-ONLY]
sesearch -T -s init_t -t httpd_exec_t   # Rocky 8
sesearch --type_trans -s init_t -t httpd_exec_t  # Rocky 9

SELinux and Common Services

Apache/Nginx

# Custom web root
semanage fcontext -a -t httpd_sys_content_t "/opt/www(/.*)?"   # [CONFIRM]
restorecon -Rv /opt/www/                                        # [CONFIRM]

# Writable directory (uploads)
semanage fcontext -a -t httpd_sys_rw_content_t "/opt/www/uploads(/.*)?"  # [CONFIRM]
restorecon -Rv /opt/www/uploads/                                          # [CONFIRM]

# Reverse proxy
setsebool -P httpd_can_network_connect on    # [CONFIRM]

MariaDB/MySQL

# Custom data directory
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"   # [CONFIRM]
restorecon -Rv /data/mysql/                                # [CONFIRM]

# Custom log location
semanage fcontext -a -t mysqld_log_t "/var/log/mariadb(/.*)?"  # [CONFIRM]
restorecon -Rv /var/log/mariadb/                                # [CONFIRM]

SSH

# Non-standard SSH port
semanage port -a -t ssh_port_t -p tcp 2222     # [CONFIRM]

Container (Podman)

# Allow containers to access host path
semanage fcontext -a -t container_file_t "/srv/containers(/.*)?"  # [CONFIRM]
restorecon -Rv /srv/containers/                                    # [CONFIRM]

# Or use the :Z/:z volume flag in podman (auto-labels)
podman run -v /srv/data:/data:Z myimage   # [CONFIRM]

Version Differences

Feature Rocky 8 Rocky 9
matchpathcon Available Deprecated (use restorecon -nv)
sesearch syntax -T flag --type_trans
setools-console Package name Same
Default policy targeted targeted
Policy version Older Newer (more rules)
MLS/MCS Available Available

Checklist: SELinux for New Service Deployment

  • [ ] Service is running in correct SELinux domain (ps -eZ | grep <service>)
  • [ ] Data directories have correct file contexts (ls -Z)
  • [ ] Custom paths registered with semanage fcontext
  • [ ] Non-standard ports registered with semanage port
  • [ ] Required booleans enabled (getsebool -a | grep <service>)
  • [ ] No AVC denials after testing (ausearch -m AVC -ts recent)
  • [ ] Custom rules documented for future reference

When to Use This Skill

  • Any "Permission denied" error that isn't a standard Unix permission issue
  • Deploying a new service or changing service paths
  • Moving service data to non-standard directories
  • Changing service ports
  • AVC denial messages in logs
  • After system relabel or SELinux policy updates
  • Configuring containers with host volumes
  • rocky-foundation -- OS detection, safety tiers
  • rocky-webstack -- Web server SELinux contexts
  • rocky-security-hardening -- SELinux as part of security posture
  • rocky-core-system -- Service management (services must run in correct domains)
  • rocky-opensearch -- OpenSearch-specific SELinux contexts

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.