mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
Update QuickProfileLanguage
parent
b977c789af
commit
fe2d7b256f
1 changed files with 345 additions and 190 deletions
|
@ -1,142 +1,206 @@
|
|||
# A quick guide to AppArmor profile Language
|
||||
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](ProfileLanguage) or the `apparmor.d` man page.
|
||||
This is a quick guide to the AppArmor profile language; for an in
|
||||
depth guide see the [Profile Language Reference](ProfileLanguage) or the `apparmor.d` man page.
|
||||
|
||||
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.
|
||||
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
|
||||
--------
|
||||
|
||||
Profiles declarations consist of a name and attachment, followed by an optional flags field described in more detail [here](profileflags). At least one of the name and attachment must be present; if only the attachment is present, it will also be considered the name. The attachment represents the path(s) of binaries that a profile is automatically applied to once the profile is loaded into the kernel. If no attachment is present, a profile will not automatically apply to any program but can still be used manually to confine programs using methods like `aa-exec`, the apparmor security option of Docker, or `AppArmorProfile=` in systemd unit files, for example.
|
||||
Profiles declarations consist of a name and attachment, followed by an optional flags field described in more detail [here](profileflags). At least one of the name and attachment must be present; if only the attachment is present, it will also be considered the name. The attachment represents the path(s) of binaries that a profile is automatically applied to once the profile is loaded into the kernel. If no attachment is present, a profile will not automatically apply to any program but can still be used manually to confine programs using methods like `aa-exec` and the apparmor security option of Docker.
|
||||
|
||||
The keyword "profile" is required when a separate name is present and is encouraged even when not required.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
/usr/bin/firefox {
|
||||
# profile contents
|
||||
}
|
||||
/usr/bin/firefox {
|
||||
# profile contents
|
||||
}
|
||||
|
||||
/usr/bin/firefox flags=(complain) {
|
||||
# profile contents
|
||||
}
|
||||
/usr/bin/firefox flags=(complain) {
|
||||
# profile contents
|
||||
}
|
||||
|
||||
profile /usr/bin/ {
|
||||
# profile contents
|
||||
}
|
||||
profile /usr/bin/ {
|
||||
# profile contents
|
||||
}
|
||||
|
||||
profile user1 {
|
||||
# profile contents
|
||||
}
|
||||
profile user1 {
|
||||
# profile contents
|
||||
}
|
||||
```
|
||||
|
||||
Profile attachments can contain file rule globbing characters to allow them to apply to multiple executables, see File Globbing (below) for details.
|
||||
Profile attachments can contain file rule globbing characters to allow
|
||||
them to apply to multiple executables, see File Globbing (below)
|
||||
for details.
|
||||
|
||||
## Comments
|
||||
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:
|
||||
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
|
||||
}
|
||||
profile example { # comment 3
|
||||
# comment 4
|
||||
/home/foo rw, # comment at the end of a file rule
|
||||
}
|
||||
```
|
||||
|
||||
## Include Rules
|
||||
Include Rules
|
||||
-------------
|
||||
|
||||
Policy files can include other files to share text segments. AppArmor includes follow the C include convention: as rules in an include would be terminated with a comma, include statements should not be terminated with one either. They start with `include` followed by either angle brackets for text chucks relative to a set include directory or quoted paths for files relative to the current file. A `#` may precede the `include` keyword, but it shouldn't be used in newer profiles. Eg:
|
||||
Policy files can include other files to share text segments. AppArmor
|
||||
includes follow the C include convention: as rules in an include would
|
||||
be terminated with a comma, include statements should not be terminated
|
||||
with one either. They start with `include` followed by either angle
|
||||
brackets for text chucks relative to a set include directory or quoted
|
||||
paths for files relative to the current file. A `#` may precede the
|
||||
`include` keyword, but it shouldn't be used in newer profiles. Eg:
|
||||
|
||||
```
|
||||
#include <file>
|
||||
#include “a/relative/path/file”
|
||||
include <file>
|
||||
#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** 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>
|
||||
# include is a comment
|
||||
#include <file>
|
||||
```
|
||||
|
||||
The include file `<abstractions/base>` sets up access to many common files used universally.
|
||||
|
||||
### 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:
|
||||
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* {
|
||||
}
|
||||
}
|
||||
/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:
|
||||
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 {
|
||||
}
|
||||
}
|
||||
/parent/profile {
|
||||
^hat {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Capability Rules
|
||||
Variables
|
||||
---------
|
||||
|
||||
AppArmor supports coarse-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:
|
||||
Variables are represented using the syntax `@{variable_name}`, are set before a profile begins, and are read inside of a profile. As variables are not profile rules, they are not terminated with a comma. They can have multiple values, with all of them being included when the variable is expanded.
|
||||
|
||||
Examples of variable assignment and usage:
|
||||
|
||||
```
|
||||
/profile {
|
||||
capability setuid,
|
||||
capability setgid,
|
||||
}
|
||||
# Assignment of a single value
|
||||
@{alphabet_string}=abcdefghijklmnopqrstuvwxyz
|
||||
# Assignment of multiple values
|
||||
@{digits}=1 2 3 4 5 6 7 8 9 0
|
||||
@{hexdigits}=@{digits}
|
||||
@{hexdigits}+=a b c d e f
|
||||
|
||||
profile example {
|
||||
# @{hexdigits} will expand to allow any of the 16 hex digits
|
||||
/var/cache/our_program/@{hexdigits}/** rw,
|
||||
}
|
||||
```
|
||||
|
||||
The include file `<tunables/global>` includes many variables that may be of use for writing profiles.
|
||||
|
||||
The special variable `@{profile_name}` contains the name of the current profile.
|
||||
|
||||
Capability Rules
|
||||
----------------
|
||||
|
||||
AppArmor supports coarse-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,
|
||||
}
|
||||
```
|
||||
|
||||
Multiple capabilities can be specified as a space-separated list.
|
||||
|
||||
## Network Rules
|
||||
Network Rules
|
||||
-------------
|
||||
|
||||
AppArmor currently supports coarse-grained access to networking via network rules. For example, a network daemon might need:
|
||||
AppArmor currently supports coarse-grained access to networking via
|
||||
network rules. For example, a network daemon might need:
|
||||
|
||||
```
|
||||
/profile {
|
||||
/profile {
|
||||
# Use "inet" for IPv4 only, "inet6" for IPv6 only, or omit for both
|
||||
network inet dgram, # can also say "udp" instead of "dgram"
|
||||
network inet stream, # can also say "tcp" instead of "stream"
|
||||
}
|
||||
network inet dgram, # can also say "udp" instead of "dgram"
|
||||
network inet stream, # can also say "tcp" instead of "stream"
|
||||
}
|
||||
```
|
||||
|
||||
Or a packet analyzer might need:
|
||||
|
||||
```
|
||||
/profile {
|
||||
network raw,
|
||||
network packet,
|
||||
}
|
||||
/profile {
|
||||
network raw,
|
||||
network packet,
|
||||
}
|
||||
```
|
||||
|
||||
## Rlimit Rules
|
||||
Rlimit Rules
|
||||
------------
|
||||
|
||||
Apparmor can set limits on the "hard limit" values of setrlimit that a process is allowed to set for itself. However, since rlimit enforcement is handled by a different part of the Linux kernel, no Apparmor audit message will be printed when an rlimit is enforced.
|
||||
|
||||
## Signal Rules
|
||||
Signal Rules
|
||||
------------
|
||||
|
||||
Example signal rules are as follows:
|
||||
|
||||
|
@ -151,7 +215,8 @@ Example signal rules are as follows:
|
|||
|
||||
For a signal to succeed, its sender must have permission to send the signal and its target must have permission to receive the signal.
|
||||
|
||||
## Ptrace Rules
|
||||
Ptrace Rules
|
||||
------------
|
||||
|
||||
There are four classes of ptrace operations:
|
||||
|
||||
|
@ -164,203 +229,293 @@ The `peer=` option can be included to limit the profiles that the other process
|
|||
|
||||
Example:
|
||||
|
||||
```
|
||||
/profile {
|
||||
ptrace, # Allow all ptrace operations
|
||||
ptrace (readby, tracedby) peer=unconfined, # Allow unconfined processes to ptrace us
|
||||
}
|
||||
```
|
||||
|
||||
## 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,
|
||||
}
|
||||
/profile {
|
||||
ptrace, # Allow all ptrace operations
|
||||
ptrace (readby, tracedby) peer=unconfined, # Allow unconfined processes to ptrace us
|
||||
}
|
||||
```
|
||||
|
||||
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,
|
||||
}
|
||||
```
|
||||
|
||||
Entries for specific (non-globbed) directories should have a trailing slash at the end. For example, `/path/to/obj rw` grants permissions for a file `obj`, while `/path/to/obj/ rw` grants permissions for a directory `obj`.
|
||||
|
||||
File rules can contain special globbing characters that allow matching to multiple files (see File Globbing, below)
|
||||
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.
|
||||
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.
|
||||
|
||||
- <b>\*</b> - match zero or more characters at the directory level. When looking at the path as a string this will match every character except <b>/</b>
|
||||
- This will match dot files (file names starting with <b>.</b>), excepting the special dot files <b>.</b> and <b>..</b>, if it is placed immediately after the directory /
|
||||
eg. /dir/\*
|
||||
- This will not match an empty directory string eg. /dir//
|
||||
- pcre equivalent is (\[^/\\000\]\*)
|
||||
- <b>\*\*</b> - match 0 or more characters over multiple directory levels.
|
||||
- This will match dot files (file names starting with <b>.</b>), excepting the special dot files <b>.</b> and <b>..</b>, if it is placed immediately after the directory /
|
||||
eg. /dir/\*\*
|
||||
- pcre equivalent is (\[^\\000\]\*)
|
||||
- <b>?</b> - match a single character that is not <b>/</b>
|
||||
- pcre equivalent is \[^/\]
|
||||
- <b>{}</b> - 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 (|)
|
||||
- <b>\[\]</b> - character class
|
||||
- same as pcre syntax
|
||||
- <b>\[^\]</b> - inverted character class
|
||||
- same as pcre syntax
|
||||
- Nesting expressions in alternations (as of AppArmor 2.3):
|
||||
- escaping characters \\\*
|
||||
- expressing characters as \# \\001
|
||||
|
||||
- **\*** - 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
|
||||
|
||||
#### 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/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 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/** - 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/
|
||||
/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
|
||||
- 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).
|
||||
The owner keyword can be used as a qualifier making permission
|
||||
conditional on owning the file (process fsuid == file's uid).
|
||||
|
||||
```
|
||||
owner /foo rw,
|
||||
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)
|
||||
- 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.
|
||||
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
|
||||
- **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.
|
||||
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, 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:
|
||||
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,
|
||||
/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.
|
||||
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,
|
||||
/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.
|
||||
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).
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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:
|
||||
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,`
|
||||
|
||||
` /foo/bar w,`
|
||||
|
||||
The permissions to copy a file are:
|
||||
|
||||
```
|
||||
/foo/src r,
|
||||
/foo/dst w,
|
||||
/foo/src r,
|
||||
/foo/dst w,
|
||||
```
|
||||
|
||||
The permissions to move a file are:
|
||||
|
||||
```
|
||||
/foo/src rw,
|
||||
/foo/dst w,
|
||||
/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).
|
||||
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.
|
||||
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'.
|
||||
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.
|
||||
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
|
||||
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:
|
||||
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
|
||||
- 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
|
||||
}
|
||||
/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.
|
||||
**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.
|
||||
|
|
Loading…
Add table
Reference in a new issue