Check AppArmor Before You Depend on It with aa-enabled
You will finish with a small, reliable check for whether AppArmor is enabled on this machine, and a shell pattern that can tell an ordinary disabled result from a missing or unreadable kernel interface. The examples use the aa-enabled command from AppArmor 4.0.1, installed here as package version 4.0.1really4.0.1-0ubuntu0.24.04.7.
Allow about ten minutes. You need a shell and the AppArmor utilities package. This guide only reads status: it does not load profiles, change policy, restart a service or alter boot settings.
1. Check the ordinary enabled state
Run the command without options:
$ aa-enabled
Yes
The command prints Yes and returns status 0 when AppArmor is enabled. That is the useful human-readable check. It does not mean every profile is loaded or that every application is confined. It answers the narrower question: is the AppArmor security module available and enabled?
Checkpoint: run printf '%s\n' "$?" immediately afterwards. You should see 0 on this machine. The status belongs to the command immediately before it, so do not insert another command first.
2. Use the exit status in a script
Scripts normally do not need to parse the word Yes. Add --quiet and branch on the status:
if aa-enabled --quiet; then
printf '%s\n' 'AppArmor is enabled'
else
status=$?
printf 'AppArmor check failed with status %s\n' "$status" >&2
exit "$status"
fi
With --quiet, aa-enabled writes nothing to standard output. On the installed system the command still returns 0. This makes it suitable for a pre-flight check before starting a service whose security policy is part of its deployment assumptions.
Do not collapse every non-zero result into "AppArmor is disabled". The documented statuses carry different information:
0: AppArmor is enabled.1: AppArmor is not enabled or not loaded.3: the AppArmor control files are not available under/sys/kernel/security/.4: the command lacks enough privilege to read those control files.10: AppArmor is enabled, but it cannot access shared LSM interfaces.64: an unexpected error or condition occurred.
Status 2 is intentionally unused by aa-enabled. Treat unknown values as errors rather than silently continuing.
3. Decide whether shared LSM interfaces are required
Some systems share Linux Security Module interfaces with another security module. The normal check accepts AppArmor when it is enabled even if it does not have exclusive access to those shared interfaces. If your application specifically requires AppArmor to own them, use --exclusive:
$ aa-enabled --exclusive
Yes
$ printf '%s\n' "$?"
0
The exclusive check returns 0 when AppArmor is enabled and has the required exclusive access. It returns 10 when AppArmor is enabled but does not have access to shared LSM interfaces. That is a different result from status 1, so report it accurately in monitoring.
This option is a requirement check, not a switch. It does not make AppArmor exclusive and it does not change the kernel's LSM configuration. Changing that configuration is a boot and security-policy decision outside this command, so do not try to "fix" status 10 by adding arbitrary kernel parameters.
4. Investigate a failed check without changing state
First capture the status with a small case statement:
aa-enabled --quiet
status=$?
case "$status" in
0) printf '%s\n' 'AppArmor enabled' ;;
1) printf '%s\n' 'AppArmor disabled or not loaded' ;;
3) printf '%s\n' 'AppArmor control files unavailable' ;;
4) printf '%s\n' 'Insufficient privilege to read AppArmor control files' ;;
10) printf '%s\n' 'AppArmor enabled without shared LSM access' ;;
64) printf '%s\n' 'Unexpected aa-enabled error' ;;
*) printf 'Unknown aa-enabled status %s\n' "$status" >&2; exit 1 ;;
esac
For status 3, inspect the mount and directory without modifying either:
$ findmnt /sys/kernel/security
$ ls -ld /sys/kernel/security /sys/kernel/security/apparmor 2>/dev/null
For status 4, rerun the same read-only check with the privilege required by your host's security policy:
$ sudo aa-enabled --quiet
$ printf '%s\n' "$?"
sudo is only needed when the command reports that it cannot read the control files. It is not a normal prerequisite, and it does not turn a disabled AppArmor module on. If the command works without elevated privileges, keep the service check unprivileged.
5. Avoid the common false assumptions
An enabled module is not the same as complete policy coverage. After aa-enabled succeeds, a separate audit should establish which profiles are loaded and whether the target process is confined. Do not use a successful result as permission to remove other sandboxing or to assume that a profile has been applied.
Likewise, a status 1 may reflect boot configuration or a kernel without AppArmor support, not a problem that a package reinstall can solve. Status 3 points at the securityfs control interface, while status 4 points at access to it. Keeping those cases separate makes an alert actionable.
The command accepts -h/--help, -q/--quiet, and -x/--exclusive. There is no profile name, configuration file or enable operation to pass to aa-enabled. It is a test command. Profile management belongs to other AppArmor tools and should be reviewed separately before use.
Done means
aa-enabledgave the expected human-readable result.- A script uses
--quietand checks the exit status, not the output text. - Status 1, 3, 4, 10 and 64 are reported as distinct conditions.
--exclusiveis used only when shared LSM access is a real requirement.- No command in this check changed profiles, mounts, boot settings or services.