QuickProfileLanguage

From AppArmor

Jump to: navigation, search

Contents

A quick guide to AppArmor profile Language

This is a quick guide to the AppArmor profile language, for an in depth guide see the Profile Language Reference

AppArmor policy is created using an administrator friendly profile language that is then compiled into a binary policy for loaded into the kernel. AppArmor policy is stored in a set of files in /etc/apparmor.d/. AppArmor policy is split into profiles which usually are designed to confine a specific application. Profiles will declare access rules to allow access to resources, and access is implicitly denied with logging when there is no matching rule in the profile.

Profiles

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. 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, see File Globbing (below) for details.

Comments

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:

  1. Comment 1
  2. 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* {

     }
  }

Hats

Hats are a special child profile that can be used with the change_hat API call. To denote a hat, prepend ^ before the hat name with no spaces. Eg:

 /parent/profile {

     ^hat {

     }
 }

Capability Rules

AppArmor supports course grained access to Linux' POSIX-style capabilities (see 'man capabilities) and capabilities rules are used to allow access to these capabilities. For example, a setuid application which drops privileges might need:

 /profile {
    capability setuid,
    capability setgid,
 }

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,
 }

Rlimit Rules

TODO

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
         rw,
 }

File rules can contain special globbing characters that allow matching to multiple files (see File Globbing, below)

