32 Profile components and syntax #
Building AppArmor profiles to confine an application is straightforward and intuitive. AppArmor ships with several tools that assist in profile creation. It does not require you to do any programming or script handling. The only task that is required of the administrator is to determine a policy of strictest access and execute permissions for each application that needs to be hardened.
Updates or modifications to the application profiles are only required if the software configuration or the desired range of activities changes. AppArmor offers intuitive tools to handle profile updates and modifications.
You are ready to build AppArmor profiles after you select the programs to profile. To do so, it is important to understand the components and syntax of profiles. AppArmor profiles contain several building blocks that help build simple and reusable profile code:
- Include files
- Include statements are used to pull in parts of other AppArmor profiles to simplify the structure of new profiles. 
- Abstractions
- Abstractions are include statements grouped by common application tasks. 
- Program chunks
- Program chunks are include statements that contain chunks of profiles that are specific to program suites. 
- Capability entries
- Capability entries are profile entries for any of the POSIX.1e (https://en.wikipedia.org/wiki/POSIX#POSIX.1) Linux capabilities allowing a fine-grained control over what a confined process is allowed to do through system calls that require privileges. 
- Network access control entries
- Network Access Control Entries mediate network access based on the address type and family. 
- Local variable definitions
- Local variables define shortcuts for paths. 
- File access control entries
- File Access Control Entries specify the set of files an application can access. 
- rlimit entries
- rlimit entries set and control an application's resource limits. 
For help determining the programs to profile, refer to Section 31.2, “Determining programs to immunize”. To start building AppArmor profiles with YaST, proceed to Chapter 34, Building and managing profiles with YaST. To build profiles using the AppArmor command line interface, proceed to Chapter 35, Building profiles from the command line.
  For more details about creating AppArmor profiles, see
  man 5 apparmor.
 
32.1 Breaking an AppArmor profile into its parts #
   The easiest way of explaining what a profile consists of and how to
   create one is to show the details of a sample profile, in this case for a
   hypothetical application called /usr/bin/foo:
  
#include <tunables/global>1 # a comment naming the application to confine /usr/bin/foo2 {3 #include <abstractions/base>4 capability setgid5, network inet tcp6, link /etc/sysconfig/foo -> /etc/foo.conf,7 /bin/mount ux, /dev/{,u}8random r, /etc/ld.so.cache r, /etc/foo/* r, /lib/ld-*.so* mr, /lib/lib*.so* mr, /proc/[0-9]** r, /usr/lib/** mr, /tmp/ r,9 /tmp/foo.pid wr, /tmp/foo.* lrw, /@{HOME}10/.foo_file rw, /@{HOME}/.foo_lock kw, owner11 /shared/foo/** rw, /usr/bin/foobar Cx,12 /bin/** Px -> bin_generic,13 # a comment about foo's local (children) profile for /usr/bin/foobar. profile /usr/bin/foobar14 { /bin/bash rmix, /bin/cat rmix, /bin/more rmix, /var/log/foobar* rwl, /etc/foobar r, } # foo's hat, bar. ^bar15 { /lib/ld-*.so* mr, /usr/bin/bar px, /var/spool/* rwl, } }
| This loads a file containing variable definitions. | |
| The normalized path to the program that is confined. | |
| 
     The curly braces ( | |
| This directive pulls in components of AppArmor profiles to simplify profiles. | |
| Capability entry statements enable each of the 29 POSIX.1e draft capabilities. | |
| A directive determining the kind of network access allowed to the application. For details, refer to Section 32.5, “Network access control”. | |
| A link pair rule specifying the source and the target of a link. See Section 32.7.6, “Link pair” for more information. | |
| 
     The curly braces ( | |
| 
     A path entry specifying what areas of the file system the program can
     access. The first part of a path entry specifies the absolute path of a
     file (including regular expression globbing) and the second part
     indicates permissible access modes (for example  | |
| This variable expands to a value that can be changed without changing the entire profile. | |
| An owner conditional rule, granting read and write permission on files owned by the user. Refer to Section 32.7.8, “Owner conditional rules” for more information. | |
| 
     This entry defines a transition to the local profile
      | |
| A named profile transition to the profile bin_generic located in the global scope. See Section 32.12.7, “Named profile transitions” for details. | |
| 
     The local profile  | |
| This section references a “hat” subprofile of the application. For more details on AppArmor's ChangeHat feature, refer to Chapter 36, Profiling your Web applications using ChangeHat. | 
When a profile is created for a program, the program can access only the files, modes and POSIX capabilities specified in the profile. These restrictions are in addition to the Linux access controls.
Example:
    To gain the capability CAP_CHOWN, the
    program must have both access to CAP_CHOWN
    under conventional Linux access controls (typically, be a
    root-owned process) and have the capability
    chown in its profile. Similarly, to be able
    to write to the file /foo/bar the program must
    have both the correct user ID and mode bits set in the files
    attributes and have /foo/bar w in its profile.
   
   Attempts to violate AppArmor rules are recorded in
   /var/log/audit/audit.log if the
   audit package is installed, or
   in /var/log/messages, or only in
   journalctl if no traditional syslog is
   installed. Often AppArmor rules prevent an attack from working
   because necessary files are not accessible and, in all cases, AppArmor
   confinement restricts the damage that the attacker can do to the set of
   files permitted by AppArmor.
  
32.2 Profile types #
AppArmor knows four different types of profiles: standard profiles,
   unattached profiles, local profiles and hats. Standard and unattached
   profiles are stand-alone profiles, each stored in a file under
   /etc/apparmor.d/. Local profiles and hats are
   children profiles embedded inside of a parent profile used to provide
   tighter or alternate confinement for a subtask of an application.
  
32.2.1 Standard profiles #
The default AppArmor profile is attached to a program by its name, so a profile name must match the path to the application it is to confine.
/usr/bin/foo {
...
}
    This profile is automatically used whenever an unconfined process
    executes /usr/bin/foo.
   
32.2.2 Unattached profiles #
    Unattached profiles do not reside in the file system namespace and
    therefore are not automatically attached to an application. The name of
    an unattached profile is preceded by the keyword
    profile. You can freely choose a profile name, except
    for the following limitations: the name must not begin with a
    : or . character. If it contains a
    whitespace, it must be quoted. If the name begins with a
    /, the profile is considered to be a standard
    profile, so the following two profiles are identical:
   
profile /usr/bin/foo {
...
}
/usr/bin/foo {
...
}
    Unattached profiles are never used automatically, nor can they be
    transitioned to through a Px rule. They need to be
    attached to a program by either using a named profile transition (see
    Section 32.12.7, “Named profile transitions”) or with the
    change_profile rule (see
    Section 32.2.5, “Change rules”).
   
    Unattached profiles are useful for specialized profiles for system
    utilities that generally should not be confined by a system-wide profile
    (for example, /bin/bash). They can also be used to
    set up roles or to confine a user.
   
32.2.3 Local profiles #
    Local profiles provide a convenient way to provide specialized
    confinement for utility programs launched by a confined application.
    They are specified like standard profiles, except that they are embedded
    in a parent profile and begin with the profile
    keyword:
   
/parent/profile {
   ...
   profile /local/profile {
      ...
   }
}
    To transition to a local profile, either use a cx
    rule (see Section 32.12.2, “Discrete local profile execute mode (cx)”) or a named
    profile transition (see
    Section 32.12.7, “Named profile transitions”).
   
32.2.4 Hats #
AppArmor "hats" are a local profiles with certain additional restrictions
    and an implicit rule allowing for change_hat to be
    used to transition to them. Refer to Chapter 36, Profiling your Web applications using ChangeHat
    for a detailed description.
   
32.2.5 Change rules #
AppArmor provides change_hat and
    change_profile rules that control domain
    transitioning. change_hat are specified by defining
    hats in a profile, while change_profile rules refer
    to another profile and start with the keyword
    change_profile:
   
change_profile -> /usr/bin/foobar,
    Both change_hat and change_profile
    provide for an application directed profile transition, without having
    to launch a separate application. change_profile
    provides a generic one way transition between any of the loaded
    profiles. change_hat provides for a returnable parent
    child transition where an application can switch from the parent profile
    to the hat profile and if it provides the correct secret key return to
    the parent profile at a later time.
   
change_profile is best used in situations where an
    application goes through a trusted setup phase and then can lower its
    privilege level. Any resources mapped or opened during the start-up
    phase may still be accessible after the profile change, but the new
    profile restricts the opening of new resources, and limits
    certain resources opened before the switch. Specifically, memory
    resources are still  available while capability and file resources
    (if they are not memory mapped) can be limited.
   
change_hat is best used in situations where an
    application runs a virtual machine or an interpreter that does not
    provide direct access to the applications resources (for example
    Apache's mod_php). Since
    change_hat stores the return secret key in the
    application's memory the phase of reduced privilege should not have
    direct access to memory. It is also important that file access is
    properly separated, since the hat can restrict accesses to a file handle
    but does not close it. If an application does buffering and provides
    access to the open files with buffering, the accesses to these files
    might not be seen by the kernel and hence not restricted by the new
    profile.
   
     The change_hat and change_profile
     domain transitions are less secure than a domain transition done
     through an exec because they do not affect a process's memory mappings,
     nor do they close resources that have already been opened.
    
32.3 Include statements #
Include statements are directives that pull in components of other AppArmor profiles to simplify profiles. Include files retrieve access permissions for programs. By using an include, you can give the program access to directory paths or files that are also required by other programs. Using includes can reduce the size of a profile.
   Include statements normally begin with a hash (#)
   sign. This is confusing because the same hash sign is used for comments
   inside profile files. Because of this, #include is
   treated as an include only if there is no preceding #
   (##include is a comment) and there is no whitespace
   between # and include (#
   include is a comment).
  
   You can also use include without the leading
   #.
  
include "/etc/apparmor.d/abstractions/foo"
is the same as using
#include "/etc/apparmor.d/abstractions/foo"
Because includes follow the C pre-processor syntax, they do not have a trailing ',' like most AppArmor rules.
   By slight changes in syntax, you can modify the behavior of
   include. If you use "" around the
   including path, you instruct the parser to do an absolute or relative
   path lookup.
  
include "/etc/apparmor.d/abstractions/foo" # absolute path include "abstractions/foo" # relative path to the directory of current file
   When using relative path includes, when the file is included,
   it is considered the new current file for its includes. For example,
   suppose you are in the /etc/apparmor.d/bar file,
   then
  
include "abstractions/foo"
   includes the file /etc/apparmor.d/abstractions/foo.
   If then there is
  
include "example"
   inside the /etc/apparmor.d/abstractions/foo file, it
   includes /etc/apparmor.d/abstractions/example.
  
   The use of <> specifies to try the include
   path (specified by -I, defaults to the
   /etc/apparmor.d directory) in an ordered way. So
   assuming the include path is
  
-I /etc/apparmor.d/ -I /usr/share/apparmor/
then the include statement
include <abstractions/foo>
   tries /etc/apparmor.d/abstractions/foo, and if
   that file does not exist, the next try is
   /usr/share/apparmor/abstractions/foo.
  
    The default include path can be overridden manually by passing
    -I to the apparmor_parser, or by
    setting the include paths in
    /etc/apparmor/parser.conf:
   
Include /usr/share/apparmor/ Include /etc/apparmor.d/
    Multiple entries are allowed, and they are taken in the same order as
    when they are when using -I or
    --Include from the apparmor_parser
    command line.
   
If an include ends with '/', this is considered a directory include, and all files within the directory are included.
To assist you in profiling your applications, AppArmor provides three classes of includes: abstractions, program chunks and tunables.
32.3.1 Abstractions #
    Abstractions are includes that are grouped by common application tasks.
    These tasks include access to authentication mechanisms, access to name
    service routines, common graphics requirements, and system accounting.
    Files listed in these abstractions are specific to the named task.
    Programs that require one of these files also requires
    other files listed in the abstraction file (depending on the local
    configuration and the specific requirements of the program). Find
    abstractions in /etc/apparmor.d/abstractions.
   
32.3.2 Program chunks #
    The program-chunks directory
    (/etc/apparmor.d/program-chunks) contains certain
    chunks of profiles that are specific to program suites and not generally
    useful outside of the suite, thus are never suggested for use in
    profiles by the profile wizards (aa-logprof and
    aa-genprof). Currently, program chunks are only
    available for the postfix program suite.
   
32.3.3 Tunables #
    The tunables directory (/etc/apparmor.d/tunables)
    contains global variable definitions. When used in a profile, these
    variables expand to a value that can be changed without changing the
    entire profile. Add all the tunables definitions that should be
    available to every profile to
    /etc/apparmor.d/tunables/global.
   
32.4 Capability entries (POSIX.1e) #
   Capability rules are simply the word capability
   followed by the name of the POSIX.1e capability as defined in the
   capabilities(7) man page. You can list multiple
   capabilities in a single rule, or grant all implemented capabilities with
   the bare keyword capability.
  
capability dac_override sys_admin, # multiple capabilities capability, # grant all capabilities
32.5 Network access control #
AppArmor allows mediation of network access based on the address type and family. The following illustrates the network access rule syntax:
network [[<domain>1][<type2>][<protocol3>]]
| 
     Supported domains:  | |
| 
     Supported types:  | |
| 
     Supported protocols:  | 
   The AppArmor tools support only family and type specification. The AppArmor
   module emits only network DOMAIN
TYPE in “ACCESS DENIED”
   messages. And only these are output by the profile generation tools, both
   YaST and command line.
  
The following examples illustrate possible network-related rules to be used in AppArmor profiles. The syntax of the last two are not currently supported by the AppArmor tools.
network1, network inet2, network inet63, network inet stream4, network inet tcp5, network tcp6,
| Allow all networking. No restrictions applied with regard to domain, type, or protocol. | |
| Allow general use of IPv4 networking. | |
| Allow general use of IPv6 networking. | |
| Allow the use of IPv4 TCP networking. | |
| Allow the use of IPv4 TCP networking, paraphrasing the rule above. | |
| Allow the use of both IPv4 and IPv6 TCP networking. | 
32.6 Profile names, flags, paths, and globbing #
A profile is attached to a program by specifying a full path to the program's executable. For example, a standard profile (see Section 32.2.1, “Standard profiles”), the profile is defined by
/usr/bin/foo { ... }The following sections describe several useful techniques that can be applied when naming a profile or putting a profile in the context of other existing ones, or specifying file paths.
AppArmor explicitly distinguishes directory path names from path
   names. Use a trailing / for any directory path that
   needs to be explicitly distinguished:
  
- /some/random/example/* r
- Allow read access to files in the - /some/random/exampledirectory.
- /some/random/example/ r
- Allow read access to the directory only. 
- /some/**/ r
- Give read access to any directories below - /some(but not /some/ itself).
- /some/random/example/** r
- Give read access to files and directories under - /some/random/example(but not /some/random/example/ itself).
- /some/random/example/**[^/] r
- Give read access to files under - /some/random/example. Explicitly exclude directories (- [^/]).
Globbing (or regular expression matching) is when you modify the directory path using wild cards to include a group of files or subdirectories. File resources can be specified with a globbing syntax similar to that used by popular shells, such as csh, Bash and zsh.
| 
 | 
        Substitutes for any number of any characters, except
         Example: An arbitrary number of path elements. | 
| 
 | 
        Substitutes for any number of characters, including
         Example: An arbitrary number of path elements, including entire directories. | 
| 
 | 
        Substitutes for any single character, except  | 
| 
 | 
        Substitutes for the single character  
        Example: a rule that matches  | 
| 
 | 
        Substitutes for the single character  | 
| 
 | 
        Expands to one rule to match  
        Example: a rule that matches  | 
| 
 | 
        Substitutes for any character except  | 
32.6.1 Profile flags #
Profile flags control the behavior of the related profile. You can add profile flags to the profile definition by editing it manually, see the following syntax:
/path/to/profiled/binary flags=(list_of_flags) {
  [...]
}You can use multiple flags separated by a comma ',' or space ' '. There are three basic types of profile flags: mode, relative, and attach flags.
Mode flag is complain (illegal
    accesses are allowed and logged). If it is omitted, the profile is in
    enforce mode (enforces the policy).
   
     A more flexible way of setting the whole profile into complain mode is
     to create a symbolic link from the profile file inside the
     /etc/apparmor.d/force-complain/ directory.
    
ln -s /etc/apparmor.d/bin.ping /etc/apparmor.d/force-complain/bin.ping
Relative flags are
    chroot_relative (states that the profile is relative
    to the chroot instead of namespace) or
    namespace_relative (the default, with the path being
    relative to outside the chroot). They are mutually exclusive.
   
Attach flags consist of two pairs of mutually
    exclusive flags: attach_disconnected or
    no_attach_disconnected (determine if path names
    resolved to be outside of the namespace are attached to the root, which
    means they have the '/' character at the beginning), and
    chroot_attach or chroot_no_attach
    (control path name generation when in a chroot environment while a file
    is accessed that is external to the chroot but within the namespace).
   
32.6.2 Using variables in profiles #
AppArmor allows to use variables holding paths in profiles. Use global variables to make your profiles portable and local variables to create shortcuts for paths.
    A typical example of when global variables come in handy are network
    scenarios in which user home directories are mounted in different
    locations. Instead of rewriting paths to home directories in all
    affected profiles, you only need to change the value of a variable.
    Global variables are defined under
    /etc/apparmor.d/tunables and need to be made
    available via an include statement. Find the variable definitions for
    this use case (@{HOME} and @{HOMEDIRS}) in
    the /etc/apparmor.d/tunables/home file.
   
Local variables are defined at the head of a profile. This is useful to provide the base of for a chrooted path, for example:
@{CHROOT_BASE}=/tmp/foo
/sbin/rsyslogd {
...
# chrooted applications
@{CHROOT_BASE}/var/lib/*/dev/log w,
@{CHROOT_BASE}/var/log/** w,
...
}In the following example, while @{HOMEDIRS} lists where all the user home directories are stored, @{HOME} is a space-separated list of home directories. Later on, @{HOMEDIRS} is expanded by two new specific places where user home directories are stored.
@{HOMEDIRS}=/home/
@{HOME}=@{HOMEDIRS}/*/ /root/
[...]
@{HOMEDIRS}+=/srv/nfs/home/ /mnt/home/With the current AppArmor tools, variables can only be used when manually editing and maintaining a profile.
32.6.3 Pattern matching #
Profile names can contain globbing expressions allowing the profile to match against multiple binaries.
    The following example is valid for systems where the
    foo binary resides either in
    /usr/bin or /bin.
   
/{usr/,}bin/foo { ... }
    In the following example, when matching against the executable
    /bin/foo, the /bin/foo profile
    is an exact match so it is chosen. For the executable
    /bin/fat, the profile /bin/foo
    does not match, and because the /bin/f* profile is
    more specific (less general) than /bin/**, the
    /bin/f* profile is chosen.
   
/bin/foo { ... }
/bin/f*  { ... }
/bin/**  { ... }
    For more information on profile name globbing examples, see the man page
    of AppArmor, man 5 apparmor.d,, section
    Globbing.
   
32.6.4 Namespaces #
    Namespaces are used to provide different profiles sets. Say one for the
    system, another for a chroot environment or container. Namespaces are
    hierarchical—a namespace can see its children but a child
    cannot see its parent. Namespace names start with a colon
    : followed by an alphanumeric string, a trailing
    colon : and an optional double slash
    //, such as
   
:childNameSpace://
Profiles loaded to a child namespace are prefixed with their namespace name (viewed from a parent's perspective):
:childNameSpace://apache
    Namespaces can be entered via the change_profile API,
    or named profile transitions:
   
/path/to/executable px -> :childNameSpace://apache
32.6.5 Profile naming and attachment specification #
Profiles can have a name, and an attachment specification. This allows for profiles with a logical name that can be more meaningful to users/administrators than a profile name that contains pattern matching (see Section 32.6.3, “Pattern matching”). For example, the default profile
/** { ... }can be named
profile default /** { ... }Also, a profile with pattern matching can be named. For example:
/usr/lib64/firefox*/firefox-*bin { ... }can be named
profile firefox /usr/lib64/firefox*/firefox-*bin { ... }32.6.6 Alias rules #
Alias rules provide an alternative way to manipulate profile path mappings to site specific layouts. They are an alternative form of path rewriting to using variables, and are done post variable resolution. The alias rule says to treat rules that have the same source prefix as if the rules are at target prefix.
alias /home/ -> /usr/home/
    All the rules that have a prefix match to /home/
    provide access to /usr/home/. For example:
   
/home/username/** r,
allows as well access to
/usr/home/username/** r,
    Aliases provide a quick way of remapping rules without the need to
    rewrite them. They keep the source path still accessible—in our
    example, the alias rule keeps the paths under
    /home/ still accessible.
   
    With the alias rule, you can point to multiple
    targets at the same time.
   
alias /home/ -> /usr/home/ alias /home/ -> /mnt/home/
With the current AppArmor tools, alias rules can only be used when manually editing and maintaining a profile.
     Insert global alias definitions in the file
     /etc/apparmor.d/tunables/alias.
    
32.7 File permission access modes #
File permission access modes consist of combinations of the following modes:
| 
 | Read mode | 
| 
 | 
        Write mode (mutually exclusive to  | 
| 
 | 
        Append mode (mutually exclusive to  | 
| 
 | File locking mode | 
| 
 | Link mode | 
| 
 | Link pair rule (cannot be combined with other access modes) | 
32.7.1 Read mode (r) #
Allows the program to have read access to the resource. Read access is required for shell scripts and other interpreted content and determines if an executing process can core dump.
32.7.2 Write mode (w) #
Allows the program to have write access to the resource. Files must have this permission if they are to be unlinked (removed).
32.7.3 Append mode (a) #
    Allows a program to write to the end of a file. In contrast to the
    w mode, the append mode does not include the ability
    to overwrite data, to rename, or to remove a file. The append permission
    is typically used with applications who need to be able to write to log
    files, but which should not be able to manipulate any existing data in
    the log files. As the append permission is a subset of the permissions
    associated with the write mode, the w and
    a permission flags cannot be used together and are
    mutually exclusive.
   
32.7.4 File locking mode (k) #
The application can take file locks. Former versions of AppArmor allowed files to be locked if an application had access to them. By using a separate file locking mode, AppArmor makes sure locking is restricted only to those files which need file locking and tightens security as locking can be used in several denial-of-service attack scenarios.
32.7.5 Link mode (l) #
The link mode mediates access to hard links. When a link is created, the target file must have the same access permissions as the link created (but the destination does not need link access).
32.7.6 Link pair #
The link mode grants permission to link to arbitrary files, provided the link has a subset of the permissions granted by the target (subset permission test).
/srv/www/htdocs/index.html rl,
By specifying origin and destination, the link pair rule provides greater control over how hard links are created. Link pair rules by default do not enforce the link subset permission test that the standard rules link permission requires.
link /srv/www/htdocs/index.html -> /var/www/index.html
    To force the rule to require the test, the subset
    keyword is used. The following rules are equivalent:
   
/var/www/index.html l, link subset /var/www/index.html -> /**,
Currently link pair rules are not supported by YaST and the command-line tools. Manually edit your profiles to use them. Updating such profiles using the tools is safe, because the link pair entries are not touched.
32.7.7 Optional allow and file rules #
    The allow prefix is optional, and it is idiomatically
    implied if not specified and the deny (see
    Section 32.7.9, “Deny rules”) keyword is not used.
   
allow file /example r, allow /example r, allow network,
    You can also use the optional file keyword. If you
    omit it and there are no other rule types that start with a keyword,
    such as network or mount, it is
    automatically implied.
   
file /example/rule r,
is equivalent to
/example/rule r,
The following rule grants access to all files:
file,
which is equal to
/** rwmlk,
File rules can use leading or trailing permissions. The permissions should not be specified as a trailing permission, but rather used at the start of the rule. This is important in that it makes file rules behave like any other rule types.
/path rw, # old style rw /path, # leading permission file rw /path, # with explicit 'file' keyword allow file rw /path, # optional 'allow' keyword added
32.7.8 Owner conditional rules #
    The file rules can be extended so that they can be conditional upon
    the user being the owner of the file (the fsuid needs to match the
    file's uid). For this purpose the owner keyword
    is put in front of the rule. Owner conditional rules accumulate like
    regular file rules do.
   
owner /home/*/** rw
When using file ownership conditions with link rules the ownership test is done against the target file so the user must own the file to be able to link to it.
Owner conditional rules are considered a subset of regular file rules. If a regular file rule overlaps with an owner conditional file rule, the rules are merged. Consider the following example.
/foo r, owner /foo rw, # or w,
     The rules are merged—it results in r for
     everybody, and w for the owner only.
    
     To address everybody but the owner of the file,
     use the keyword other.
    
owner /foo rw, other /foo r,
32.7.9 Deny rules #
    Deny rules can be used to annotate or quiet known rejects. The
    profile generating tools do not ask about a known reject treated
    with a deny rule. Such a reject does not show up in the audit
    logs when denied, keeping the log files lean. If this is not
    desired, put the keyword audit in front of the
    deny entry.
   
    It is also possible to use deny rules in combination with allow rules.
    This allows you to specify a broad allow rule, and then subtract a few
    known files that should not be allowed. Deny rules can also be combined
    with owner rules, to deny files owned by the user. The following example
    allows read/write access to everything in a users directory except write
    access to the .ssh/ files:
   
deny /home/*/.ssh/** w, owner /home/*/** rw,
The extensive use of deny rules is generally not encouraged, because it makes it much harder to understand what a profile does. However a judicious use of deny rules can simplify profiles. Therefore the tools only generate profiles denying specific files and do not use globbing in deny rules. Manually edit your profiles to add deny rules using globbing. Updating such profiles using the tools is safe, because the deny entries are not touched.
32.8 Mount rules #
AppArmor can limit mount and unmount operations, including file system
   types and mount flags. The rule syntax is based on the
   mount command syntax and starts with one of the
   keywords mount, remount, or
   umount. Conditions are optional and unspecified
   conditionals are assumed to match all entries. For example, not
   specifying a file system means that all file systems are matched.
  
   Conditionals can be specified by specifying conditionals with
   options= or options in.
  
options= specifies conditionals that have to be met
    exactly. The rule
  
mount options=ro /dev/foo -E /mnt/,
matches
#mount -o ro /dev/foo /mnt
but does not match
#mount -o ro,atime /dev/foo /mnt#mount -o rw /dev/foo /mnt
options in requires that at least one of the
   listed mount options is used. The rule
  
mount options in (ro,atime) /dev/foo -> /mnt/,
matches
#mount -o ro /dev/foo /mnt#mount -o ro,atime /dev/foo /mnt#mount -o atime /dev/foo /mnt
but does not match
#mount -o ro,sync /dev/foo /mnt#mount -o ro,atime,sync /dev/foo /mnt#mount -o rw /dev/foo /mnt#mount -o rw,noatime /dev/foo /mnt#mount /dev/foo /mnt
With multiple conditionals, the rule grants permission for each set of options. The rule
mount options=ro options=atime
matches
#mount -o ro /dev/foo /mnt#mount -o atime /dev/foo /mnt
but does not match
#mount -o ro,atime /dev/foo /mnt
Separate mount rules are distinct and the options do not accumulate. The rules
mount options=ro, mount options=atime,
are not equivalent to
mount options=(ro,atime), mount options in (ro,atime),
   The following rule allows mounting /dev/foo on
   /mnt/ read only and using inode access times or
   allows mounting /dev/foo on
   /mnt/ with some combination of 'nodev' and
   'user'.
  
mount options=(ro, atime) options in (nodev, user) /dev/foo -> /mnt/,
allows
#mount -o ro,atime /dev/foo /mnt#mount -o nodev /dev/foo /mnt#mount -o user /dev/foo /mnt#mount -o nodev,user /dev/foo /mnt
32.9 Pivot root rules #
AppArmor can limit changing the root file system. The syntax is
pivot_root [oldroot=OLD_ROOT] NEW_ROOT
The paths specified in 'pivot_root' rules must end with '/' since they are directories.
# Allow any pivot pivot_root, # Allow pivoting to any new root directory and putting the old root # directory at /mnt/root/old/ pivot_root oldroot=/mnt/root/old/, # Allow pivoting the root directory to /mnt/root/ pivot_root /mnt/root/, # Allow pivoting to /mnt/root/ and putting the old root directory at # /mnt/root/old/ pivot_root oldroot=/mnt/root/old/ /mnt/root/, # Allow pivoting to /mnt/root/, putting the old root directory at # /mnt/root/old/ and transition to the /mnt/root/sbin/init profile pivot_root oldroot=/mnt/root/old/ /mnt/root/ -> /mnt/root/sbin/init,
32.10 PTrace rules #
AppArmor supports limiting ptrace system calls. ptrace rules are accumulated so that the granted ptrace permissions are the union of all the listed ptrace rule permissions. If a rule does not specify an access list, permissions are implicitly granted.
   The trace and tracedby
   permissions control ptrace(2); read and
   readby control proc(5) file system access,
   kcmp(2), futexes (get_robust_list(2)) and perf trace events.
  
   For a ptrace operation to be allowed, the tracing and traced
   processes need the correct permissions. This means that the tracing
   process needs the trace permission and the traced
   process needs the tracedby permission.
  
Example AppArmor PTrace rules:
# Allow all PTrace access ptrace, # Explicitly allow all PTrace access, ptrace (read, readby, trace, tracedby), # Explicitly deny use of ptrace(2) deny ptrace (trace), # Allow unconfined processes (eg, a debugger) to ptrace us ptrace (readby, tracedby) peer=unconfined, # Allow ptrace of a process running under the /usr/bin/foo profile ptrace (trace) peer=/usr/bin/foo,
32.11 Signal rules #
AppArmor supports limiting inter-process signals. AppArmor signal rules are accumulated so that the granted signal permissions are the union of all the listed signal rule permissions. AppArmor signal permissions are implied when a rule does not explicitly state an access list.
The sending and receiving process must both have the correct permissions.
Example signal rules:
# Allow all signal access
signal,
# Explicitly deny sending the HUP and INT signals
deny signal (send) set=(hup, int),
# Allow unconfined processes to send us signals
signal (receive) peer=unconfined,
# Allow sending of signals to a process running under the /usr/bin/foo
# profile
signal (send) peer=/usr/bin/foo,
# Allow checking for PID existence
signal (receive, send) set=("exists"),
# Allow us to signal ourselves using the built-in @{profile_name} variable
signal peer=@{profile_name},
# Allow two real-time signals
signal set=(rtmin+0 rtmin+32),32.12 Execute modes #
Execute modes, also named profile transitions, consist of the following modes:
| 
 | Discrete profile execute mode | 
| 
 | Discrete local profile execute mode | 
| 
 | Unconfined execute mode | 
| 
 | Inherit execute mode | 
| 
 | 
        Allow  | 
32.12.1 Discrete profile execute mode (px) #
This mode requires that a discrete security profile is defined for a resource executed at an AppArmor domain transition. If there is no profile defined, the access is denied.
    Incompatible with Ux, ux,
    px, and ix.
   
32.12.2 Discrete local profile execute mode (cx) #
    As Px, but instead of searching the global profile
    set, Cx only searches the local profiles of the
    current profile. This profile transition provides a way for an
    application to have alternate profiles for helper applications.
   
Currently, Cx transitions are limited to top level profiles and cannot be used in hats and children profiles. This restriction will be removed in the future.
    Incompatible with Ux, ux,
    Px, px, cx, and
    ix.
   
32.12.3 Unconfined execute mode (ux) #
    Allows the program to execute the resource without any AppArmor profile
    applied to the executed resource. This mode is useful when a confined
    program needs to be able to perform a privileged operation, such as
    rebooting the machine. By placing the privileged section in another
    executable and granting unconfined execution rights, it is possible to
    bypass the mandatory constraints imposed on all confined processes.
    Allowing a root process to go unconfined means it can change AppArmor
    policy itself. For more information about what is constrained, see the
    apparmor(7) man page.
   
    This mode is incompatible with ux,
    px, Px, and ix.
   
32.12.4 Unsafe exec modes #
    Use the lowercase versions of exec modes—px,
    cx, ux—only in
    special cases. They do not scrub the environment of variables such as
    LD_PRELOAD. As a result, the calling domain may have an
    undue amount of influence over the called resource. Use these modes only
    if the child absolutely must be run unconfined and
    LD_PRELOAD must be used. Any profile using such modes
    provides negligible security. Use at your own risk.
   
32.12.5 Inherit execute mode (ix) #
ix prevents the normal AppArmor domain transition on
    execve(2) when the profiled program executes the
    named program. Instead, the executed resource inherits the current
    profile.
   
    This mode is useful when a confined program needs to call another
    confined program without gaining the permissions of the target's profile
    or losing the permissions of the current profile. There is no version to
    scrub the environment because ix executions do not
    change privileges.
   
    Incompatible with cx, ux, and
    px. Implies m.
   
32.12.6 Allow executable mapping (m) #
    This mode allows a file to be mapped into memory using
    mmap(2)'s PROT_EXEC flag. This flag
    marks the pages executable. It is used on certain architectures to provide
    non executable data pages, which can complicate exploit attempts.
    AppArmor uses this mode to limit which files a well-behaved program (or
    all programs on architectures that enforce non executable memory access
    controls) may use as libraries, to limit the effect of invalid
    -L flags given to ld(1) and
    LD_PRELOAD, LD_LIBRARY_PATH, given to
    ld.so(8).
   
32.12.7 Named profile transitions #
    By default, the px and cx (and
    their clean exec variants, too) transition to a profile whose name
    matches the executable name. With named profile transitions, you can
    specify a profile to be transitioned to. This is useful if multiple
    binaries need to share a single profile, or if they need to use a
    different profile than their name would specify. Named profile
    transitions can be used with cx,
    Cx, px and Px.
    Currently there is a limit of twelve named profile transitions per
    profile.
   
    Named profile transitions use -> to indicate the
    name of the profile that needs to be transitioned to:
   
/usr/bin/foo
{
  /bin/** px -> shared_profile,
  ...
  /usr/*bash cx -> local_profile,
  ...
  profile local_profile
  {
    ...
  }
}
     When used with globbing, normal transitions provide a “one to
     many” relationship—/bin/** px transitions
     to /bin/ping,
     /bin/cat, etc, depending on the program being run.
    
Named transitions provide a “many to one” relationship—all programs that match the rule regardless of their name transition to the specified profile.
     Named profile transitions show up in the log as having the mode
     Nx. The name of the profile to be changed to is
     listed in the name2 field.
    
32.12.8 Fallback modes for profile transitions #
    The px and cx transitions specify
    a hard dependency—if the specified profile does not exist, the
    exec fails. With the inheritance fallback, the execution
    succeeds but inherits the current profile. To specify inheritance
    fallback, ix is combined with cx,
    Cx, px and Px
    into the modes cix, Cix,
    pix and Pix.
   
/path Cix -> profile_name,
or
Cix /path -> profile_name,
    where -> profile_name is optional.
   
    The same applies if you add the unconfined ux mode,
    where the resulting modes are cux,
    CUx, pux and
    PUx. These modes allow falling back to
    “unconfined” when the specified profile is not found.
   
/path PUx -> profile_name,
or
PUx /path -> profile_name,
    where -> profile_name is optional.
   
The fallback modes can be used with named profile transitions, too.
32.12.9 Variable settings in execution modes #
When choosing one of the Px, Cx or Ux execution modes, take into account that the following environment variables are removed from the environment before the child process inherits it. As a consequence, applications or processes relying on any of these variables do not work anymore if the profile applied to them carries Px, Cx or Ux flags:
- GCONV_PATH
- GETCONF_DIR
- HOSTALIASES
- LD_AUDIT
- LD_DEBUG
- LD_DEBUG_OUTPUT
- LD_DYNAMIC_WEAK
- LD_LIBRARY_PATH
- LD_ORIGIN_PATH
- LD_PRELOAD
- LD_PROFILE
- LD_SHOW_AUXV
- LD_USE_LOAD_BIAS
- LOCALDOMAIN
- LOCPATH
- MALLOC_TRACE
- NLSPATH
- RESOLV_HOST_CONF
- RES_OPTIONS
- TMPDIR
- TZDIR
32.12.10 safe and unsafe keywords #
    You can use the safe and unsafe
    keywords for rules instead of using the case modifier of execution
    modes. For example
   
/example_rule Px,
is the same as any of the following
safe /example_rule px, safe /example_rule Px, safe px /example_rule, safe Px /example_rule,
and the rule
/example_rule px,
is the same as any of
unsafe /example_rule px, unsafe /example_rule Px, unsafe px /example_rule, unsafe Px /example_rule,
    The safe/unsafe keywords are
    mutually exclusive and can be used in a file rule after the
    owner keyword, so the order of rule keywords is
   
[audit] [deny] [owner] [safe|unsafe] file_rule
32.13 Resource limit control #
AppArmor can set and control an application's resource
   limits (rlimits, also known as ulimits). By default, AppArmor does not
   control an application's rlimits, and it controls those limits
   specified in the confining profile. For more information about resource
   limits, refer to the setrlimit(2),
   ulimit(1), or ulimit(3)
   man pages.
  
AppArmor leverages the system's rlimits and as such does not provide an additional auditing that would normally occur. It also cannot raise rlimits set by the system, AppArmor rlimits can only reduce an application's current resource limits.
The values are inherited by the children of a process and remain even if a new profile is transitioned to or the application becomes unconfined. So when an application transitions to a new profile, that profile can further reduce the application's rlimits.
AppArmor's rlimit rules provide mediation of setting an application's hard limits, should it try to raise them. The application cannot raise its hard limits any further than specified in the profile. The mediation of raising hard limits is not inherited as the set value is, so that when the application transitions to a new profile it is free to raise its limits as specified in the profile.
AppArmor's rlimit control does not affect an application's soft limits beyond ensuring that they are less than or equal to the application's hard limits.
AppArmor's hard limit rules have the general form of:
set rlimit RESOURCE <= value,
where RESOURCE and VALUE are to be replaced with the following values:
- cpu
- CPU time limit in seconds. 
- fsize,- data,- stack,- core,- rss,- as,- memlock,- msgqueue
- a number in bytes, or a number with a suffix where the suffix can be K/KB (kilobytes), M/MB (megabytes), G/GB (gigabytes), for example - rlimit data <= 100M, 
- fsize,- nofile,- locks,- sigpending,- nproc,- rtprio
- a number greater or equal to 0 
- nice
- a value between -20 and 19 
The nproc rlimit is handled different than all the other rlimits. Instead of indicating the standard process rlimit, it controls the maximum number of processes that can be running under the profile at any time. When the limit is exceeded, the creation of new processes under the profile fails until the number of currently running processes is reduced.
Currently the tools cannot be used to add rlimit rules to profiles. The only way to add rlimit controls to a profile is to manually edit the profile with a text editor. The tools still work with profiles containing rlimit rules and will not remove them, so it is safe to use the tools to update profiles containing them.
32.14 Auditing rules #
AppArmor provides the ability to audit given rules so that when they are
   matched, an audit message appears in the audit log. To enable audit
   messages for a given rule, the audit keyword is
   put in front of the rule:
  
audit /etc/foo/* rw,
If it is desirable to audit only a given permission, the rule can be split into two rules. The following example results in audit messages when files are opened for writing, but not when they are opened for reading:
audit /etc/foo/* w, /etc/foo/* r,
Audit messages are not generated for every read or write of a file but only when a file is opened for reading or writing.
   Audit control can be combined with
   owner/other conditional file rules
   to provide auditing when users access files they own/do not own:
  
audit owner /home/*/.ssh/** rw, audit other /home/*/.ssh/** r,