Home / Alt manpages / aa-status(8)

  • aa-status(8)
  • Admin command
  • linux

Read AppArmor policy state safely with aa-status

You will check whether AppArmor is enabled, inspect the loaded policy set, choose a human or machine-readable report, and distinguish a permissions problem from a disabled or empty policy set. Allow about ten minutes. The examples target AppArmor 4.0.1, as supplied by the Ubuntu package installed on this machine.

1. Check the installed command

Start by confirming which executable will run and which package version provides it. This is an inspection task, so the first two commands do not need elevated privileges.

$ command -v aa-status
/usr/sbin/aa-status
$ dpkg-query -W -f='${Package} ${Version}\n' apparmor
apparmor 4.0.1really4.0.1-0ubuntu0.24.04.7

The installed manual is for AppArmor 4.0.1 and describes aa-status as a report of the current confinement state. Option names and output details can differ in older distributions, so keep the local manual as the authority when a packaged version is not this one.

Checkpoint

You have confirmed the binary and package version. If command -v finds nothing, install or repair the AppArmor utilities through your normal package-management process before continuing.

2. Test only whether AppArmor is enabled

Use --enabled when a script only needs a yes-or-no test. It returns a status rather than a report of every profile.

$ aa-status --enabled
$ printf 'aa-status exit status: %s\n' "$?"
aa-status exit status: 0

On the installed version, status 0 means AppArmor is enabled and policy is loaded. The manual defines status 1 as not enabled or not loaded, status 2 as enabled with no policy loaded, status 3 as missing AppArmor control files under /sys/kernel/security/, status 4 as insufficient privilege, and status 42 as an internal error. Treat these values as distinct diagnostics in a health check.

Do not write a test that looks only for text on standard output. The useful result from --enabled is its exit status. A shell check can be concise:

if aa-status --enabled; then
    echo 'AppArmor is enabled with policy loaded'
else
    status=$?
    printf 'AppArmor check failed with status %s\n' "$status" >&2
fi

3. Run the full report with the required privilege

For profile and process details, run aa-status through sudo. The manual says the command must be run as root to read the loaded policy state. The default report is the same as --verbose.

$ sudo aa-status
apparmor module is loaded.
110 profiles are loaded.
102 profiles are in enforce mode.
8 profiles are in complain mode.
Out of 129 processes running:
13 processes have profiles defined.
8 processes have profiles in enforce mode.
5 processes have profiles in complain mode.

The numbers above are the manual's sample, not a prediction for your host. Profile counts, process counts and modes change as services start, stop and reload. Look for the shape of the report rather than copying expected numbers.

A non-root run on this machine prints You do not have enough privilege to read the profile set. and exits with status 4. That is a permissions result, not evidence that the AppArmor module is disabled.

Checkpoint

Run the command once with sudo and record whether the report says that the module is loaded, how many profiles are loaded, and whether any are in complain mode. No policy is changed by this command.

4. Ask for one count when a script needs it

The individual legacy options are useful for a single number: --profiled counts loaded policies, --enforced counts enforcing policies, and --complaining counts non-enforcing policies. The related --kill, --prompt, --special-unconfined and --process-mixed options report narrower policy or process categories.

$ sudo aa-status --enforced
# one host-specific integer is printed here

The number is host-specific, so do not treat the comment above as literal output. Keep the command's exit status as well as its output: a failed read can leave you with no number and status 4. If your script needs a count for a selected data set, the newer form is explicit:

$ sudo aa-status --show=profiles --count
102

--show accepts profiles, processes or all; all is the default. --count prints only counts for the selected information and implies quiet output. Do not combine several report options and assume they will be merged: the manual specifies one argument at a time.

5. Use JSON for monitoring and automation

For a program rather than a person, request JSON and parse it with a real JSON parser. --json is intended for machine consumption; --pretty-json contains the same kind of data with human-readable formatting.

$ sudo aa-status --json > /tmp/aa-status.json
$ jq . /tmp/aa-status.json
$ printf 'aa-status exit status: %s\n' "$?"
aa-status exit status: 0

The temporary file is only an example output location. It is not policy configuration and can be removed after inspection. Avoid extracting values with grep: profile names and process entries can contain characters that make line-oriented parsing fragile.

AppArmor's upstream project has fixed malformed JSON cases in the 4.x development line, including output selected with --show. That history is another reason to parse the output and check the command's exit status rather than trusting a hand-written text pattern. If an older distribution produces invalid JSON, check its package version and use its local release guidance before building automation around it.

6. Narrow a report with filters

Filters reduce displayed profiles or processes without changing policy. They take POSIX regular expressions. For example, this lists enforcing profiles only:

$ sudo aa-status --show=profiles --filter.mode='^enforce$'
# profile entries for this host are printed here

Use --filter.profiles for the confining profile name, --filter.pid for process IDs, and --filter.exe for executable names. Quote the expression so the shell does not interpret special characters. A filter that matches nothing is not proof that policy is absent; it may simply be too narrow.

When a report is unexpectedly empty, remove filters first, then try sudo aa-status --show=all. This separates a matching mistake from a policy or permissions problem.

7. Diagnose failures without changing AppArmor

aa-status reads the kernel's AppArmor control files and process information. It does not load, unload, enforce or complain a profile. Do not respond to a surprising count by editing a profile or restarting a service until you have established the failure category.

  • Status 1 means AppArmor is not enabled or loaded.
  • Status 2 means AppArmor is enabled but no policy is loaded.
  • Status 3 means the control files are unavailable under /sys/kernel/security/.
  • Status 4 means the caller lacks enough privilege to read the control files.
  • Status 42 indicates an internal error.

First rerun the same command with sudo. If it still fails, inspect the security filesystem and service state using your distribution's normal diagnostic tools. Do not mount filesystems, reload profiles or restart production services merely to make a status command return zero. Those are operational changes with their own outage and policy risks.

There is no undo action for the examples in this guide: they read state and write, at most, a temporary report under /tmp. If you created that report and no longer need it, remove that exact file:

$ rm -- /tmp/aa-status.json

Done means

  • You confirmed the installed aa-status and AppArmor package version.
  • You used --enabled when only an exit-status health check was needed.
  • You used sudo for profile and process details, and recognised status 4 as a privilege failure.
  • You selected counts, JSON output or filters for the job instead of scraping a verbose report.
  • You treated the output as a read-only snapshot and made no policy or service changes.