APPARMOR.D(5) AppArmor APPARMOR.D(5) (NAME) apparmor.d - AppArmor (DESCRIPTION) AppArmor apparmor_parser(8) AppArmor . AppArmor AppArmor apparmor(7) . (FORMAT) AppArmor . . . AppArmor . . (whitelist) . AppArmor (preamble) . ( /include ). AppArmor ( ) . include . BNF AppArmor AppArmor . AppArmor # () . #include (include) cpp(1) . PROFILE FILE = ( [ PREAMBLE ] [ PROFILE ] )* PREAMBLE = ( COMMENT | VARIABLE ASSIGNMENT | ALIAS RULE | INCLUDE | ABI )* . VARIABLE ASSIGNMENT = VARIABLE ('=' | '+=') ( ) 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 '"' ( open(2) ) MAGIC PATH = '<' relative path '>' /etc/apparmor.d/ . COMMENT = '#' TEXT [ '\r' ] '\n' TEXT = 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 = ( '/' AARE . VARIABLE . .) ATTACHMENT SPECIFICATION = [ PROFILE_EXEC_COND ] [ PROFILE XATTR CONDS ] PROFILE_EXEC_COND = FILEGLOB PROFILE XATTR CONDS = [ 'xattrs=' ] '(' PROFILE XATTR ')' PROFILE XATTR = '=' XATTR VALUE FILEGLOB XATTR VALUE FILEGLOB = FILEGLOB PROFILE FLAG CONDS = [ 'flags=' ] '(' PROFILE FLAGS ')' PROFILE FLAGS = PROFILE MODE | AUDIT_MODE | 'mediate_deleted' | 'attach_disconnected' | 'attach_disconnected.path='ABS PATH | 'chroot_relative' | 'debug' | 'interruptible' | 'kill.signal='SIGNAL | 'error='ERROR CODE ERROR CODE = ( 'E' errno(3) ) PROFILE MODE = 'enforce' | 'complain' | 'kill' | 'default_allow' | 'unconfined' | 'prompt' 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 | IO_URING RULE | USERNS RULE | ALL 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 = ( . "hat" aa_change_hat(2) . '^' (hat) '^' HATNAME ) QUALIFIER BLOCK = QUALIFIERS BLOCK INTEGER = (+ | -)? [[:digit:]]+ ACCESS TYPE = ( 'allow' | 'deny' ) QUALIFIERS = [ 'priority' '=' ] [ 'audit' ] [ ACCESS TYPE ] CAPABILITY RULE = [ QUALIFIERS ] 'capability' [ CAPABILITY LIST ] CAPABILITY LIST = ( CAPABILITY )+ CAPABILITY = ( 'CAP_' capabilities(7) ) NETWORK RULE = [ QUALIFIERS ] 'network' [ NETWORK ACCESS EXPR ] [ DOMAIN ] [ TYPE | PROTOCOL ] [ NETWORK LOCAL EXPR ] [ NETWORK PEER EXPR ] NETWORK ACCESS EXPR = ( NETWORK ACCESS | NETWORK ACCESS LIST ) NETWORK ACCESS = ( 'create' | 'bind' | 'listen' | 'accept' | 'connect' | 'shutdown' | 'getattr' | 'setattr' | 'getopt' | 'setopt' | 'send' | 'receive' | 'r' | 'w' | 'rw' ) . NETWORK ACCESS LIST = '(' NETWORK ACCESS ( [','] NETWORK ACCESS )* ')' 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' ) NETWORK LOCAL EXPR = ( NETWORK IP COND | NETWORK PORT COND )* . NETWORK PEER EXPR = 'peer' '=' '(' ( NETWORK IP COND | NETWORK PORT COND )+ ')' . NETWORK IP COND = 'ip' '=' ( 'none' | NETWORK IPV4 | NETWORK IPV6 ) NETWORK PORT COND = 'port' '=' ( NETWORK PORT | NETWORK PORT '-' NETWORK PORT ) NETWORK IPV4 = IPv4 '.' NETWORK IPV6 = IPv6 ':' . '::' NETWORK PORT = 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 = ( ext4 debugfs devfs ...) MOUNT FLAGS EXPRESSION = ( MOUNT FLAGS LIST | MOUNT EXPRESSION ) MOUNT FLAGS LIST = 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 = '(' 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 USERNS RULE = [ QUALIFIERS ] 'userns' [ USERNS ACCESS PERMISSIONS ] USERNS ACCESS PERMISSIONS = ( 'create' ) IO_URING RULE = [ QUALIFIERS ] 'io_uring' [ IO_URING ACCESS PERMISSIONS [ IO_URING LABEL ] IO_URING ACCESS PERMISSIONS = ( 'sqpoll' | 'override_creds' ) IO_URING LABEL = 'label' '=' '(' '"' AARE '"' | 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 = '(' 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 = '(' SIGNAL ACCESS ')' SIGNAL ACCESS = ( 'r' | 'w' | 'rw' | 'read' | 'write' | 'send' | 'receive' ) SIGNAL SET = 'set' '=' '(' SIGNAL LIST ')' SIGNAL LIST = SIGNAL SIGNAL = ( '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 = DBUS ACCESS DBUS ACCESS = ( 'send' | 'receive' | 'bind' | 'eavesdrop' | 'r' | 'read' | 'w' | 'write' | 'rw' ) . 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' ) . UNIX ACCESS LIST = '(' UNIX ACCESS ( [','] UNIX ACCESS )* ')' UNIX RULE CONDS = ( TYPE COND | PROTO COND ) . 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 )* . UNIX PEER EXPR = 'peer' '=' ( UNIX ADDRESS COND | UNIX LABEL COND )+ . 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' ) RLIMIT 'fsize' 'data' 'stack' 'core' 'rss' 'as' 'memlock' 'msgqueue' . RLIMIT NUMBER = 0 rlimit. RLIMIT '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' ) RLIMIT 'cpu' 'rttime' . RLIMIT 'cpu' >= 'seconds' . RLIMIT NICE = -20 19. RLIMIT 'nice' . FILE RULE = [ QUALIFIERS ] [ 'owner' ] ( 'file' | [ 'file' ] ( FILEGLOB ACCESS | ACCESS FILEGLOB ) [ '->' EXEC TARGET ] ) FILEGLOB = ( QUOTED FILEGLOB | UNQUOTED FILEGLOB ) QUOTED FILEGLOB = '"' UNQUOTED FILEGLOB '"' UNQUOTED FILEGLOB = ( '/' AARE . VARIABLE . . '/' .) AARE = ?*[]{}^ "Globbing (AARE)" . ACCESS = ( 'r' | 'w' | 'a' | 'l' | 'k' | 'm' | EXEC TRANSITION )+ ( .) EXEC TRANSITION = ( 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx' | 'Cx' | 'pix' | 'Pix' | 'cix' | 'Cix' | 'pux' | 'PUx' | 'cux' | 'CUx' | 'x' ) 'x' deny deny . EXEC TARGET = name EXEC TRANSITION . 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 RULE = 'all' (full path) . ( child profiles) . . (unconfined) . (Hats) aa_change_hat(2) API . aa_change_hat(2) . aa_change_hat(2) mod_apparmor(5) PAM pam_apparmor Tomcat valve tomcat_apparmor. change_profile(2) . libvirt . (Profile Head) . Name () . ( ps -Z) ipc . firefox firefox log_admin. /usr/bin/firefox (exec attachment conditional) . . Attachment Conditionals ( ) . ( ) . . . . . (Exec Attachment Conditional) . exec exec px cx ( ) . unconfined pix . ( ) exec . : Name . . (longest left match heuristic) . . exec . (Extended Attributes Attachment Conditional) AppArmor xattr(7) . /usr/bin "security.apparmor" "trusted" : /usr/bin/* xattrs(security.apparmor="trusted") { # ... } apparmor_xattrs(7) . Flags () . . (Profile Mode) . enforce . enforce EACCES EPERM DENIED . kill enforce EACCES EPERM . complain ALLOWED . default_allow apparmor . default_allow . unconfined allow deny audit . enforce allow . : default_allow allow all, . default_allow allow all, . unconfined unconfined . . . default_allow default_allow unconfined . deny allow unconfined . unconfined . : unconfined unconfined . unconfined default_allow . prompt (up call) . . (Audit Mode) AppArmor (audit) . audit (log) . (Misc modes) mediate_deleted AppArmor . attach_disconnected AppArmor . : (aliasing) . . attach_disconnected.path=ABS PATH attach_disconnected . chroot_relative chroot chroot (mount namespace) . debug . . . interruptible prompt . kill.signal=SIGNAL AppArmor kill kill . error=ERROR CODE AppArmor . (Access Modes) : r - (read) w - (write) -- append a - (append) -- write ux - (unconfined execute) Ux - -- (scrub the environment) px - (discrete profile execute) Px - -- cx - Cx - -- ix - (inherit execute) pix - Pix - -- cix - Cix - -- pux - (unconfined) PUx - -- cux - CUx - -- deny x - ( deny) m - PROT_EXEC mmap(2) l - (link) k - (lock) (Access Modes Details) r - (Read mode) . . w - (Write mode) . (unlink) . . (append) . a - (Append mode) . O_APPEND . . ux - (Unconfined execute mode) AppArmor . ( ) . . apparmor(7) . : 'ux' . AppArmor . 'ux' LD_PRELOAD . LD_PRELOAD . . . exec deny. Ux - -- (unconfined execute -- scrub the environment) 'Ux' 'ux' AppArmor unsafe_exec setuid. ( setuid/setgid ld.so(8) .) : 'Ux' . AppArmor . . . exec deny. px - (Discrete Profile execute mode) AppArmor . . : 'px' LD_PRELOAD . exec deny. Px - -- (Discrete Profile execute mode -- scrub the environment) 'Px' 'px' AppArmor unsafe_exec setuid. ( setuid/setgid ld.so(8) .) exec deny. cx - (Transition to Subprofile execute mode) AppArmor . . : 'cx' LD_PRELOAD . exec deny. Cx - -- (Transition to Subprofile execute mode -- scrub the environment) 'Cx' 'cx' AppArmor unsafe_exec setuid. ( setuid/setgid ld.so(8) .) exec deny. ix - (Inherit execute mode) AppArmor execve(2) . . . 'ix' . exec deny. (Profile transition with inheritance fallback execute mode) ( ) 'ix' . 'Pix' == 'Px' with fallback to 'ix' 'pix' == 'px' with fallback to 'ix' 'Cix' == 'Cx' with fallback to 'ix' 'cix' == 'cx' with fallback to 'ix' exec deny. (unconfined fallback) (domain transition) ( ) 'ux' ( 'pux' 'cux' ) 'Ux' ( 'PUx' 'CUx' ) . 'PUx' == 'Px' with fallback to 'Ux' 'pux' == 'px' with fallback to 'ux' 'CUx' == 'Cx' with fallback to 'Ux' 'cux' == 'cx' with fallback to 'ux' exec deny . deny x - (Deny execute) deny 'x' . 'ix' 'Px' 'px' 'Cx' 'cx' (fallback) deny . (Directed profile transitions) ('px' 'Px' 'pix' 'Pix' 'pux' 'PUx') ('cx' 'Cx' 'cix' 'Cix' 'cux' 'CUx') . . '->' : /bin/** px -> profile, exec . m - (Allow executable mapping) PROT_EXEC mmap(2) . (exploit) . AppArmor ( ) -L ld(1) LD_PRELOAD LD_LIBRARY_PATH ld.so(8) . l - (Link mode) . ( ). 'x' . k - (Lock mode) . (advisory) (mandatory) . (leading OR trailing access permissions) (glob) : rw /**, # leading permissions /** rw, # trailing permissions : l /foo -> /bar, # lead 'l' link permission is equivalent to link rules (Link rules) (hard link) - . subset . 'x' . : /file1 r, /file2 rwk, /link* rw, link subset /link* -> /**, link /link /file1 /file2 /link 'rw' /file1 /file1 'r' . /link /file2 'rw' /link 'rwk' /file2 . link 'l' . link . link 'l' : link /foo -> bar, l /foo -> /bar, 'l' link : /foo l, l /foo, link subset /foo -> /**, (Comments) # . . (shell scripts) . (Capabilities) (capabilities) capabilities(7) . AppArmor (advisory) open(2) read(2) write(2) IPC (root) . (Network Rules) AppArmor (coarse-grained) . socket(2) . . netlink(7) 'dgram' 'raw' . AppArmor . AppArmor . : network, #allow access to all networking network tcp, #allow access to tcp network inet tcp, #allow access to tcp only for inet4 addresses network inet6 tcp, #allow access to tcp only for inet6 addresses network netlink raw, #allow access to AF_NETLINK SOCK_RAW (Network permissions) . (peer) . create bind listen shutdown getattr setattr getopt setopt . . accept . connect send receive . inet/inet6 (Mediation of inet/inet6 family) AppArmor ip port (fine-grained) inet inet6 . ip IPv4 IPv6 '.' IPv4 ':' IPv6. '::' . recvfrom sendto . (unbound) IP none . IP 'none' . ip IP : IPv4 IPv6 none. INADDR_ANY in6addr_any ip : network ip=::, #allow in6addr_any network ip=0.0.0.0; #allow INADDR_ANY IP . network ip=127.0.0.1 port=8080, network peer=(ip=10.139.15.23 port=8081), network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9), network port=8080 peer=(port=8081), network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081), network ip=127.0.0.1 port=8080-8084, (Mount Rules) AppArmor (mount) mount . mount AppArmor mount(8) . mount mount remount umount mount . ( fstype ). mount AppArmor : 1. '=' . AppArmor : mount options=ro /dev/foo -> /mnt/, : $ mount -o ro /dev/foo /mnt : $ mount -o ro,atime /dev/foo /mnt $ mount -o rw /dev/foo /mnt 2. 'in' . AppArmor : mount options in (ro,atime) /dev/foo -> /mnt/, mount : $ mount -o ro /dev/foo /mnt $ mount -o ro,atime /dev/foo /mnt $ mount -o atime /dev/foo /mnt : $ 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 3. mount . mount . AppArmor : mount options=ro options=atime, mount : $ mount -o ro /dev/foo /mnt $ mount -o atime /dev/foo /mnt : $ mount -o ro,atime /dev/foo /mnt mount . mount AppArmor: mount options=ro, mount options=atime, mount : mount options=(ro,atime), mount options in (ro,atime), mount : mount, 'mount' . 'mount fstype=** options=** ** -> /**' . mount /dev/foo, /dev/foo . mount : $ mount /dev/foo /mnt $ mount -t ext3 /dev/foo /mnt $ mount -t vfat /dev/foo /mnt $ mount -o ro,atime,noexec,nodiratime /dev/foo /srv/some/mountpoint mount options=ro /dev/foo, /dev/foo . mount : $ mount -o ro /dev/foo /mnt $ mount -o ro /dev/foo /some/where/else mount options=(ro,atime) /dev/foo, /dev/foo inode . mount : $ mount -o ro,atime /dev/foo /mnt $ mount -o ro,atime /dev/foo /some/where/else mount options in (ro,atime) /dev/foo, (mount) /dev/foo 'ro' 'atime' ( ). mount: $ mount -o ro /dev/foo /mnt $ mount -o atime /dev/foo /some/where/else $ mount -o ro,atime /dev/foo /some/other/place mount options=ro /dev/foo, mount options=atime /dev/foo, /dev/foo /dev/foo . . : $ mount -o ro /dev/foo /mnt/1 $ mount -o atime /dev/foo /mnt/2 mount -> /mnt/**, /mnt/**. mount: $ mount /dev/foo1 /mnt/1 $ mount -o ro,atime,noexec,nodiratime /dev/foo2 /mnt/deep/path/foo2 mount options=ro -> /mnt/**, /mnt/** . mount: $ mount -o ro /dev/foo1 /mnt/1 $ mount -o ro /dev/foo2 /mnt/deep/path/foo2 mount fstype=ext3 options=(rw,atime) /dev/sdb1 -> /mnt/stick/, ext3 /dev/sdb1 /mnt/stick / . : $ mount -o rw,atime /dev/sdb1 /mnt/stick mount options=(ro, atime) options in (nodev, user) /dev/foo -> /mnt/, /dev/foo /mnt/ /dev/foo /mnt/ 'nodev' 'user'. : $ 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 (Message Queue) (AppArmor) POSIX SYSV . AppArmor . . AppArmor . (type) (label) . 'r' 'read' . 'w' 'write' . 'create' 'open' . 'delete' . 'getattr' 'setattr' . 'posix' 'sysv' . posix '/' SYSV . (policy label) . POSIX '/' SYSV . . AppArmor: # Allow all Message Queue access mqueue, # Explicitly allow all Message Queue access, mqueue (create, open, delete, read, write, getattr, setattr), # Explicitly deny use of Message Queue deny mqueue, # Allow all access for POSIX queue of name /bar mqueue type=posix /bar, # Allow create permission for a SYSV queue of label foo mqueue create label=foo 123, (User Namespace) (User namespaces) (sandboxing) . (root) . . AppArmor . . . : (unconfined) . . create . userns: # Allow all userns perms userns, # Allow creation of a userns userns create, IO_URing / . . IO Uring . . : io_uring (unconfined) . io_uring io_uring . sqpoll (polling thread) io_uring . override_creds io_uring (credentials) () . IO_URING: # Allow io_uring operations io_uring, # Allow creation of a polling thread io_uring sqpoll, # Allow task to override credentials during io_uring operation io_uring override_creds label=new_creds, Pivot Root pivot_root(2) . 'pivot_root' AppArmor pivot_root(2) . put_old pivot_root(2) 'pivot_root' 'oldroot=' . 'pivot_root' AppArmor (profile transition) pivot_root(2) . . AppArmor pivot_root(2) . 'pivot_root' '/' . 'pivot_root' : # 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, PTrace ptrace(2) . PTrace AppArmor PTrace PTrace . PTrace AppArmor . PTrace . trace tracedby ptrace(2) read readby proc(5) kcmp(2) (get_robust_list(2)) perf . ptrace (tracing) . trace tracedby . PTrace AppArmor: # 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, Signal signal(7) . AppArmor . AppArmor . . . send receive . AppArmor: # 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), DBus DBus . DBus . DBus (bus) AppArmor . DBus AppArmor DBus DBus . DBus AppArmor . ( ) . DBus AppArmor DBus . 'bind' (message rules) . 'send' 'receive' (service rules) . 'eavesdrop' 'bus' . 'r' 'read' 'receive' . 'w' 'write' 'send' . 'rw' 'send' 'receive' . DBus AppArmor . DBus . . DBus AppArmor: # Allow all DBus access dbus, # Explicitly allow all DBus access, dbus (send, receive, bind), # Deny send/receive/bind access to the session bus deny dbus bus=session, # Allow bind access for a particular name on any bus dbus bind name=com.example.ExampleName, # Allow receive access for a particular path and interface dbus receive path=/com/example/path interface=com.example.Interface, # Deny send/receive access to the system bus for a particular interface deny dbus bus=system interface=com.example.ExampleInterface, # Allow send access for a particular path, interface, member, and pair of # peer names: dbus send bus=session path=/com/example/path interface=com.example.Interface member=ExampleMethod peer=(name=(com.example.ExampleName1|com.example.ExampleName2)), # Allow receive access for all unconfined peers dbus receive peer=(label=unconfined), # Allow eavesdropping on the system bus dbus eavesdrop bus=system, # Allow and audit all eavesdropping audit dbus eavesdrop, (Unix socket rules) AppArmor (abstract) (anonymous) . . (nonportable) unix(7) . (Unix socket address paths) sun_path ( ) addr= . . AppArmor @ ( ) netstat -x. (null character) . AppArmor null \000 \x00 . * / . : unix addr=@*, (Autobound) sun_path . auto . : unix addr=auto, . bind . auto (peer addr) . : unix rw addr=auto, : unix rw addr=@[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9], . sun_path none . : unix addr=none, (autobind) (abstract) (anonymous) . (Unix socket permissions) . . ( sun_path) (label) . . . (local) (peer) . create bind listen shutdown getattr setattr getopt setopt . peer . accept . connect send receive . peer . : # unix, # unix (create, listen, accept, connect, send, receive, getattr, setattr, setopt, getopt), # deny unix, # profile_name unix peer=(label=@{profile_name}), # unconfined unix (receive) peer=(label=unconfined), # getattr shutdown unix (getattr, shutdown) addr=none, # SOCK_STREAM @bar # '/foo' unix (connect, receive, send) type=stream peer=(label=/foo,addr="@bar"), # # '/bar' '@foo' unix (accept, receive) addr=@foo peer=(label=/bar), (Abstract unix domain sockets autobind) (autobind) . @00001. . (coarse grained) . (fine grained) . : network unix, => unix, network unix stream, => unix stream, : unix bind addr=@example, : network unix, change_profile AppArmor API (change_profile api) . change_profile (confined) . AppArmor . change_profile -> **, API . exec change_profile api (exec time) change_profile api . Change_profile exec . change_profile /bin/bash -> new_profile, . . : change_profile /bin/bash -> {new_profile1,new_profile2,new_profile3}, change_profile api change_profile exec . : /bin/bash Px -> new_profile1, change_profile /bin/bash -> {new_profile1,new_profile2,new_profile3}, exec unsafe_exec (scrub the environment) setuid . ( setuid/setgid ld.so(8) .) safe unsafe AppArmor ( libc ). exec exec . change_profile safe /bin/bash -> new_profile, safe (parser) unsafe . exec safe . all all . (access qualifier) . : allow all, # deny file, deny unix, : (audit) audit access all, rlimit setrlimit(2) AppArmor . rlimit AppArmor (audit) . rlimit AppArmor . rlimit rlimit rlimit . rlimit . rlimit AppArmor (hard limit) (soft limit) . : set rlimit data <= 100M, set rlimit nproc <= 10, set rlimit nice <= 5, (Variables) AppArmor ( ) . . (parser) (expand) . ("") . AppArmor : @{HOME} @{HOMEDIRS} @{multiarch} @{pid} @{pids} @{PROC} @{securityfs} @{apparmorfs} @{sys} @{tid} @{run} @{XDG_DESKTOP_DIR} @{XDG_DOWNLOAD_DIR} @{XDG_TEMPLATES_DIR} @{XDG_PUBLICSHARE_DIR} @{XDG_DOCUMENTS_DIR} @{XDG_MUSIC_DIR} @{XDG_PICTURES_DIR} @{XDG_VIDEOS_DIR} /etc/apparmor.d/tunables . /etc/apparmor.d/tunables/home.d @{HOMEDIRS} /etc/apparmor.d/tunables/multiarch.d @{multiarch} /etc/apparmor.d/tunables/xdg-user-dirs.d @{XDG_*} . @{profile_name} . / (variable expansion) AppArmor . . : : @{HOME}=/home/*/ file rw @{HOME}/*, : file rw /home/*//*. AppArmor / (canonicalize) . : file rw /home/*/*, / posix (posix namespace) . : @{HOME}=/home/*/ file rw /@{HOME}/*, : file rw //home/*//*, : file rw //home/*/*, : // / . // ( ) . (Alias rules) AppArmor (alias rules) . (variable resolution) . (preamble) . /etc/apparmor.d/tunables/alias /etc/apparmor.d/tunables/global . /etc/apparmor.d/tunables/global AppArmor . (AARE) AARE (globbing syntax) csh(1) bash(1) zsh(1) . * '/' ** '/' ? '/' [abc] a b c [a-c] a b c [^a-c] a b c {ab,cd} ab cd . @{variable} . AppArmor ( /var/tmp/) . . /tmp/ : /tmp/* /tmp . /tmp/*/ /tmp . /tmp/** /tmp. /tmp/**/ /tmp. (Rule Qualifiers) . / . priority . -1000 1000 0 . (override) . . AppArmor . allow . . deny . audit (audit log) . deny . 'audit' . allow . owner euid/fsuid . (Qualifier Blocks) . audit { /foo r, network, } #include AppArmor AppArmor . '#include' cpp(1) '#include' . '#' '#include' 'if exists' . #include "/absolute/path" /absolute/path . #include "relative/path" relative/path . #include magic/path apparmor_parser(8) . /etc/apparmor.d/ AppArmor . AppArmor /etc/apparmor.d/abstractions/ . . abstractions/audio . abstractions/authentication . abstractions/base . abstractions/bash bash system(3) . abstractions/consoles sshd(8) xterm(1) . . abstractions/fonts . abstractions/gnome GNOME GNOME . abstractions/kde KDE KDE . abstractions/kerberosclient (kerberos) . abstractions/nameservice DNS LDAP NIS SMB . abstractions/perl perl . abstractions/user-download abstractions/user-mail abstractions/user-manpages abstractions/user-tmp abstractions/user-write "" . abstractions/wutmp wtmp(5) utmp(5) w(1) . abstractions/X X X . /etc/apparmor.d/tunables/ . @{HOME} @{HOMEDIRS} . . #include @{HOME} @{HOMEDIRS} . aa-autodep(8) aa-genprof(8) #include . ABI (Feature ABI) abi AppArmor . . abi abi . . . abi kernel abi . . ABI AppArmor 2.x AppArmor 3 ABI AppArmor 2.x . ABI ABI . ABI AppArmor 3 . (EXAMPLE) AppArmor: # which feature abi the policy was developed with abi , # 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 owner /proc/[0-9]*/stat r, /bin/bash ixr, /var/lib/baz/ r, owner /var/lib/baz/* rw, } } (FILES) /etc/apparmor.d/ (KNOWN BUGS) o mount mount . 'mount options=**,' 'mount,' . (LP: #965690) o mount fstype . fstype mount remount bind . o mount 'options' 'options in (ro,nodev) options in (atime)' 'options in (ro,nodev,atime)' . o mount 'in' . 'ro' 'rw' 'nodev' 'dev' 'options in (ro,nodev)' 'options in (rw,dev)' . (SEE ALSO) apparmor(7) apparmor_parser(8) apparmor_xattrs(7) aa-complain(1) aa-enforce(1) aa_change_hat(2) mod_apparmor(5) . AppArmor 4.1.7 2026-03-10 APPARMOR.D(5)