From Bauman National Library
This page was last modified on 17 January 2019, at 15:45.
AppArmor logo.png
Original author(s) Immunix
Developer(s) SUSE
Initial release 1998; 25 years ago (1998)
Stable release
2.13.0 / 15 April 2018; 4 years ago (2018-04-15)
Preview release
Repository {{#property:P1324}}
Written in C, Perl, C++
Operating system Linux
Type System software
License GNU General Public Licence

AppArmor ("Application Armor") is a security module of Linux kernel that limits the capabilities of programs by using their individual profiles. Profiles can grant or deny programs access to the network, raw sockets, read, write, or execute permissions on specific system paths. AppArmor complements DAC (discretionary access control) with mandatory access control (MAC). It is included in the Linux kernel since version 2.6.36.


AppArmor is a Linux security system based on mandatory access control. AppArmor restricts individual programs to a set of files, capabilities, and access to the network. Such restrictions are called AppArmor policies for a program or simply a profile. AppArmor complements the discretionary Unix access model: if access has been allowed by the system, the final decision rests with AppArmor, which verifies the permissions with its control and access policies. AppArmor supports a profile learning mode that helps users write and update security policies. The training mode allows you to create and configure a profile using the example of a running program. After full training there is a transition to the compulsory execution mode. Although the result of creating such a profile may be more “soft” than fully manual configuration for a specific environment and application, the training mode requires much less effort and knowledge required to use AppArmor.

AppArmor differs from some other MAC systems on Linux: it is path-based, it allows mixing of enforcement and complain mode profiles, it uses include files to ease development, and it has a far lower barrier to entry than other popular MAC systems.

AppArmor is an established technology first seen in Immunix and later integrated into Ubuntu, Novell/SUSE, and Mandriva. Core AppArmor functionality is in the mainline Linux kernel from 2.6.36 onwards; work is ongoing by AppArmor, Ubuntu and other developers to merge additional AppArmor functionality into the mainline kernel.[Reference 1]


  • AppArmor's predecessor SubDomain began life as a Grad project
  • 1998/1999 WireX founded by Crispin Cowan to commercialize SubDomain, and develop other security extensions to Linux. WireX produced Immunix a secure Linux distribution based on Red Hat Linux using StackGuard, FormatGuard, and SubDomain. WireX involved in creation of LSM.
  • In early 2004 WireX rebranded to Immunix and then dropped its Linux distribution, refocusing instead on providing SubDomain for SuSE linux.
  • SubDomain rewritten to use LSM, despite WireX involvement in creating the LSM the porting of AppArmor to the LSM was done late after the LSM was created for political reasons. This meant that LSM was less than optimal for AppArmor and the feedback that could have improved the LSM during its development never occured.
  • A YaST GUI implemented for SubDomain on SuSE linux.
  • In May 2005 Novell acquired Immunix and rebranded SubDomain as AppArmor and began cleaningup/rewritting the code for upstream linux kernel inclusion.
  • AppArmor 2.0.1 released - based on SubDomain 2.0 code with AppArmor rebranding.
  • AppArmor 2.1 released. Large portions of the kernel module where rewritten to use a new custom dfa based matching engine (dropping pcre for licencing reasons) and with name lookup being based on a large patch to vfs and LSM which passed the vfsmnt through into all of the relevant LSM hooks).
  • In October 2007 Novell layed-off most of the development team working on AppArmor, and re-assigned the remaining developers putting AppArmor in development mode.
  • June 2008 Novell releases AppArmor 2.3 released using another iteration of the vfs patches, and extension to the matching engine.
  • In May 2009 Canonical Inc. picks up AppArmor maintenance and development.
  • Fall 2009 AppArmor 2.4 released. Based on a large update/rewrite to of the AppArmor 2.3 kernel module, it was updated to for creds, and the LSM path_security hooks.
  • July 2010 AppArmor security module merged into security-next tree. Core functionality accepted into official Linux 2.6.36 kernel. A few compatibility small patches are needed to work with current userspace.[Reference 2]
  • AppArmor was enabled in Solus Release 3 on 2017/8/15.[Reference 3]

Distributions with AppArmor

Distributions that include AppArmor: [Reference 4]

  • Annvix
  • Arch Linux
  • Debian
  • Gentoo
  • openSUSE (installed by default)
  • Pardus Linux
  • PLD
  • Ubuntu (installed by default)

Installing AppArmor

Source layout

AppArmor consists of several different parts:

binutils/ - source for basic utilities written in compiled languages

changehat/ - source for using changehat with Apache, PAM and Tomcat

common/ - common makefile rules

desktop/ - empty

kernel-patches/ - compatibility patches for various kernel versions

libraries/ - libapparmor source and language bindings

parser/ - source for parser/loader and corresponding documentation

profiles/ - configuration files, reference profiles and abstractions

tests/ - regression and stress testsuites

utils/ - high-level utilities for working with AppArmor

Building and Installing AppArmor Userspace

To build and install AppArmor userspace on your system, build and install in the following order. Some systems may need to export various python-related environment variables to complete the build. For example, before building anything on these systems, use something along the lines of:

$ export PYTHONPATH=$(realpath libraries/libapparmor/swig/python)
$ export PYTHON=/usr/bin/python3
$ export PYTHON_VERSIONS=python3


$ cd ./libraries/libapparmor
$ sh ./
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
$ make
$ make check
$ make install

an additional optional argument to libapparmor's configure is --with-ruby, to generate Ruby bindings to libapparmor.

Binary Utilities:

$ cd binutils
$ make
$ make check
$ make install


$ cd parser
$ make		# depends on libapparmor having been built first
$ make check
$ make install


$ cd utils
$ make
$ make check
$ make install

Apache mod_apparmor:

$ cd changehat/mod_apparmor
$ make		# depends on libapparmor having been built first
$ make install

PAM AppArmor:

$ cd changehat/pam_apparmor
$ make		#depends on libapparmor having been built first
$ make install


$ cd profiles
$ make
$ make check	# depends on the parser having been built first
$ make install


AppArmor profiles are plain text files that are located in /etc/apparmor.d/. The profile files are named according to the full path to the executable they manage, with the replacement of the "/" with ".". For example /etc/apparmor.d/ is the AppArmor profile for the /bin/ping command.

AppArmor profiles have 2 execution modes:

  1. Complaining/Learning: profile violations are resolved and stored in the log. Useful for testing and developing new profiles.
  2. Enforced/Confined: enforce policy profile, it also records the violation in the log.

There are two main types of rules used in a profile:

  1. Path entries: describes which files the application has access to on the filesystem.
  2. Capability entries: determine which permissions a restricted process may use.

Example for /etc/apparmor.d/

#include <tunables/global>
/bin/ping flags=(complain) {
  #include <abstractions/base>
  #include <abstractions/consoles>
  #include <abstractions/nameservice>

  capability net_raw,
  capability setuid,
  network inet raw,
  /bin/ping mixr,
  /etc/modules.conf r,
  1. #include <tunables/global>: includes operators from another file. This allows operators belonging to multiple applications to reside in a single common file.
  2. /bin/ping flags=(complain): flags that set the training mode
  3. capability net_raw,: allows the application to access features of CAP_NET_RAW Posix.1e.
  4. /bin/ping mixr,: allows the application to read and execute the file.

The profile should restarted after editing.

Creating a profile

  1. Development of a test plan. The test plan should be divided into small text blocks. Each test block should have a brief description and a list of execution steps. Some standard text blocks:
    1. Program startup.
    2. Stopping the program.
    3. Program restarting.
    4. Test all commands supported by the init script.
  2. Create a new profile: Use 'aa-genprof' to create a new profile. Command in terminal:
     sudo aa-genprof executable 
  3. To get your new profile as part of the apparmor-profiles package, log the problem in Launchpad for the AppArmor package.
    1. Include your test plan and test blocks.
    2. Attach your new profile to the reported issue.

Updating profiles

If the program behaves incorrectly, analyze the messages in the log files. Aa-logprof can be used to scan AppArmor log files to check messages, review (analyze) them, and update profiles. The command in the terminal:
 sudo aa-logprof 

AppArmor is guided by the principle of "everything that is not allowed is forbidden", so when there is no corresponding rule in the profile, the action is not allowed.

AppArmor Language

AppArmor profile Language

Profiles begin with the name of the profile followed by an optional flags field, then an opening { followed by the rules for the profile and is finished by a closing } If the profile name does not begin with a / then the keyword profile should be prepended.[Reference 5] Eg:

  /usr/bin/firefox {
    # profile contents

 /usr/bin/firefox flags=(complain) {
    # profile contents

 profile /usr/bin/ {
    # profile contents

 profile user1 {
    # profile contents

Profile names can contain file rule globbing characters to allow them to apply to multiple executables.


Comments are line oriented and begin with a #. Text following a '# to the end of the line is ignored (with the exception of the #include rule). Eg:

 #  Comment 1
 #  Comment 2

 profile example {  # comment 3
    # comment 4
    /home/foo rw,  # comment at the end of a file rule

Include Rules

Policy files can include other files to share text segments. AppArmor includes follow the C include convention. They start with #include followed by either < > for text chucks relative to a set include directory or " " for files relative to the current file. The # is optional and shouldn't be used in newer profiles. Eg:

 #include <file>
 #include “a/relative/path/file”
 include <file>

#include conflicts with commenting rules and takes precedence. The # and include must not be separated from the include with white space otherwise it is considered a comment

 # include is a comment
 #include <file>

Child profiles

A profile can contain children profiles. Child profiles can be used to confine an application in a special way, or when you want the child to be unconfined on the system, but confined when called from the parent. Eg:

 /parent/profile {
     /path/to/child1 cx -> child1,
     /path/to/child2 cx,
     /path/to/* cx,           # for * matching child3 will transition to child3,
                              # child4, child5, ... will transition to /path/to/child*
                              # if matching child profile does not exist will fail
     /another/path/to/* cx -> child1,        # send all matching execs to child1
     profile child1 {
     profile /path/to/child2 {
     profile /path/to/child3 {
     # generic fall back profile
     profile /path/to/child* {

Network Rules

AppArmor currently supports course grained access to networking via network rules. For example, a network daemon might need:

 /profile {
   network inet dgram,
   network inet stream,

Or a packet analyzer might need:

 /profile {
   network raw,
   network packet,

File rules

File rules control how files are accessed and only occur within a profile. They consist of a pathname, a permission set and are terminated by a comma. They can be written with either the permission first or the pathname first, though the convention it to list the path first. A valid pathname always begins with a /. Eg:

 /profile {
    /path/to/file  rw,   # file rule beginning with a pathname (convention)
    rw /path/to/file2,   # file rule beginning with permissions
    /path/to/file3       # file rule split over multiple lines

File rules can contain special globbing characters that allow matching to multiple files.

File Globbing

AppArmor uses a file globbing syntax similar to that used by the bash shell. Globbing is not standard full regular expression syntax, but instead uses a few characters known as wild cards. The AppArmor wildcards have slightly different semantics than that of bash

  • * - match zero or more characters at the directory level. When looking at the path as a string this will match every character except /.
  • ** - match 0 or more characters over multiple directory levels
  •  ? - match a single character that is not /
  • {} - alternation - a comma separated list of alternate strings that can be matched. An empty string is allowed and means the empty string is a viable alternative
  • [] - character class
  • [^] - inverted character class

File Globbing examples:

/dir/file - match a specific file

/dir/* - match any files in a directory (including dot files)

/dir/a* - match any file in a directory starting with 'a'

/dir/*.png - match any file in a directory ending with '.png'

/dir/[^.]* - match any file in a directory except dot files

/dir/ - match a directory

/dir/*/ - match any directory within /dir/

/dir/a*/ - match any directory within /dir/ starting with a

/dir/*a/ - match any directory within /dir/ ending with a

/dir/** - match any file or directory in or below /dir/

/dir/**/ - match any directory in or below /dir/

/dir/**[^/] - match any file in or below /dir/

/dir{,1,2}/** - match any file or directory in or below /dir/, /dir1/, and /dir2/

File permissions

The following file permissions are supported:

  • r - read
  • w - write
  • a - append (implied by w)
  • x - execute
  • m - m - memory map executable
  • k - lock (requires r or w, AppArmor 2.1 and later)
  • l - link

The owner keyword can be used as a qualifier making permission conditional on owning the file (process fsuid == file's uid).

 owner /foo rw,

The following are in development:

  • create (implied by w)
  • delete (implied by w)
  • chown - change ownership (implied by w)
  • chmod - change mode (implied by w)

Execute permissions

AppArmor distinguishes between the different ways a file may be executed. Because a new process is created when executing a file, the process is said to transition to another (possibly same) profile across execute.

The base execute permission are::

  • ix - the new process should run under the current profile
  • cx - the new process should run under a child profile that matches the name of the executable
  • px - the new process should run under another profile that matches the name of the executable
  • ux - the new process should run unconfined

A process that runs unconfined is actually in the built-in unconfined profile, which allows everything with no logging.

The px, cx, and ux permission when written using a capitalized leading character (Px, Cx, Ux) will trigger libc's Secure Execution. When developing profiles, the Secure Execution variants should in general be used so that the executed program starts in a clean environment.

The px and cx rules (and their Secure Execution variants) may also have an ix, or ux fallback, expressed as pix, pux, cix, or cux. Using the fallback indicates that the process should run under the profile if it exists, otherwise the profile transition should use the specified ix or ux transition. It is often a good idea to use 'PUx' instead of 'Ux' so you don't have to update your profile for when the executed program has an AppArmor profile added later. For example, if a confined program should be allowed to run 'evince', then the profile might have:

 /usr/bin/evince PUx,

The px and cx rules (and all their variants) can also be modified to specify a profile by name instead of using the profile that matches the name of the executable. This is done by providing a -> transition arrow and the name of the profile.

 /foo px -> profile1,

Using AppArmor

The apparmor-utils package contains command-line utilities that you can use to change the AppArmor execution mode, find profile status, create new profiles, and so on.[Reference 6]

  1. apparmor_status is used to see the current status of the AppArmor profile:
    $ sudo apparmor_status 
  2. aa-complain switch the profile to the complain mode:
    $ sudo aa-complain /path/to/bin 
  3. aa-enforce switch the profile to the enforce mode:
    $ sudo aa-enforce /path/to/bin 
  4. AppArmor profiles are located in directory <code>/etc/apparmor.d. It can be used to control all profiles mode. Enter the next command to switch all profiles to complain mode:
    $ sudo aa-complain /etc/apparmor.d/* 
    Switch all profiles to enforce mode:
    $ sudo aa-enforce /etc/apparmor.d/* 
  5. apparmor_parser command is used to load the profile into the kernel. It can also be used to restart the installed profile when using the option '-r'. To install enter:
    $ cat /etc/apparmor.d/ | sudo apparmor_parser -a 
    To restart:
    $ cat /etc/apparmor.d/ | sudo apparmor_parser -r 
  6. /etc/init.d/apparmor restarts all profiles:
    $ sudo /etc/init.d/apparmor reload 
  7. Directory /etc/apparmor.d/disable can be used in conjunction with the option apparmor_parser -R to disable the profile:
    $ sudo ln -s /etc/apparmor.d/ /etc/apparmor.d/disable/ 
    $ sudo apparmor_parser -R /etc/apparmor.d/ 
  8. To activate a disabled profile, remove the symbolic link to the profile in /etc/apparmor.d/disable/. Then install the profile using the option '-a':
    $ sudo rm /etc/apparmor.d/disable/ 
    $ cat /etc/apparmor.d/ | sudo apparmor_parser -a 
  9. AppArmor can be disabled and kernel module can be unloaded using the following command:
    $ sudo /etc/init.d/apparmor stop 
    $ sudo update-rc.d -f apparmor remove 
  10. To reactivate AppArmor enter:
    $ sudo /etc/init.d/apparmor start 
    $ sudo update-rc.d apparmor defaults 

AppArmor protection status can be inspected using both high-level and low-level tools. The high-level tools use the low-level tools to gather information, and most of the low-level tools require an unconfined 'root' (uid 0) process. It may be possible to confine these processes with file and capability privileges.[Reference 7]

High level view

The 'aa-status' tool gives a high level status of AppArmor and applications it has profiles for (as root):

 # aa-status 
 apparmor module is loaded.
 11 profiles are loaded.
 11 profiles are in enforce mode.
 0 profiles are in complain mode.
 2 processes have profiles defined.
 2 processes are in enforce mode :
    /usr/sbin/cupsd (1192) 
    /sbin/dhclient3 (22378) 
 0 processes are in complain mode.
 0 processes are unconfined but have a profile defined.

Information on running processes

To discover which processes are confined, you can either use 'aa-status' as described above, or alternatively use the 'ps' command (as root):

 # ps aux -Z | grep -v unconfined
 /usr/sbin/cupsd    root  1192  0.0  0.0  75148  1260 ?   Ss   Jan15   0:00 /usr/sbin/c...
 /sbin/dhclient3    root 22378  0.0  0.0   6464  1088 ?   S    Jan23   0:00 /sbin/dhcli...

The raw data is also available via /proc (as root):

 # grep -L unconfined /proc/*/attr/current

Most sites that deploy AppArmor are especially interested in confining applications that use the network. Because this is so common, the aa-unconfined tool can help system administrators discover network servers that may or may not be confined (as root):

 # aa-unconfined 
 883 /usr/sbin/avahi-daemon not confined
 883 /usr/sbin/avahi-daemon not confined
 1192 /usr/sbin/cupsd confined by '/usr/sbin/cupsd (enforce)'
 12375 /usr/sbin/pdns_recursor not confined
 12375 /usr/sbin/pdns_recursor not confined
 22378 /sbin/dhclient3 (/sbin/dhclient) confined by '/sbin/dhclient3 (enforce)'
 27260 /usr/sbin/dictd (dictd 1.11.1: 1/275) not confined

Information from the kernel module

AppArmor supports the kernel-standard securityfs mechanism; securityfs is normally mounted on /sys/kernel/security, and the apparmor module populates /sys/kernel/security/apparmor with a few control and information files. The informational files are:

 $ ls -1 /sys/kernel/security/apparmor/

'features' and 'matching' provides feature and version information that is used by apparmor_parser to compile profiles for the running kernel. 'profiles' provides a list of the profiles loaded into the kernel as well as the per-profile enabled/complain/audit information.

Information from the persistent configuration files

You may also be curious about the profiles that AppArmor will load on next boot. /etc/apparmor.d/ contains all the profiles, as well as profile 'chunks' that are commonly shared between profiles. Some of these 'chunks' are abstractions, which are essentially libraries of access rules. On boot, the AppArmor init scripts will examine and load the profiles in /etc/apparmor.d/, ignoring certain files such as vim swap files and package manager generated files as well as profiles that have a symbolic link in /etc/apparmor.d/disable/. Files with a symbloic link in /etc/apparmor.d/force-complain/ are forced into complain mode.

If you want to verify the contents of a profile --- say, you want to make sure the abstractions that are included in the profile do not allow some ridiculous permissions --- you can invoke:

$ apparmor_parser -Q --debug /etc/apparmor.d/usr.bin.firefox | head -10
----- Debugging built structures -----
Name:       /usr/lib/firefox-4.0b7/firefox{,*[^s][^h]}
Profile Mode:   Enforce
Capabilities: net_bind_service
--- Entries ---
Mode:   r:r Name:   (/)
Mode:   r:r Name:   (/**/)
Mode:   rx:rx   Name:   (/bin/bash)
Mode:   rx:rx   Name:   (/bin/dash)
Mode:   rx:rx   Name:   (/bin/grep)

This listing shows the permissions granted when the user owns the resource (file, directory, pipe, etc.) and when the user does not own the resource.

Additionally, you can see the complete profile with all abstractions include with:

$ apparmor_parser -p /etc/apparmor.d/usr.bin.firefox
##included <abstractions/audio>
/dev/admmidi*   rw,
/dev/adsp*      rw,
/dev/aload*     rw,
/dev/amidi*     rw,
/dev/audio*     rw,
/dev/dmfm*      rw,


  1. AppArmor Wiki Page // Ubuntu Wiki. Updated on: 10.22.2018. URL: (retrieved: 11.15.2018)
  2. AppArmor_History // GitLab [2011—2019]. Updated on: 08.04.2018. URL: (retrieved: 01.17.2019).
  3. Solus 3 Linux Distribution Released For Enthusiasts // phoronix. [2004—2018]. Updated on: 08.15.2017. URL: (retrieved: 10.04.2018).
  4. AppArmor Home Wiki // GitLab [2011—2019]. Updated on: 12.21.2018. Access Mode: (retrieved: 11.15.2018)
  5. AppArmor Profile Language // GitLab [2011—2019]. Updated on: 11.04.2017. URL: (retrieved: 11.15.2018).
  6. AppArmor // URL:руководство_по_ubuntu_server/безопасность/apparmor (retrieved: 10.04.2018).
  7. AppArmor Monitoring // GitLab [2011—2019]. Updated on: 11.04.2017. URL: (retrieved: 11.15.2018).