Runbook: MAC denial - restore service access
1 · Prerequisites
Confirm every item is in place before any state change.
2 · Pre-checks
Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.
- · Identify the affected service and the symptom
- · Capture the MAC denial log (ausearch, journalctl)
- · Determine whether SELinux or AppArmor is in use
3 · Procedure
Execute each step in order. Verify the expected output of a step before moving to the next.
- 1Diagnose: read AVC denials or AppArmor logs
- 2Identify the cause: mislabel, port, capability, profile gap
- 3Apply the right fix: restorecon, semanage, audit2allow, profile update
- 4Verify the service works in enforcing mode
- 5Document the fix and the policy change
4 · Verification
Confirm the procedure actually fixed the problem.
- ✓The failing operation succeeds
- ✓No new MAC denials in the audit log
- ✓MAC is still in enforcing mode
- ✓The fix is documented and reviewable
5 · Rollback
If verification fails, undo the procedure in reverse order.
- ↶Put the domain in permissive mode if the fix breaks other services
- ↶Restore the previous policy module from backup
- ↶Reload the previous AppArmor profile
- ↶Reload the previous SELinux policy module and confirm with semodule -l; for AppArmor, apparmor_parser -R the new profile and -a the previous one, then confirm with aa-status
6 · Escalation
When the runbook isn't enough, contact:
- · If the cause is a missing rule in the upstream policy, escalate to distribution or upstream
- · If a third-party application needs policy changes that affect security, escalate for review
- · If the same denial occurs repeatedly, escalate for permanent fix
- · If MAC was disabled to recover, escalate for re-enabling
This runbook restores service access when MAC (SELinux or AppArmor) is blocking legitimate operations. The procedure differs by cause; the diagnosis step is the same.
When to use this runbook
Use this runbook when:
- A service is failing with permission denied.
- AVC denials appear in the audit log.
- AppArmor denials appear in
journalctl -k. - A recent change (deployment, config, or upgrade) is suspected.
Inputs
Gather before starting:
- The affected service and the error message.
- Recent changes (deploy, config edit, system upgrade).
- The MAC mode (sestatus or aa-status).
Procedure
Step 1: Verify MAC is the cause
# SELinux
sestatus
sudo ausearch -m avc -ts recent
# AppArmor
aa-status
sudo journalctl -k -n 20 | grep apparmorIf there are no recent MAC denials, MAC is not the cause. Investigate other layers.
Step 2: For mislabeled files (SELinux)
ls -lZ <file>
sudo restorecon -v <file>Verify:
# Re-run the failing operation
sudo systemctl restart <service>
sudo ausearch -m avc -ts recentStep 3: For missing port types (SELinux)
sudo ausearch -m avc -ts recent | grep tclass=port
sudo semanage port -a -t <type> -p <tcp|udp> <port>Common types: http_port_t, https_port_t,
unreserved_port_t (for high ports).
Step 4: For policy gaps (SELinux)
Generate a policy module:
sudo ausearch -m avc -ts recent | audit2allow -M <name>
cat <name>.te # REVIEW before installing
sudo semodule -i <name>.ppAlways review the .te file before installing. The policy module allows the specific actions observed; reject anything that grants more access than the application legitimately needs.
Step 5: For AppArmor profile gaps
For a new application:
sudo aa-complain /path/to/binary
# Run the application
sudo aa-logprofFor an existing profile that needs more access:
sudo aa-logprofReview each suggested change. Edit the profile manually if you need fine control.
Step 6: For debugging (temporary)
# SELinux: make a single domain permissive
sudo semanage permissive -a <domain>
# AppArmor: switch a profile to complain
sudo aa-complain /path/to/binaryThese are diagnostic steps. They log denials but allow them. Use to confirm MAC is the cause, then fix properly.
Step 7: Verify
# Re-run the failing operation
sudo systemctl restart <service>
curl ... # or whatever was failing
# Verify no new denials
sudo ausearch -m avc -ts recent
sudo journalctl -k -n 20 | grep -E 'apparmor|avc'Step 8: Document
MAC DENIAL FIX
==============
Service: <service>
Date: 2026-08-09
Symptom: <what was failing>
Diagnosis: <mislabel | port | policy gap | profile gap>
Fix applied: <restorecon | semanage | audit2allow | profile update>
Verification: <curl succeeds, no new denials>
Policy review: <reviewed by, accepted, etc.>
Common patterns
| Symptom | Likely cause | Fix |
|---|---|---|
| New file, service cannot read | Mislabel (SELinux) or profile (AppArmor) | restorecon / profile update |
| Service cannot bind to port | Missing port type (SELinux) or network rule (AppArmor) | semanage port / profile update |
| Service cannot connect out | Boolean (SELinux) or network rule (AppArmor) | setsebool / profile update |
| Recent upgrade, app fails | Policy update changed access | audit2allow / aa-logprof |
| Many denials for same source | Application legitimately needs more | Generate policy module |
Escalation
Escalate when:
- The fix requires changes to upstream policy (escalate to distribution maintainers).
- A third-party application needs policy changes that affect security (security review).
- The same denial occurs repeatedly (permanent fix).
- MAC was disabled to recover (must be re-enabled).
Bring: affected service, denial log, attempted fix, recommendation.