| |

LFCS 143 ๐Ÿง SELinux โ€” Troubleshooting

โฑ๏ธ Estimated read: 12 min | |

The previous chapters covered the SELinux modes, contexts, and booleans. This chapter covers the workflow for diagnosing an access denial. An application fails, the logs show a denial, and the administrator must decide whether the cause is a mislabeled file, a boolean that needs to be toggled, a port that is not permitted, or a policy rule that is missing. The LFCS exam tests the commands that reveal the denial and the sequence of fixes that the administrator should try before writing a custom policy. The critical trap is the order of the fixes. A custom policy module generated by audit2allow is the last resort, not the first. The first three checks are the file context, the boolean, and the port. If none of them resolves the denial, the custom policy is the correct final step .

Key point: The ausearch -m avc command reveals the denial. The sealert command translates the denial into a human-readable explanation. The audit2why command explains why the denial occurred. The fixes, in order, are: relabel the file with restorecon, toggle the boolean with setsebool -P, add the port with semanage port -a, and only then generate a custom policy with audit2allow. The audit2allow output must be reviewed before installation, because it grants whatever the denial requested.


Why troubleshooting requires a specific sequence

The AVC log problem. When SELinux denies an action, it logs an AVC (Access Vector Cache) message. The message is in /var/log/audit/audit.log if auditd is running, and in /var/log/messages if it is not. The ausearch -m avc command searches the audit log for the AVC messages. The -ts recent flag limits the search to the recent entries, which is the correct filter after reproducing the failure .

The interpretation problem. The raw AVC message is cryptic. It contains the source context (scontext), the target context (tcontext), the target class (tclass), and the denied permission. The sealert -a /var/log/audit/audit.log command parses the log and produces a human-readable description with a suggested fix. The audit2why command translates a single AVC message into an explanation. The sealert is the more comprehensive tool because it groups the related denials and suggests the boolean or the semanage command .

The fix-order problem. The common causes of a denial are, in order of likelihood: a mislabeled file, a boolean that is off, and a port that is not permitted. The file mislabel happens when a file is moved with mv instead of cp, or when a file is created in a directory that does not have the correct default type. The boolean happens when a service needs a capability that the policy disables by default, such as httpd_can_network_connect. The port happens when a service is configured to listen on a port that is not in the service’s port type . The custom policy is the last resort for the cases that the first three do not cover.

The per-domain permissive problem. If an application has multiple denials, the enforcing mode stops at the first one. The semanage permissive -a <domain> command puts a single domain in permissive mode, which allows the application to run while logging every denial. The administrator can exercise all the application’s features, collect the complete set of denials, and generate a single policy module. The semanage permissive -d <domain> removes the permissive mode after the policy is installed .

The trade-off. The audit2allow is powerful, but it grants whatever the denial requested. A denial that is caused by a misconfiguration, such as a wrong file path or a wrong port, is not a policy problem. Running audit2allow on that denial creates a policy rule that permits the misconfiguration instead of fixing it. The correct approach is to check the file context and the boolean first, and to use audit2allow only when the denial is a genuine missing policy rule .


a. Finding and interpreting the denial

The ausearch -m avc command is the primary tool for finding the denial. The -ts recent flag limits the search to the recent entries. The -c <command> flag filters by the command name. The -exe <path> flag filters by the executable path.

# Find recent AVC denials
sudo ausearch -m avc -ts recent

# Filter by command
sudo ausearch -m avc -c httpd -ts recent

# Filter by executable
sudo ausearch -m avc -exe /usr/sbin/httpd -ts recent

The sealert command translates the denial into a description. The -a flag reads the audit log, and the -l <id> flag shows the details for a specific alert.

# Install the setroubleshoot-server package
sudo dnf install setroubleshoot-server

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

# Show a specific alert
sudo sealert -l <alert-id>

The audit2why command is the translator for a single denial.

# Explain the denial
sudo ausearch -m avc -ts recent | audit2why

The audit2why output shows the reason: a missing type, a missing boolean, or a constraint. The reason determines the fix.


b. The fix sequence: context, boolean, port

The first check is the file context. The ls -Z shows the context. The matchpathcon -V compares the current context to the default. The restorecon -Rv applies the default.

# Check the context
ls -Z /var/www/html/file.txt

# Compare to the default
sudo matchpathcon -V /var/www/html/file.txt

# Fix the context
sudo restorecon -Rv /var/www/html/

