apparmor.d โ syntax of security profiles for AppArmor, fed to the policy enforcement module via apparmor_parser(8).
| ๐ Use Case | โ๏ธ Command | ๐ Description |
|---|---|---|
| ๐ Define a profile | profile /usr/bin/app { โฆ } | Create a new profile for an executable |
| ๐ Allow readโonly file | /path/file r, | Grant read access to a file |
| ๐ Allow all networking | network, | Permit all socket operations |
| ๐ก๏ธ Allow a capability | capability net_raw, | Grant a specific Linux capability (without CAP_ prefix) |
| ๐ Exec to subprofile | /usr/bin/app cx -> sub_name, | Transition to a child profile on exec |
| โ Deny access | deny /path/file w, | Explicitly block write (and log only if audit is added) |
| ๐งฉ Include abstraction | #include <abstractions/base> | Pull in a common set of permissions |
| ๐ Set resource limit | set rlimit nproc <= 50, | Cap the number of processes |
| ๐ Mount rule | mount options=ro /dev/sda1 -> /mnt/, | Allow mounting a block device as readโonly |
| ๐ณ Pivot root | pivot_root oldroot=/old/ /newroot/, | Change the root filesystem and keep old root accessible |
| ๐ Ptrace control | ptrace (read, trace) peer=/usr/bin/app, | Allow tracing a specific profile |
| ๐ก Signal rule | signal set=(kill) peer=unconfined, | Allow receiving SIGKILL from unconfined processes |
| ๐ฅ๏ธ DBus access | dbus, | Full bus access (send/receive/bind/eavesdrop) |
| ๐๏ธ Unix socket | unix, | Full control over unix domain sockets |
AppArmor profiles describe mandatory access rights granted to given programs. They are compiled by apparmor_parser(8) into kernelโenforced rules. For an overview, see apparmor(7).
Policy is written in a declarative language; order of rules within a section or block does not matter. It can be split over multiple files. Each file begins with a preamble (variables, aliases, includes, feature ABI) and then defines profiles. Once a profile block starts, no preamble rules may follow. Comments start with # except that #include acts like a preโprocessor include.
The following is a BNFโstyle description of AppArmor policy configuration files:
PROFILE FILE = ( [ PREAMBLE ] [ PROFILE ] )*
PREAMBLE = ( COMMENT | VARIABLE ASSIGNMENT | ALIAS RULE | INCLUDE | ABI )*
Variable assignment and alias rules must come before the profile.
VARIABLE ASSIGNMENT = VARIABLE ('=' | '+=') (space separated values)
VARIABLE = '@{' ALPHA [ ( ALPHANUMERIC | '_' ) ... ] '}'
ALIAS RULE = 'alias' ABS PATH '->' REWRITTEN ABS PATH ','
INCLUDE = ( '#include' | 'include' ) [ 'if exists' ] ( ABS PATH | MAGIC PATH )
ABI = ( 'abi' ) ( ABS PATH | MAGIC PATH ) ','
ABS PATH = '"' path '"' (the path is passed to open(2))
MAGIC PATH = '<' relative path '>'
The path is relative to /etc/apparmor.d/.
COMMENT = '#' TEXT [ '\r' ] '\n'
TEXT = any characters
PROFILE = ( PROFILE HEAD ) [ ATTACHMENT SPECIFICATION ] [ PROFILE FLAG CONDS ] '{' ( RULES )* '}'
PROFILE HEAD = [ 'profile' ] FILEGLOB | 'profile' PROFILE NAME
PROFILE NAME ( UNQUOTED PROFILE NAME | QUOTED PROFILE NAME )
QUOTED PROFILE NAME = '"' UNQUOTED PROFILE NAME '"'
UNQUOTED PROFILE NAME = (must start with alphanumeric character (after variable expansion), or '/' AARE have special meanings; see below. May include VARIABLE. Rules with embedded spaces or tabs must be quoted.)
ATTACHMENT SPECIFICATION = [ PROFILE_EXEC_COND ] [ PROFILE XATTR CONDS ]
PROFILE_EXEC_COND = FILEGLOB
PROFILE XATTR CONDS = [ 'xattrs=' ] '(' comma or white space separated list of PROFILE XATTR ')'
PROFILE XATTR = extended attribute name '=' XATTR VALUE FILEGLOB
XATTR VALUE FILEGLOB = FILEGLOB
PROFILE FLAG CONDS = [ 'flags=' ] '(' comma or white space separated list of PROFILE FLAGS ')'
PROFILE FLAGS = PROFILE MODE | AUDIT_MODE | 'mediate_deleted' | 'attach_disconnected' | 'chroot_relative'
PROFILE MODE = 'enforce' | 'complain' | 'kill' | 'unconfined'
AUDIT MODE = 'audit'
RULES = [ ( LINE RULES | COMMA RULES ',' | BLOCK RULES )
LINE RULES = ( COMMENT | INCLUDE ) [ '\r' ] '\n'
COMMA RULES = ( CAPABILITY RULE | NETWORK RULE | MOUNT RULE | PIVOT ROOT RULE | UNIX RULE | FILE RULE | LINK RULE | CHANGE_PROFILE RULE | RLIMIT RULE | DBUS RULE | MQUEUE RULE )
BLOCK RULES = ( SUBPROFILE | HAT | QUALIFIER BLOCK )
SUBPROFILE = 'profile' PROFILE NAME [ ATTACHMENT SPECIFICATION ] [ PROFILE FLAG CONDS ] '{' ( RULES )* '}'
HAT = ('hat' | '^') HATNAME [ PROFILE FLAG CONDS ] '{' ( RULES )* '}'
HATNAME = (must start with alphanumeric character. See aa_change_hat(2) for a description of how this "hat" is used. If '^' is used to start a hat then there is no space between the '^' and HATNAME)
QUALIFIER BLOCK = QUALIFIERS BLOCK
ACCESS TYPE = ( 'allow' | 'deny' )
QUALIFIERS = [ 'audit' ] [ ACCESS TYPE ]
CAPABILITY RULE = [ QUALIFIERS ] 'capability' [ CAPABILITY LIST ]
CAPABILITY LIST = ( CAPABILITY )+
CAPABILITY = (lowercase capability name without 'CAP_' prefix; see capabilities(7))
NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ] [ TYPE | PROTOCOL ]
DOMAIN = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' | 'mctp' ) ','
TYPE = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
PROTOCOL = ( 'tcp' | 'udp' | 'icmp' )
MOUNT RULE = ( MOUNT | REMOUNT | UMOUNT )
MOUNT = [ QUALIFIERS ] 'mount' [ MOUNT CONDITIONS ] [ SOURCE FILEGLOB ] [ '->' [ MOUNTPOINT FILEGLOB ]
REMOUNT = [ QUALIFIERS ] 'remount' [ MOUNT CONDITIONS ] MOUNTPOINT FILEGLOB
UMOUNT = [ QUALIFIERS ] 'umount' [ MOUNT CONDITIONS ] MOUNTPOINT FILEGLOB
MOUNT CONDITIONS = [ ( 'fstype' | 'vfstype' ) ( '=' | 'in' ) MOUNT FSTYPE EXPRESSION ] [ 'options' ( '=' | 'in' ) MOUNT FLAGS EXPRESSION ]
MOUNT FSTYPE EXPRESSION = ( MOUNT FSTYPE LIST | MOUNT EXPRESSION )
MOUNT FSTYPE LIST = Comma separated list of valid filesystem and virtual filesystem types (eg ext4, debugfs, devfs, etc)
MOUNT FLAGS EXPRESSION = ( MOUNT FLAGS LIST | MOUNT EXPRESSION )
MOUNT FLAGS LIST = Comma separated list of MOUNT FLAGS.
MOUNT FLAGS = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nostrictatime' | 'lazytime' | 'nolazytime' | 'nouser' | 'user' | 'symfollow' | 'nosymfollow' )
MOUNT EXPRESSION = ( ALPHANUMERIC | AARE ) ...
MQUEUE_RULE = [ QUALIFIERS ] 'mqueue' [ MQUEUE ACCESS PERMISSIONS ] [ MQUEUE TYPE ] [ MQUEUE LABEL ] [ MQUEUE NAME ]
MQUEUE ACCESS PERMISSIONS = MQUEUE ACCESS | MQUEUE ACCESS LIST
MQUEUE ACCESS LIST = '(' Comma or space separated list of MQUEUE ACCESS ')'
MQUEUE ACCESS = ( 'r' | 'w' | 'rw' | 'read' | 'write' | 'create' | 'open' | 'delete' | 'getattr' | 'setattr' )
MQUEUE TYPE = 'type' '=' ( 'posix' | 'sysv' )
MQUEUE LABEL = 'label' '=' '(' '"' AARE '"' | AARE ')'
MQUEUE NAME = AARE
PIVOT ROOT RULE = [ QUALIFIERS ] pivot_root [ oldroot=OLD PUT FILEGLOB ] [ NEW ROOT FILEGLOB ] [ '->' PROFILE NAME ]
SOURCE FILEGLOB = FILEGLOB
MOUNTPOINT FILEGLOB = FILEGLOB
OLD PUT FILEGLOB = FILEGLOB
PTRACE_RULE = [ QUALIFIERS ] 'ptrace' [ PTRACE ACCESS PERMISSIONS ] [ PTRACE PEER ]
PTRACE ACCESS PERMISSIONS = PTRACE ACCESS | PTRACE ACCESS LIST
PTRACE ACCESS LIST = '(' Comma or space separated list of PTRACE ACCESS ')'
PTRACE ACCESS = ( 'r' | 'w' | 'rw' | 'read' | 'readby' | 'trace' | 'tracedby' )
PTRACE PEER = 'peer' '=' AARE
SIGNAL_RULE = [ QUALIFIERS ] 'signal' [ SIGNAL ACCESS PERMISSIONS ] [ SIGNAL SET ] [ SIGNAL PEER ]
SIGNAL ACCESS PERMISSIONS = SIGNAL ACCESS | SIGNAL ACCESS LIST
SIGNAL ACCESS LIST = '(' Comma or space separated list of SIGNAL ACCESS ')'
SIGNAL ACCESS = ( 'r' | 'w' | 'rw' | 'read' | 'write' | 'send' | 'receive' )
SIGNAL SET = 'set' '=' '(' SIGNAL LIST ')'
SIGNAL LIST = Comma or space separated list of SIGNALS
SIGNALS = ( 'hup' | 'int' | 'quit' | 'ill' | 'trap' | 'abrt' | 'bus' | 'fpe' | 'kill' | 'usr1' | 'segv' | 'usr2' | 'pipe' | 'alrm' | 'term' | 'stkflt' | 'chld' | 'cont' | 'stop' | 'stp' | 'ttin' | 'ttou' | 'urg' | 'xcpu' | 'xfsz' | 'vtalrm' | 'prof' | 'winch' | 'io' | 'pwr' | 'sys' | 'emt' | 'exists' | 'rtmin+0' ... 'rtmin+32' )
SIGNAL PEER = 'peer' '=' AARE
DBUS RULE = ( DBUS MESSAGE RULE | DBUS SERVICE RULE | DBUS EAVESDROP RULE | DBUS COMBINED RULE )
DBUS MESSAGE RULE = [ QUALIFIERS ] 'dbus' [ DBUS ACCESS EXPRESSION ] [ DBUS BUS ] [ DBUS PATH ] [ DBUS INTERFACE ] [ DBUS MEMBER ] [ DBUS PEER ]
DBUS SERVICE RULE = [ QUALIFIERS ] 'dbus' [ DBUS ACCESS EXPRESSION ] [ DBUS BUS ] [ DBUS NAME ]
DBUS EAVESDROP RULE = [ QUALIFIERS ] 'dbus' [ DBUS ACCESS EXPRESSION ] [ DBUS BUS ]
DBUS COMBINED RULE = [ QUALIFIERS ] 'dbus' [ DBUS ACCESS EXPRESSION ] [ DBUS BUS ]
DBUS ACCESS EXPRESSION = ( DBUS ACCESS | '(' DBUS ACCESS LIST ')' )
DBUS BUS = 'bus' '=' '(' 'system' | 'session' | '"' AARE '"' | AARE ')'
DBUS PATH = 'path' '=' '(' '"' AARE '"' | AARE ')'
DBUS INTERFACE = 'interface' '=' '(' '"' AARE '"' | AARE ')'
DBUS MEMBER = 'member' '=' '(' '"' AARE '"' | AARE ')'
DBUS PEER = 'peer' '=' '(' [ DBUS NAME ] [ DBUS LABEL ] ')'
DBUS NAME = 'name' '=' '(' '"' AARE '"' | AARE ')'
DBUS LABEL = 'label' '=' '(' '"' AARE '"' | AARE ')'
DBUS ACCESS LIST = Comma separated list of DBUS ACCESS
DBUS ACCESS = ( 'send' | 'receive' | 'bind' | 'eavesdrop' | 'r' | 'read' | 'w' | 'write' | 'rw' )
Some accesses are incompatible with some rules; see below.
AARE = ?*[]{}^
See below for meanings.
UNIX RULE = [ QUALIFIERS ] 'unix' [ UNIX ACCESS EXPR ] [ UNIX RULE CONDS ] [ UNIX LOCAL EXPR ] [ UNIX PEER EXPR ]
UNIX ACCESS EXPR = ( UNIX ACCESS | UNIX ACCESS LIST )
UNIX ACCESS = ( 'create' | 'bind' | 'listen' | 'accept' | 'connect' | 'shutdown' | 'getattr' | 'setattr' | 'getopt' | 'setopt' | 'send' | 'receive' | 'r' | 'w' | 'rw' )
Some access modes are incompatible with some rules or require additional parameters.
UNIX ACCESS LIST = '(' UNIX ACCESS ( [','] UNIX ACCESS )* ')'
UNIX RULE CONDS = ( TYPE COND | PROTO COND )
Each cond can appear at most once.
TYPE COND = 'type' '=' ( AARE | '(' ( '"' AARE '"' | AARE )+ ')' )
PROTO COND = 'protocol' '=' ( AARE | '(' ( '"' AARE '"' | AARE )+ ')' )
UNIX LOCAL EXPR = ( UNIX ADDRESS COND | UNIX LABEL COND | UNIX ATTR COND | UNIX OPT COND )*
Each cond can appear at most once.
UNIX PEER EXPR = 'peer' '=' ( UNIX ADDRESS COND | UNIX LABEL COND )+
Each cond can appear at most once.
UNIX ADDRESS COND 'addr' '=' ( AARE | '(' '"' AARE '"' | AARE ')' )
UNIX LABEL COND 'label' '=' ( AARE | '(' '"' AARE '"' | AARE ')' )
UNIX ATTR COND 'attr' '=' ( AARE | '(' '"' AARE '"' | AARE ')' )
UNIX OPT COND 'opt' '=' ( AARE | '(' '"' AARE '"' | AARE ')' )
RLIMIT RULE = 'set' 'rlimit' [RLIMIT '<=' RLIMIT VALUE ]
RLIMIT = ( 'cpu' | 'fsize' | 'data' | 'stack' | 'core' | 'rss' | 'nofile' | 'ofile' | 'as' | 'nproc' | 'memlock' | 'locks' | 'sigpending' | 'msgqueue' | 'nice' | 'rtprio' | 'rttime' )
RLIMIT VALUE = ( RLIMIT SIZE | RLIMIT NUMBER | RLIMIT TIME | RLIMIT NICE )
RLIMIT SIZE = NUMBER ( 'K' | 'M' | 'G' )
Only applies to RLIMIT of 'fsize', 'data', 'stack', 'core', 'rss', 'as', 'memlock', 'msgqueue'.
RLIMIT NUMBER = number from 0 to max rlimit value.
Only applies to RLIMIT of 'ofile', 'nofile', 'locks', 'sigpending', 'nproc', 'rtprio'.
RLIMIT TIME = NUMBER ( 'us' | 'microsecond' | 'microseconds' | 'ms' | 'millisecond' | 'milliseconds' | 's' | 'sec' | 'second' | 'seconds' | 'min' | 'minute' | 'minutes' | 'h' | 'hour' | 'hours' | 'd' | 'day' | 'days' | 'week' | 'weeks' )
Only applies to RLIMIT of 'cpu' and 'rttime'. RLIMIT 'cpu' only allows units >= 'seconds'.
RLIMIT NICE = a number between -20 and 19.
Only applies to RLIMIT of 'nice'.
FILE RULE = [ QUALIFIERS ] [ 'owner' ] ( 'file' | [ 'file' ] ( FILEGLOB ACCESS | ACCESS FILEGLOB ) [ '->' EXEC TARGET ] )
FILEGLOB = ( QUOTED FILEGLOB | UNQUOTED FILEGLOB )
QUOTED FILEGLOB = '"' UNQUOTED FILEGLOB '"'
UNQUOTED FILEGLOB = (must start with '/' (after variable expansion), AARE have special meanings; see below. May include VARIABLE. Rules with embedded spaces or tabs must be quoted. Rules must end with '/' to apply to directories.)
ACCESS = ( 'r' | 'w' | 'a' | 'l' | 'k' | 'm' | EXEC TRANSITION )+ (not all combinations are allowed; see below.)
EXEC TRANSITION = ( 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx' | 'Cx' | 'pix' | 'Pix' | 'cix' | 'Cix' | 'pux' | 'PUx' | 'cux' | 'CUx' | 'x' )
A bare 'x' is only allowed in rules with the deny qualifier, everything else only without the deny qualifier.
EXEC TARGET = name
Requires EXEC TRANSITION specified.
LINK RULE = QUALIFIERS [ 'owner' ] 'link' [ 'subset' ] FILEGLOB '->' FILEGLOB
ALPHA = ('a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')
ALPHANUMERIC = ('0', '1', '2', ... '9', 'a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')
CHANGE_PROFILE RULE = 'change_profile' [ [ EXEC MODE ] EXEC COND ] [ '->' PROFILE NAME ]
EXEC_MODE = ( 'safe' | 'unsafe' )
EXEC COND = FILEGLOB
All resources and programs need a full path. There may be any number of subprofiles (child profiles) limited only by kernel memory. Subprofile names are limited to 974 characters. Hats are a special child profile used with aa_change_hat(2). Applications written to use aa_change_hat(2) can take advantage of subprofiles; several exist (e.g., Apache module, PAM module, Tomcat valve). Applications using change_profile(2) transition permanently to the specified profile (e.g., libvirt).
The profile head consists of a unique name, optional attachment conditionals, and control flags.
The name is its identifier, shown during introspection (e.g., ps -Z). It is recommended to be short and meaningful. If the name is a full absolute path and no exec attachment conditional is specified, the name serves as the exec attachment, but this is deprecated because it makes names long and hard to read.
Used during profile transitions to determine the best match. If no conditionals are specified, the profile is only used when explicitly referenced by a transition. The exec attachment conditional uses longest left match heuristic; if ambiguous, exec is denied.
Used only during exec operations with px or cx (or derivatives). Can contain variables and patterns. Unconfined tasks also use it with a pix transition.
Target files based on xattr(7). Example: /usr/bin/* xattrs(security.apparmor="trusted") { โฆ }. See apparmor_xattrs(7).
Profile flags modify behavior; if specified, they override conflicting rules in the body.
audit ๐ Force logging of both allowed and denied actions.
File permission access modes combine the following characters:
r ๐ readw โ๏ธ write โ conflicts with appenda โ append โ conflicts with writeux ๐ก๏ธ unconfined executeUx ๐ก๏ธ unconfined execute โ scrub environmentpx ๐ discrete profile executePx ๐ discrete profile execute โ scrub environmentcx ๐ถ transition to subprofile on executeCx ๐ถ transition to subprofile on execute โ scrub environmentix ๐งฌ inherit executepix ๐โ๐งฌ discrete profile execute with inherit fallbackPix ๐โ๐งฌ discrete profile execute with inherit fallback โ scrub environmentcix ๐ถโ๐งฌ transition to subprofile with inherit fallbackCix ๐ถโ๐งฌ transition to subprofile with inherit fallback โ scrub environmentpux ๐โ๐ก๏ธ discrete profile execute with fallback to unconfinedPUx ๐โ๐ก๏ธ discrete profile execute with fallback to unconfined โ scrub environmentcux ๐ถโ๐ก๏ธ transition to subprofile with fallback to unconfinedCUx ๐ถโ๐ก๏ธ transition to subprofile with fallback to unconfined โ scrub environmentdeny x โ disallow execute (only with deny qualifier)m ๐ง allow PROT_EXEC with mmap(2)l ๐ linkk ๐ lockr โ Read mode
๐ Allows read access to the file or directory listing. Required for shell scripts and interpreted content.
w โ Write mode
โ๏ธ Allows write access. Required to unlink (remove) files. Not needed to rename or create files within a directory. Incompatible with a.
a โ Append mode
โ Limited appendingโonly write; prevents opening for write unless O_APPEND is passed. Incompatible with w.
ux โ Unconfined execute mode
๐ก๏ธ Executes without any AppArmor profile. โ ๏ธ Very dangerous: no environment scrubbing; LD_PRELOAD etc. can influence the callee. Use only when absolutely necessary. Incompatible with other exec transitions and deny.
Ux โ unconfined execute โ scrub the environment
๐ก๏ธ Same as ux but kernelโs unsafe_exec scrubs the environment (like setuid). Still dangerous. Incompatible with other exec transitions and deny.
px โ Discrete Profile execute mode
๐ Forces a transition to a discrete profile. If no profile exists, access is denied. โ ๏ธ No environment scrubbing. Incompatible with other exec transitions and deny.
Px โ Discrete Profile execute mode โ scrub the environment
๐ Like px but with unsafe_exec scrubbing. Incompatible with other exec transitions and deny.
cx โ Transition to Subprofile execute mode
๐ถ Forces a transition to a local (sub)profile. If no profile exists, denied. โ ๏ธ No scrubbing. Incompatible with other exec transitions and deny.
Cx โ Transition to Subprofile execute mode โ scrub the environment
๐ถ Like cx with scrubbing. Incompatible with other exec transitions and deny.
ix โ Inherit execute mode
๐งฌ No domain transition; the executed resource inherits the current profile. No scrubbing needed. Incompatible with other exec transitions and deny.
Profile transition with inheritance fallback
Pix, pix, Cix, cix attempt the primary transition and fall back to ix if the target profile is missing. Incompatible with other exec transitions and deny.
Profile transition with unconfined fallback
PUx, pux, CUx, cux fall back to Ux/ux if the target profile is missing. Incompatible with other exec transitions and deny.
deny x โ Deny execute
โ Only bare x is allowed in deny rules; conflicts with all other exec transitions.
Directed profile transitions
๐ฏ Use -> to explicitly name the target profile, e.g., /bin/** px -> myprofile,. Incompatible with other exec transitions.
m โ Allow executable mapping
๐ง Allows mmap(2) with PROT_EXEC. Used to control which libraries can be mapped executable, to limit invalid -L flags or LD_PRELOAD abuse.
l โ Link mode
๐ Allows creation of hard links. The new link must have a subset of permissions of the original (except the destination doesnโt need link access).
k โ lock mode
๐ Allows locking the file (advisory and mandatory).
Leading vs. trailing permissions
๐ File rules can have permissions before or after the fileglob. Leading permissions permit further rule options, e.g., l /foo -> /bar, is equivalent to a link rule.
Specify permission to form a hard link as a target pair. If subset is specified, the linkโs permissions must be a subset of the targetโs permissions. Example:
/file1 r,
/file2 rwk,
/link* rw,
link subset /link* -> /**,
Linking /link to /file1 would be denied because the link has more permissions (rw) than the target (r). Linking to /file2 is allowed because rw โ rwk.
Start with # and run to end of line, same as shell scripts.
Enumerate allowed capabilities (see capabilities(7)). Granting some capabilities (e.g., loading kernel modules) can bypass AppArmor confinement.
Coarseโgrained mediation of socket(2) operations. No port or detailed protocol control beyond tcp/udp/raw. Netlink only dgram and raw. Rules are accumulated (union of permissions). Examples:
network, # all networking
network tcp, # only tcp
network inet tcp, # tcp over ipv4
network inet6 tcp, # tcp over ipv6
network netlink raw, # AF_NETLINK SOCK_RAW
Mediate mount operations (mount, remount, umount). Conditionals can be specified with = (exact match) or in (any combination of listed options). Multiple conditionals work as separate sets. For full details and examples, see the man page.
Mediate POSIX and SYSV message queues. Permissions: r/read, w/write, create, open, delete, getattr, setattr. Type can be specified with type=posix or type=sysv. Label and name constraints are available. Examples:
mqueue, # all access
mqueue (create, open, delete, read, write, getattr, setattr), # explicit all
deny mqueue, # deny all
mqueue type=posix /bar, # all access to POSIX queue /bar
mqueue create label=foo 123, # create permission for SYSV queue 123 with label foo
Mediate pivot_root(2). Paths must end with /. Optional oldroot prefix, new root, and profile transition. Examples:
pivot_root, # allow any pivot
pivot_root oldroot=/mnt/root/old/, # only specify old root
pivot_root /mnt/root/, # only new root
pivot_root oldroot=/mnt/root/old/ /mnt/root/, # both
pivot_root oldroot=/mnt/root/old/ /mnt/root/ -> /mnt/root/sbin/init, # with profile transition
Mediate ptrace(2) and some procfs, kcmp, futex, perf accesses. Permissions: trace/tracedby for ptrace itself, read/readby for other observability. Both tracer and target must have matching permissions. Peer can be restricted by label. Examples:
ptrace, # all access
ptrace (read, readby, trace, tracedby), # explicit all
deny ptrace (trace), # deny ptrace
ptrace (readby, tracedby) peer=unconfined, # allow unconfined to read/trace us
ptrace (trace) peer=/usr/bin/foo, # allow tracing /usr/bin/foo
Mediate signal(7). Permissions: send, receive (or r/w). Signal set can be restricted. Peer restrictions. The special โexistsโ signal governs PID existence checks. Examples:
signal, # all signals
deny signal (send) set=(hup, int), # deny sending HUP and INT
signal (receive) peer=unconfined, # receive from unconfined
signal (send) peer=/usr/bin/foo, # send to /usr/bin/foo
signal (receive, send) set=("exists"), # allow checking PID existence
signal peer=@{profile_name}, # allow signalling self
signal set=(rtmin+0 rtmin+32), # two realโtime signals
Mediation in conjunction with the DBus daemon. Permissions: send, receive, bind, eavesdrop (with synonyms). Message, service, eavesdrop, and combined forms. Restrict by bus, path, interface, member, peer. Examples:
dbus, # full access
dbus (send, receive, bind), # explicit all
deny dbus bus=session, # block session bus
dbus bind name=com.example.ExampleName, # bind to a specific name
dbus receive path=/com/example/path interface=com.example.Interface, # receive on that path/iface
deny dbus bus=system interface=com.example.ExampleInterface, # block system bus for an interface
dbus send bus=session path=... interface=... member=ExampleMethod peer=(name=(...)), # specific send
dbus receive peer=(label=unconfined), # receive from unconfined peers
dbus eavesdrop bus=system, # listen on system bus
audit dbus eavesdrop, # audit all eavesdropping
Fineโgrained mediation of unix domain sockets (abstract, anonymous; filesystem paths are mediated via file rules). Address conditionals: addr=@โฆ for abstract, addr=auto for autobound, addr=none for anonymous. Peer restrictions with label and addr. Local/peer permissions. Examples:
unix, # all permissions
unix (create, listen, accept, connect, send, receive, getattr, setattr, setopt, getopt), # explicit all
deny unix, # deny all
unix peer=(label=@{profile_name}), # create/use sockets with same profile
unix (receive) peer=(label=unconfined), # receive from unconfined
unix (getattr, shutdown) addr=none, # only anonymous sockets
unix (connect, receive, send) type=stream peer=(label=/foo,addr="@bar"), # stream connect to @bar by /foo
unix (accept, receive) addr=@foo peer=(label=/bar), # accept on @foo from /bar
Control selfโdirected profile transitions via the change_profile API. Can be restricted by executable name and target profile set. Execution environment scrubbing can be specified (safe/unsafe). Examples:
change_profile -> **, # transition to any profile
change_profile /bin/bash -> new_profile, # exec condition
change_profile /bin/bash -> {new1, new2, new3}, # set of profiles
change_profile safe /bin/bash -> new_profile, # with safe exec mode
Set and control resource limits. If a profile sets an rlimit, any higher current limit is lowered; changes beyond the set limit are restricted. Hard limit is enforced; soft โค hard. Examples:
set rlimit data <= 100M, # limit data segment to 100 MB
set rlimit nproc <= 10, # max 10 processes
set rlimit nice <= 5, # nice value โค 5
Embedded with @{variable}. Must be assigned before profile definitions. Many predefined variables (e.g., @{HOME}, @{PROC}, @{run}) are defined in tunables files. The special @{profile_name} is the current profile name.
Path rewriting for siteโspecific layouts, applied after variable resolution. Example: alias /home โ /new/home/. Systemโwide aliases in /etc/apparmor.d/tunables/alias.
Shellโlike patterns for file resources:
* โญ any characters except /** ๐ any characters including /? โ any single character except /[abc] ๐ค match a, b, or c[aโc] ๐ range a to c[^aโc] ๐ซ any character not in range{ab,cd} ๐งฉ expansion to two rulesDirectory matching: paths ending in / match only directories. Examples: /tmp/* files directly in /tmp; /tmp/*/ directories directly in /tmp; /tmp/** anything under /tmp; /tmp/**/ any directory under /tmp.
allow โ
default, permits matching requestsaudit ๐ log matching requestsdeny โ deny and do not log (unless combined with audit)owner ๐ค restricting to same euid/fsuid as the objectQualifier blocks apply qualifiers to multiple rules:
audit {
/foo r,
network,
}
Includes files inline, similar to cpp(1). #include "/absolute/path", #include "relative/path", #include <magic/path> (relative to /etc/apparmor.d/). Optional if exists skips missing files. Many common abstractions exist (console, audio, authentication, base, bash, etc.). Some abstractions rely on variables set in tunables.
Specifies the feature set the policy was developed for (e.g., abi <abi/3.0>,). When compiled, the kernelโs features and the policyโs ABI are merged. Using abi kernel is dangerous โ it should never be used in shipped policy. Backward compatibility with AppArmor 2.x is maintained by detecting missing ABI and applying a pinned default.
An example AppArmor profile:
# which feature abi the policy was developed with
abi <abi/3.0>,
# a variable definition in the preamble
@{HOME} = /home/*/ /root/
# a comment about foo.
/usr/bin/foo {
/bin/mount ux,
/dev/{,u}random r,
/etc/ld.so.cache r,
/etc/foo.conf r,
/etc/foo/* r,
/lib/ld-*.so* rmix,
/lib/lib*.so* r,
/proc/[0-9]** r,
/usr/lib/** r,
/tmp/foo.pid wr,
/tmp/foo.* lrw,
/@{HOME}/.foo_file rw,
/usr/bin/baz Cx -> baz,
# a comment about foo's hat (subprofile), bar.
^bar {
/lib/ld-*.so* rmix,
/usr/bin/bar rmix,
/var/spool/* rwl,
}
# a comment about foo's subprofile, baz.
profile baz {
#include <abstractions/bash>
owner /proc/[0-9]*/stat r,
/bin/bash ixr,
/var/lib/baz/ r,
owner /var/lib/baz/* rw,
}
}
/etc/init.d/boot.apparmor/etc/apparmor.d/mount options=**, is not equivalent to mount, (LP#965690).options conditionals are merged incorrectly: options in (ro,nodev) options in (atime) becomes options in (ro,nodev,atime).in, positive and negative flags both match; e.g., rw matches when ro is specified.apparmor(7), apparmor_parser(8), apparmor_xattrs(7), aa-complain(1), aa-enforce(1), aa_change_hat(2), mod_apparmor(5), and <https://wiki.apparmor.net>.
Generated by phpman v4.9.26-5-g7740029 Author: Che Dong Under GNU General Public License
2026-08-14 21:53 @2600:1f28:365:80b0:4d23:66fa:c2bb:7bae
CrawledBy CCBot/2.0 (https://commoncrawl.org/faq/)