Skip to main content
RunBook Academy

← All runbooks in Linux

high riskservice affecting~30 min

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.

  1. 1Diagnose: read AVC denials or AppArmor logs
  2. 2Identify the cause: mislabel, port, capability, profile gap
  3. 3Apply the right fix: restorecon, semanage, audit2allow, profile update
  4. 4Verify the service works in enforcing mode
  5. 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

Read-only / Safesestatus
# SELinux
sestatus
sudo ausearch -m avc -ts recent

# AppArmor
aa-status
sudo journalctl -k -n 20 | grep apparmor

If there are no recent MAC denials, MAC is not the cause. Investigate other layers.

Step 2: For mislabeled files (SELinux)

Configuration changels
ls -lZ <file>
sudo restorecon -v <file>

Verify:

Service impact possiblesystemctl restart
# Re-run the failing operation
sudo systemctl restart <service>
sudo ausearch -m avc -ts recent

Step 3: For missing port types (SELinux)

Configuration changeausearch
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:

Read-only / Safeausearch
sudo ausearch -m avc -ts recent | audit2allow -M <name>
cat <name>.te        # REVIEW before installing
sudo semodule -i <name>.pp

Always 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:

Service impact possibleaa-complain
sudo aa-complain /path/to/binary
# Run the application
sudo aa-logprof

For an existing profile that needs more access:

Read-only / Safeaa-logprof
sudo aa-logprof

Review each suggested change. Edit the profile manually if you need fine control.

Step 6: For debugging (temporary)

Service impact possiblesemanage permissive
# SELinux: make a single domain permissive
sudo semanage permissive -a <domain>

# AppArmor: switch a profile to complain
sudo aa-complain /path/to/binary

These are diagnostic steps. They log denials but allow them. Use to confirm MAC is the cause, then fix properly.

Step 7: Verify

Service impact possiblesystemctl restart
# 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

SymptomLikely causeFix
New file, service cannot readMislabel (SELinux) or profile (AppArmor)restorecon / profile update
Service cannot bind to portMissing port type (SELinux) or network rule (AppArmor)semanage port / profile update
Service cannot connect outBoolean (SELinux) or network rule (AppArmor)setsebool / profile update
Recent upgrade, app failsPolicy update changed accessaudit2allow / aa-logprof
Many denials for same sourceApplication legitimately needs moreGenerate 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.

References

  1. AppArmor documentation - profiles, complain mode and denials
  2. getenforce(8) - reading the SELinux enforcement mode