The second check is the boolean. The getsebool shows the current value. The semanage boolean -l shows the description. The setsebool -P changes the value persistently.

# Check the boolean
getsebool httpd_can_network_connect

# Toggle the boolean
sudo setsebool -P httpd_can_network_connect on

The third check is the port. The semanage port -l shows the port types. The semanage port -a adds the port to the type.

# Check the port type
sudo semanage port -l | grep http_port_t

# Add the port
sudo semanage port -a -t http_port_t -p tcp 9496

The semanage port -a command is the fix for a service that is configured to listen on a non-standard port. The http_port_t type is the type that the httpd_t domain is allowed to bind to. The port 9496 is not in the default list, so the bind fails. The semanage port -a adds it .


c. The custom policy as the last resort

The audit2allow command generates a policy module from the denials. The -m flag generates the Type Enforcement (TE) source. The -M flag generates the compiled module (.pp). The semodule -i installs the module.

# Generate the policy source
sudo ausearch -m avc -ts recent | audit2allow -m myapp_custom

# Review the source
cat myapp_custom.te

# Generate and compile the module
sudo ausearch -m avc -ts recent | audit2allow -M myapp_custom

# Install the module
sudo semodule -i myapp_custom.pp

The myapp_custom.te file contains the allow rules. The rule format is allow <source_type> <target_type>:<class> { <permissions> };. The rule grants the source type the permissions on the target type. The rule must be reviewed before installation. The audit2allow grants whatever the denial requested, which may be more than the application needs.

The semanage permissive -a <domain> command is the tool for collecting the complete set of denials for a multi-denial application. The domain is set to permissive, the application is exercised, the denials are collected, and the single policy module is generated.

# Set the domain to permissive
sudo semanage permissive -a httpd_t

# Exercise the application
sudo systemctl restart httpd

# Generate the policy
sudo ausearch -m avc -ts recent | audit2allow -M httpd_custom

# Install the policy
sudo semodule -i httpd_custom.pp

# Remove the permissive mode
sudo semanage permissive -d httpd_t

The semanage permissive -d removes the permissive mode. The domain returns to enforcing. The installed policy module covers the denials that were collected.


Complete Example Session

# ============================================
# PART 1: REPRODUCE THE FAILURE
# ============================================

sudo systemctl restart httpd
# Job for httpd.service failed.
# ============================================
# PART 2: FIND THE DENIAL
# ============================================

sudo ausearch -m avc -ts recent
# avc: denied { name_bind } for ... tcontext=...:http_port_t ... tclass=tcp_socket
# ============================================
# PART 3: INTERPRET WITH SEALERT
# ============================================

sudo sealert -a /var/log/audit/audit.log
# SELinux is preventing httpd from name_bind access on the tcp_socket port 9496.
# ============================================
# PART 4: CHECK THE PORT TYPE
# ============================================

sudo semanage port -l | grep http_port_t
# http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
# ============================================
# PART 5: ADD THE PORT
# ============================================

sudo semanage port -a -t http_port_t -p tcp 9496
# ============================================
# PART 6: RESTART THE SERVICE
# ============================================

sudo systemctl restart httpd
# Success.
# ============================================
# PART 7: VERIFY
# ============================================

sudo ss -tlnp | grep 9496
# LISTEN 0 511 *:9496 *:* users:(("httpd",...))
# ============================================
# PART 8: CUSTOM POLICY (LAST RESORT)
# ============================================

sudo ausearch -m avc -ts recent | audit2allow -M myapp_custom
cat myapp_custom.te
sudo semodule -i myapp_custom.pp
# ============================================
# PART 9: PER-DOMAIN PERMISSIVE (MULTI-DENIAL)
# ============================================

sudo semanage permissive -a httpd_t
# Exercise the application, collect denials, generate policy.
sudo semanage permissive -d httpd_t

The nine parts trace the troubleshooting: reproduce, find, interpret, check port, add port, restart, verify, custom policy, and per-domain permissive.


Quick Reference

Finding Denials

CommandPurpose
ausearch -m avc -ts recentRecent AVC denials
ausearch -m avc -c <cmd>Filter by command
sealert -a /var/log/audit/audit.logHuman-readable analysis
audit2whyExplain a denial

The Fix Sequence

OrderCheckCommand
1File contextrestorecon -Rv
2Booleansetsebool -P
3Portsemanage port -a
4Custom policyaudit2allow

Custom Policy

