Troubleshooting 'SELinux Permission Denied': Causes and Solutions
Fix 'SELinux permission denied' errors on Linux. Learn how to diagnose AVC denials using audit2allow, semanage, and restorecon to resolve access issues securely
- Incorrect file context is the most common cause of SELinux permission denied errors, especially after moving files.
- Boolean values restricting service capabilities (like an HTTP server attempting to connect to a database) often block expected behaviors.
- Use 'ausearch' and 'audit2allow' to quickly identify the root cause of AVC (Access Vector Cache) denials.
- Always prefer fixing contexts with 'semanage fcontext' and 'restorecon' over disabling SELinux.
| Method | When to Use | Time | Risk |
|---|---|---|---|
| restorecon | When files have the wrong context (e.g., moved files) | Fast | Low |
| semanage fcontext | To define persistent custom file paths for a service | Medium | Low |
| setsebool | When a service needs a specific capability (e.g., sending email) | Fast | Low |
| audit2allow | For custom applications or complex policy exceptions | Medium | Medium |
| setenforce 0 | Only for temporary debugging, never for production | Immediate | High |
Understanding the Error
Security-Enhanced Linux (SELinux) is a mandatory access control (MAC) security mechanism implemented in the Linux kernel. When you encounter a Permission denied error despite having the correct standard Linux permissions (owner, group, read/write/execute), SELinux is often the culprit.
SELinux operates on the principle of least privilege, meaning processes only have access to the files, directories, and resources explicitly permitted by their policy. When a process attempts an action that violates this policy, the kernel denies the action and logs an Access Vector Cache (AVC) denial.
Identifying an SELinux Denial
The typical symptom is a service failing to start, a web server returning a 403 Forbidden, or a script failing with Permission denied. To confirm if SELinux is blocking the action, check the audit log:
sudo grep AVC /var/log/audit/audit.log
You might see an entry like this:
type=AVC msg=audit(1612345678.123:456): avc: denied { read } for pid=1234 comm="httpd" name="index.html" dev="sda1" ino=56789 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
This log tells us that the process httpd running with the source context (scontext) of httpd_t tried to read a file with the target context (tcontext) of user_home_t, and was denied.
Step 1: Diagnose the Root Cause
The most common causes for SELinux denials fall into three categories:
- Incorrect File Contexts: Files moved (not copied) from a user directory often retain their original context (e.g.,
user_home_t) instead of inheriting the destination's context (e.g.,httpd_sys_content_t). - Disabled Booleans: Many services have optional features controlled by SELinux booleans. For instance, allowing Apache to connect to a database requires explicitly toggling a boolean.
- Non-Standard Ports: If you configure a service (like SSH or Nginx) to listen on a non-standard port, SELinux will block it unless you update the port definitions.
Step 2: Implement the Fix
Scenario A: Fixing File Contexts
If the issue is incorrect file labels (very common for web root directories or custom data mounts), you should update the context. Never use chcon for permanent fixes, as its changes are lost upon a filesystem relabel. Instead, use semanage and restorecon.
Define the rule:
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/mywebsite(/.*)?"Apply the rule:
sudo restorecon -Rv /var/www/mywebsite
Scenario B: Enabling Booleans If an application needs to perform an action restricted by policy (e.g., a PHP script sending email or an application connecting to a remote database), find the relevant boolean and enable it.
List related booleans:
sudo getsebool -a | grep httpdEnable the boolean persistently:
sudo setsebool -P httpd_can_network_connect 1
Scenario C: Allowing Custom Ports If you moved SSH to port 2222, allow it:
sudo semanage port -a -t ssh_port_t -p tcp 2222
Step 3: Generating Custom Modules (Last Resort)
If the application is custom or the policy is too strict, use audit2allow to generate a custom policy module from the audit logs.
sudo grep httpd /var/log/audit/audit.log | audit2allow -M mypol
sudo semodule -i mypol.pp
Always review the .te (Type Enforcement) file generated by audit2allow before installing the module to ensure it is not granting overly broad permissions that could compromise the system.
Frequently Asked Questions
# 1. Check if SELinux is enforcing
getenforce
sestatus
# 2. Search for recent AVC denials
sudo ausearch -m AVC -ts recent
# 3. Analyze audit logs and get fix suggestions (requires setroubleshoot)
sudo grep AVC /var/log/audit/audit.log | audit2allow -w -a
# 4. View current file contexts
ls -lZ /path/to/directory
# 5. Fix file contexts permanently
sudo semanage fcontext -a -t httpd_sys_content_t "/custom/www(/.*)?"
sudo restorecon -Rv /custom/www
# 6. Check available SELinux booleans
getsebool -a | grep keywordError Medic Editorial
The Error Medic Editorial team consists of senior Linux administrators and DevOps engineers dedicated to providing actionable, secure solutions to complex infrastructure challenges.