From AppArmor
Jump to: navigation, search

AppArmor Policy Table of Contents

AppArmor Policy Basics Table of Contents


AppArmor policy is a variant of Domain Type Enforcement (DTE), all policy is written from a domain (from a tasks view) model. This makes it easy to target policy to specific applications or users. AppArmor does not require a total system policy, making it is easy to selectively deploy in just a few hours.

AppArmor policy is written in simple text based rules and then is compiled and loaded into the kernel for enforcement. The majority of enforcement is done by the kernel but some trusted daemons may be responsible for enforcing certain pieces of policy (eg. dbus daemon, x server, ...)


The base unit of AppArmor confinement is a profile. Profiles have a few main components

  • Name (identity)
  • Attachment (optional)
  • Flags (optional)
  • Preamble
  • Body
    • Rules (rights and privileges a.k.a. authority)
  • Comments
  • Includes
  • Variables
  • Conditionals
 # preamble comment
 include <tunables/global>
profile example /bin/attachment flags=(complain) { # a comment include <abstractions/base>
file r /bin/example, }


The name of the profile is its identity and is how the profile is referenced within policy. It is generally good practice to give the profile a name that has meaning to the user for the application or user that is being confined. That is it is better to call a profile to confine the firefox web browser "firefox" or "browser" than it is to call it "app_1" or "xyz".

Like file path names, profile names can be hierarchical, but using the // sequence as a separator. Eg. The profile


can have a child profile


While it is possible to create profile names that match an applications installation path, and can be used as the profile attachment (see below), it is not recommended for several reasons.

  • They result in longer names that may be harder for a user to scan on introspection (eg using ps -Z), especially when globbing is used.

    eg. 1) /usr/bin/firefox vs. firefox
    eg 2) /usr/lib/firefox/firefox{,*[^s][^h]} vs. firefox

  • They result in names that are harder for user to parse/read when stacking or policy namespaces are used.

    eg.) firefox//&:user:guest vs. /usr/lib/firefox/firefox{,*[^s][^h]}//&:user:guest

  • File system paths are specific to an install or distro and can change, requiring the profile name to be updated to match the change, or the name will be misleading or even worse result in mediation not being applied.

    eg. /usr/lib/firefox { } was used in the past and now it is common to use /usr/bin/firefox { }

  • File system path based names when changed require updating not only the profile for the application that has changed locations, but also rules controlling inter-task communication in other profiles.
    eg. cups needs to communicate with 3rd party drivers that are have a separate confinement profile.

    unix peer=(label=/usr/sbin/cupsd//third_party,

    if their location changes the cups profile would have to be updated for their new location, say /usr/opt

    unix peer=(label=/usr/opt/cupsd//third_party,

    where if the profile was give a recommended style name

    eg. cups_third_party

    the rule would not have to be changed

The full specification of what is allowed as part of a profile name can be found ??profile spec??


The attachment specification provides a matching pattern that is used against a file system executable name to help determine if the profile should be used to confine that executable. The attachment must be a valid filesystem path and may contain apparmor globbing for pattern matches.

The attachment can be used as a profile name (and is by default if the profile keyword is not used when declaring the profile), however this is not recommended as it results in long profile names, that do not conform well to all interfaces and uses of them (eg ps -Z reporting the profile name can't handle some characters). It also results in brittle policy as application location varies by version or distribution, and other parts of the policy may refer to a profile by name, meaning that location changes require updating all uses of the name in policy.


There are several flags that can modify a profiles behavior, perhaps the most important one being

  • complain

which turns off enforcement of the profiles rules, and audits but allows any behavior not allowed by the profile's rules. This flag is used to allow rapid profile development in trusted environments, by capturing and generating rules based on the logged behavior.


The mode of the profile determines how the profile rules are being applied.

  • enforce - the default flag means the profiles rules are being applied
  • complain - check the profile rules but only audit accesses that are not allowed (see profile flag).
  • unconfined - a special mode in which profile rules are not applied. (see unconfined and default profiles)
  • mixed - a special mode used in profile stacks when multiple enforcement modes are present.

The mode of the profile is reported by task queries like ps -Z

: ps -Z
LABEL                             PID TTY       TIME CMD
unconfined                       4265 pts/0    00:00 bash
unconfined                      31594 pts/0    00:00 ps
pidgin (enforce)                 3156 ?        23:54 pidgin


Begins with open brace { and ends with matching }


??? declarative - order doesn't matter various mediation types ??? reference out to policy reference manual


Line based comments begin with #


include based on Include lookup path

 include < >

relative include

 include " "


boolean variables


multi-valued variables


multipass evaluation

Special Profiles

AppArmor has a few special profiles, and conventions around profile names.

unconfined profile

The unconfined profile is a special profile that does not enforce any confinement (it is in the unconfined mode). It is often used as the default profile that a system is brought up in, and will apply to most tasks in the system when a targeted policy is used.

default profile

The default profile, is the profile the system is brought up in. It can be specified as part of the boot parameters, and defaults to the unconfined profile. Until policy is loaded it is just a profile name in unconfined mode. The default profile allows specifying a different profile than unconfined from boot that can be replaced and enforced once policy is loaded (the unconfined profile will never be enforced).

null-XXX learning profiles

When in complain mode and a domain transition is encountered a special place holder profile is created and used to represent the new domain until the policy can be updated to cover the transition. These learning profiles have no rules and start with the reserved prefix


the XXX is some undefined value. It may be a unique number like


or it could be the name of the executable that is missing a domain transition


null- learning profiles are always created as a child of the profile that the domain transition was undefined in that resulted in their creation, so the will appear like


Since null- profiles have no rules, including domain transitions defined, any executable spawned by them will receive its own null- profile that is a child of the null profile. Eg.


Reserved Prefixes

Some prefixes are reserved to indicate special behavior/use so that the tools can properly identify profile semantics and report them to the user.

  • user_
  • role_
  • null-

Reserved Namespaces

  •  :user:
  •  :role: