AppArmor

On this page 8

AppArmor is a Linux Security Module (LSM) that implements mandatory access control by confining individual programs to per-application profiles. Each profile lists the files, capabilities, network access and other resources a program may use, and the kernel denies everything the profile does not allow, even when the process runs as root.

In Linux security, AppArmor is known for its path-based model and readable profile language, which make it easier to adopt than label-based SELinux. It has been part of the mainline kernel since version 2.6.36 and is enabled by default on Ubuntu and Debian, where it confines services, snap packages and container runtimes.

How AppArmor enforces mandatory access control

Standard Unix permissions are discretionary access control (DAC): the owner of a file decides who may access it, and root bypasses almost every check. AppArmor adds a second, independent check through LSM hooks in the kernel, so an operation succeeds only if both DAC and the AppArmor profile allow it.

A profile attaches to a program by its executable path, for example /usr/sbin/cupsd. When that binary is executed, the kernel places the new process under the profile, and every later file open, socket creation or capability use is compared with the profile’s rules. Processes without a matching profile run unconfined and are limited only by normal permissions.

Because rules name file paths rather than inode labels, AppArmor needs no filesystem relabeling and works on any filesystem. The same design creates its main weakness: a file reachable through two different paths may receive two different decisions.

Profile structure and rule types

Profiles live in the /etc/apparmor.d directory, are compiled by apparmor_parser and are loaded into the kernel at boot. A profile combines shared abstractions, such as abstractions/base for libraries every program needs, with rules specific to the application.

Rule typeExampleWhat it controls
File rule/etc/nginx/nginx.conf r,Read, write, append, lock, link and memory-map access
Execute rule/usr/bin/gzip ix,How a child program is confined when executed
Capability rulecapability net_bind_service,Use of specific root privileges
Network rulenetwork inet stream,Socket families and types
Signal and ptracesignal send set=term,Inter-process control
Deny ruledeny /etc/shadow r,Explicit refusal that overrides allows
Common AppArmor rule types

Execute rules deserve special care. The modes ix (inherit the current profile), px (switch to the program’s own profile), cx (switch to a child profile) and ux (run unconfined) decide whether confinement survives an exec. Granting ux to a shell effectively disables the whole profile.

AppArmor profile modes

Every loaded profile runs in a mode that defines what happens when a process attempts a disallowed action. Administrators switch modes per profile without rebooting.

ModeDisallowed actionLoggedTypical use
EnforceBlockedYes, as DENIEDProduction
ComplainAllowedYes, as ALLOWEDDeveloping a new profile
KillBlocked and process killedYesStrict containment
Unconfined flagAllowedNoPlaceholder profiles that only attach
DisabledProfile not loadedNoTroubleshooting
AppArmor profile modes and their effect

Denials appear in the kernel audit log with the text apparmor="DENIED", the profile name, the operation and the requested path. Reading these records is the fastest way to diagnose an application that fails only under confinement.

AppArmor compared with SELinux and other controls

AppArmor and SELinux are the two dominant MAC systems on Linux, and a kernel normally runs only one of them as the major LSM. Seccomp, Linux capabilities and PAM address different layers and complement either one.

MechanismModelScopeDefault on
AppArmorPath-based profilesSelected programsUbuntu, Debian
SELinuxLabels and type enforcementWhole systemRHEL, Fedora, Android
SeccompSystem call filterOne process treeContainer runtimes, browsers
Linux capabilitiesSplit root privilegesPer threadAll distributions
PAMAuthentication modulesLogin and servicesAll distributions
AppArmor and related Linux security mechanisms

The practical trade-off is clear. AppArmor offers faster adoption and readable profiles for confining a few exposed services, while SELinux offers finer, system-wide control and multi-level security at the cost of a steeper learning curve.

Building and maintaining AppArmor profiles

The usual workflow is learn, review, enforce: run the program in complain mode, exercise all its features, convert the logged events into rules and then switch to enforce mode.

ToolPurpose
aa-statusLists loaded profiles, their modes and confined processes
aa-genprofCreates a new profile interactively from observed behavior
aa-logprofTurns logged events into proposed rule updates
aa-complainSwitches a profile to complain mode
aa-enforceSwitches a profile to enforce mode
apparmor_parser -rReloads a profile after manual editing
AppArmor administration tools

Generated rules must be reviewed by a person. Learning tools tend to suggest broad recursive globs that match whole directory trees, which silently turn a tight profile into a nearly meaningless one.

Limitations and common mistakes

  • Only profiled programs are confined. A system with a handful of profiles still runs most processes unconfined.
  • Path ambiguity through bind mounts, chroots and namespaces can lead to unexpected denials or gaps.
  • Leaving a profile in complain mode indefinitely gives a false sense of protection, because nothing is blocked.
  • Disabling AppArmor globally to fix one application removes protection from every confined service; adjusting the single profile is the correct fix.
  • Moving a program to a different install path detaches it from its profile without any warning.

Explained without jargon

Normally, a program on Linux can do anything its user account is allowed to do. AppArmor gives selected programs a personal rulebook that is stricter than that.

Picture a hotel where staff cards open certain rooms. AppArmor is like giving the window cleaner a card that opens only the windows, even if the cleaner is also the manager. If an attacker takes over the window cleaner, the card still opens nothing else, so the damage stays small.

A typical use case

A company runs a public web server on Ubuntu with a PHP application that handles file uploads. The security team worries that a vulnerability in the application could let an attacker read configuration files or start a shell.

An administrator writes a profile for the PHP-FPM workers that allows reading the application directory, writing only to the upload folder and connecting only to the local database socket. After two weeks in complain mode, aa-logprof shows three legitimate actions missing, which are added before switching to enforce mode. Months later, an attacker exploits an upload bug and tries to run /bin/sh and read /etc/shadow; both attempts produce DENIED entries, and the compromise stays contained to the upload folder.