| 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) الگوبرداری شده است.
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' '=' <INTEGER> ] [ '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) را فراهم میکند.
حالتهای متفرقه (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) است و نویسهها فشرده نخواهند شد.
بهعنوان مثال:
منجر به بسط زیر خواهد شد:
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> رایجترین کاربرد است؛ این دستور 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 <tunables/global> را درج کند یا به نحوی اطمینان حاصل نماید که @{HOME} و @{HOMEDIRS} قبل از شروع تعریف پروفایل مقداردهی شدهاند. ابزارهای aa-autodep(8) و aa-genprof(8) به طور خودکار عبارت #include <tunables/global> را در پروفایلهای تولیدشده صادر میکنند.
ویژگی 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 <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,
}
}
فایلها (FILES)
- /etc/apparmor.d/
باگهای شناختهشده (KNOWN BUGS)
- گزینههای mount از تطبیق الگو پشتیبانی میکنند اما فلگهای mount به درستی با الگوهای مشخصشده اشتراک داده نمیشوند. به عنوان مثال، 'mount options=**,' باید معادل 'mount,' باشد، اما چنین نیست. (LP: #965690)
- هنگامی که فلگهای معینی از دستور mount استفاده میشوند ممکن است تطبیق با fstype انجام نشود. به طور مشخص، تطبیق fstype در حال حاضر فقط هنگام ایجاد یک mount جدید کار میکند و نه remount، bind و غیره.
- قواعد mount با چند شرط 'options' طبق مستندات اعمال نمیشوند بلکه به گونهای ادغام میگردند که 'options in (ro,nodev) options in (atime)' معادل 'options in (ro,nodev,atime)' خواهد بود.
- هنگام مشخص کردن گزینههای 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) و https://wiki.apparmor.net.
| 2026-03-10 | AppArmor 4.1.7 |