CommandPurpose
audit2allow -m <name>Generate TE source
audit2allow -M <name>Generate compiled module
semodule -i <name>.ppInstall module
semodule -l | grep <name>Verify module loaded

Per-Domain Permissive

CommandPurpose
semanage permissive -a <domain>Set domain permissive
semanage permissive -d <domain>Remove permissive

Best Practices

โœ… Do This:

sudo ausearch -m avc -ts recent
<!-- Find the denial first -->                        # โœ…
sudo sealert -a /var/log/audit/audit.log
<!-- Interpret the denial -->                         # โœ…
sudo semanage port -a -t http_port_t -p tcp 9496
<!-- Fix the port before writing a policy -->         # โœ…

โŒ Don’t Do This:

sudo ausearch -m avc -ts recent | audit2allow -M policy && semodule -i policy.pp
<!-- Run audit2allow without reviewing -->           # โŒ
# Disable SELinux to fix the denial
<!-- Use the fix sequence instead -->                # โŒ
# Assume every denial is a policy problem
<!-- Check context, boolean, port first -->          # โŒ

Common Pitfalls

PitfallWhy It HappensFix
ausearch shows nothingauditd not runningStart auditd
Denial is a file contextFile moved with mvrestorecon -Rv
Denial is a booleanService needs a capabilitysetsebool -P
Denial is a portNon-standard portsemanage port -a
Policy module too broadaudit2allow not reviewedReview .te before install

Real-World Examples

1. Find Denials

sudo ausearch -m avc -ts recent

2. Interpret

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

3. Check Context

sudo matchpathcon -V /var/www/html/*

4. Fix Context

sudo restorecon -Rv /var/www/html

5. Check Boolean

getsebool httpd_can_network_connect

6. Toggle Boolean

sudo setsebool -P httpd_can_network_connect on

7. Add Port

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

8. Generate Policy

sudo ausearch -m avc -ts recent | audit2allow -M myapp_custom

9. Install Policy

sudo semodule -i myapp_custom.pp

10. Per-Domain Permissive

sudo semanage permissive -a httpd_t

Visual

Troubleshooting Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Application fails                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ausearch -m avc -ts recent                  โ”‚
โ”‚  โ†’ Find the denial                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  sealert / audit2why                         โ”‚
โ”‚  โ†’ Interpret the denial                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Check: context โ†’ boolean โ†’ port             โ”‚
โ”‚  โ”œโ”€โ”€ Fix found โ†’ Apply fix                   โ”‚
โ”‚  โ””โ”€โ”€ No fix โ†’ audit2allow                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Review and install custom policy            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Fix Order

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  1. File context                             โ”‚
โ”‚     restorecon -Rv                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  2. Boolean                                  โ”‚
โ”‚     setsebool -P                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  3. Port                                     โ”‚
โ”‚     semanage port -a                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  4. Custom policy                            โ”‚
โ”‚     audit2allow -M                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Find denialsausearch -m avc -ts recent
Interpret denialssealert -a or audit2why
Fix contextrestorecon -Rv
Fix booleansetsebool -P
Fix portsemanage port -a
Generate policyaudit2allow -M
Install policysemodule -i
Per-domain permissivesemanage permissive -a

Key takeaways:

  • The ausearch command finds the denial. The -m avc filter shows the SELinux denials. The -ts recent flag limits the search to the entries after the failure. The sealert and audit2why commands translate the denial into a human-readable explanation .
  • The fix order is context, boolean, port, policy. The file context is the most common cause, followed by a boolean that is off, followed by a port that is not permitted. The custom policy is the last resort for the cases that the first three do not cover .
  • The audit2allow output must be reviewed. The command grants whatever the denial requested. A denial that is caused by a misconfiguration, such as a wrong port or a wrong file path, is not a policy problem. The audit2allow on that denial creates a policy rule that permits the misconfiguration instead of fixing it .
  • The per-domain permissive is for multi-denial applications. The semanage permissive -a <domain> command allows the application to run while logging every denial. The complete set of denials is collected and a single policy module is generated .
  • The semanage port -a is the fix for a non-standard port. The http_port_t type is the type that the httpd_t domain can bind to. The port must be added to the type before the service can bind to it in enforcing mode .

Remember: The troubleshooting is a sequence. The ausearch finds the denial. The sealert interprets it. The context, boolean, and port are the first checks. The audit2allow is the last resort. The policy module is reviewed before installation. The per-domain permissive is the tool for collecting the complete set of denials. The exam tests the commands and the fix order.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!