See AppArmor File Permissions for more detail about file permissions.

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 /
    • This will match dot files (file names starting with .), excepting the special dot files . and .., if it is placed immediately after the directory /
      eg. /dir/*
    • This will not match an empty directory string eg. /dir//
    • pcre equivalent is ([^/\000]*)
  • ** - match 0 or more characters over multiple directory levels.
    • This will match dot files (file names starting with .), excepting the special dot files . and .., if it is placed immediately after the directory /
      eg. /dir/**
    • pcre equivalent is ([^\000]*)
  • ? - match a single character that is not /
    • pcre equivalent is [^/]
  • {} - 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
    • pcre equivalent is (|)
  • [] - character class
    • same as pcre syntax
  • [^] - inverted character class
    • same as pcre syntax
  • Nesting expressions in alternations (as of AppArmor 2.3):
    • escaping characters \*
    • expressing characters as # \001

Proposed additions

The following are proposed additions to the current file globbing and are not currently implemented:

  • {*^} - a glob similar to * with an alternation style list of things it is not allowed to match.
    eg. /etc/{*^shadow} is the same as allowing everything /etc/* matches except /etc/shadow
    eg. /etc/{*^shadow,passwd} is the same as /etc/* - /etc/{shadow,passwd}
    eg. /etc/{*^*shadow} is the same as /etc/* - /etc/*shadow
    • note that an empty alternation entry is not allowed ie. {*^shadow,}
  • {**^} - a glob similar to ** with an alternation style list of things is is not allowed to match eg. /etc/{**^shadow} is the same as /etc/** matches - /etc/shadow
    eg. /etc/{**^shadow,passwd} is the same as /etc/** - /etc/{shadow,passwd}
    eg. /etc/{**^*shadow} is the same as /etc/** - /etc/*shadow
    • note that an empty alternation entry is not allowed ie. {**^shadow,}

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
    • ux - Execute unconfined (preserve environment) -- WARNING: should only be used in very special cases
    • Ux - Execute unconfined (scrub the environment)
    • px - Execute under a specific profile (preserve the environment) -- WARNING: should only be used in special cases
    • Px - Execute under a specific profile (scrub the environment)
    • pix - as px but fallback to inheriting the current profile if the target profile is not found
    • Pix - as Px but fallback to inheriting the current profile if the target profile is not found
    • pux - as px but fallback to executing unconfined if the target profile is not found
    • Pux - as Px but fallback to executing unconfined if the target profile is not found
    • ix - Execute and inherit the current profile
    • cx - Execute and transition to a child profile (preserve the environment)
    • Cx - Execute and transition to a child profile (scrub the environment)
    • cix - as cx but fallback to inheriting the current profile if the target profile is not found
    • Cix - as Cx but fallback to inheriting the current profile if the target profile is not found
    • cux - as cx but fallback to executing unconfined if the target profile is not found
    • Cux - as Cx but fallback to executing unconfined if the target profile is not found
  • 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,

For directories, the UNIX execute permission maps to search access and AppArmor does not further control directory search access. In other words, traversing directories is granted if DAC permits it.

How AppArmor file permissions differ from DAC

On traditional UNIX systems using DAC, when files are looked up by name, the lookup starts either at the root or the current working directory of a process. From there, each directory reached is checked for search permission (x). The permissions on the directories leading to the current working directory are not checked. When a file is being created or deleted, the parent directory of that file is checked for write and search access (wx). When a file is being accessed, the permissions of that file are checked for r, w, or x access, or a combination thereof. Each check can result in a failure with errno set to EACCES (Permission denied).

AppArmor provides an additional permission check to DAC. DAC is always checked in addition to the AppArmor permission checks. As such, AppArmor cannot override DAC to provide more access than what would be normally allowed.

Path permission checking is calculated differently for AppArmor than in DAC. AppArmor first computes the pathname to the file. If the file is being created, the name being looked up is the name of the new file and not the name of the parent directory. If the file being looked up is a directory, AppArmor appends a slash to the pathname (this means a directory pathname in a profile must always end in a slash). As a convenience, AppArmor also allows pathnames to be rewritten via aliases.

After determining the pathname to evaluate, AppArmor then checks for file access rules in the process' profile that match that pathname, and performs permission checks based on these rules. With some exceptions for execute modes and deny mode, the permissions granted are the union of permissions of all matching rules.

More simply, creation of files requires the create permission (implied by w) on the path to be created. Permissions to write to the directory the file is created or accessed in is not required. Deletion works like creation but requires the delete permission (implied by w). Copy requires 'r' of the source with create and write at the destination (implied by w). Move is like copy, but also requires delete at source. For example:

The permissions to create and/or delete a file are:

 /foo/bar      w,

The permissions to copy a file are:

 /foo/src      r,
 /foo/dst      w,

The permissions to move a file are:

 /foo/src     rw,
 /foo/dst      w,

Notice in the above that AppArmor does not require additional rules in the policy to access or write to the / or /foo/ directories (DAC rules still apply though).

For directories, read access (r) allows reading of directory meta data (eg, owner) and reading of directory contents (ie listing) but is not needed for traversal. Write access (w) allows creation, deletion, and updating of directory meta data.

AppArmor file labeling

AppArmor will assign a default label to a file (as opposed to storing that label in the file's inode). When a process opens a file, the file object is assigned a label, which can be thought of as the profile name. A file can have multiple labels for when different processes want to access the same file to allow for different processes having different access controls. In practice, when developing policy one just refers to files by name, and the kernel handles all the necessary labeling behind the scenes. As such, AppArmor is often referred to as 'pathname-based'.

Since AppArmor labels files by pathname (rather than using on disk labeling), the administrator does not need to perform a relabelling step after a file is overwritten or moved. For example, if a process is granted read access to /etc/shadow and the system administrator renames /etc/shadow to /etc/shadow.old and replaces it with a copy (that may have an additional user in it, for example), the process will have access to the new /etc/shadow, and not to /etc/shadow.old.

Rule Modifiers

When there is no corresponding rule for a resource, AppArmor will block access to the resource and log it. When there is a rule in the policy, access is allowed to the resource without logging. The following modifiers can be prepended to a rule to change this behavior:

  • audit: force logging
  • deny: explicitly deny, without logging
  • audit deny: combination to explicitly deny, but log

Eg:

 /profile {
    /path/to/file*            r,  # allow read to /path/to/file*
    /path/to/file1            w,  # allow write to /path/to/file1
    deny /path/to/file2,      w,  # deny write to /path/to/file2, without logging
    audit /path/to/file3      w,  # allow write to /path/to/file3, with logging
    audit deny /path/to/file4 r,  # deny read to /path/to/file4, with logging
 }

IMPORTANT: deny rules are evaluated before allow rules and cannot be overridden by an allow rule. They are often used to override file globbing rules. For example, in the above policy the 'audit deny /path/to/file4 r' rule above overrides the '/path/to/file* r' rule.

Personal tools