Дар сатрҳои 4 ва 5 мо нимкалимаҳои дар суроғаи 20 ҷойгиршударо бор мекунем ва фармонро истифода мебарем jset санҷед, ки яке аз се муқаррар карда шудааст байракхо - пӯшидани ниқоби додашуда jset се битҳои муҳимтарин тоза карда мешаванд. Ду бит аз се бит ба мо мегӯянд, ки оё баста як қисми пакети пора-пораи IP аст ва агар ин тавр бошад, оё он порчаи охирин аст. Бити сеюм маҳфуз аст ва бояд сифр бошад. Мо намехоҳем бастаҳои нопурра ё шикастаро тафтиш кунем, аз ин рӯ ҳар се битро тафтиш мекунем.
Сатри 6 ҷолибтарин дар ин рӯйхат аст. Ифода ldxb 4*([14]&0xf) маънои онро дорад, ки мо ба реестр бор мекунем X камтарин чор бит аз байт понздаҳуми баста ба 4 зарб. Дарозии сарлавҳаи интернет Сарлавҳаи IPv4, ки дарозии сарлавҳаро бо калимаҳо нигоҳ медорад, бинобар ин шумо бояд ба 4 зарб кунед. Ҷолиб он аст, ки ифода 4*([14]&0xf) нишона барои схемаи махсуси адресатсия мебошад, ки онро танҳо дар ин шакл ва танҳо барои реестр истифода бурдан мумкин аст X, яъне. мо хам гуфта наметавонем ldb 4*([14]&0xf) на ldxb 5*([14]&0xf) (мо метавонем танҳо ҷуброни дигарро муайян кунем, масалан, ldxb 4*([16]&0xf)). Маълум аст, ки ин схемаи адресатсия ба BPF маҳз барои гирифтани он илова карда шудааст X (Феҳристи индекс) Дарозии сарлавҳаи IPv4.
Ҳамин тавр, дар сатри 7 мо кӯшиш мекунем, ки ним калимаро дар (X+16). Дар хотир доред, ки 14 байтро сарлавҳаи Ethernet ишғол мекунад ва X дорои дарозии сарлавҳаи IPv4, мо мефаҳмем, ки дар A Порти таъиноти TCP бор карда шудааст:
14 X 2 2
|ethernet header|ip header|source port|destination port|
Тавре ки дар боло зикр гардид, мо филтри худро ба васлаки сатри 5 бор мекунем ва пайваст мекунем, аммо дар сатрҳои 3 ва 4 чӣ мешавад? Маълум мешавад, ки ин libpcap ба мо ғамхорӣ мекунад - ба тавре ки баромади филтри мо бастаҳоеро дар бар нагирад, ки онро қонеъ намекунанд, китобхона мепайвандад филтри муҷаррад ret #0 (ҳамаи бастаҳоро партоед), розеткаро ба ҳолати ғайрибандӣ мегузарад ва кӯшиш мекунад, ки ҳамаи бастаҳоеро, ки аз филтрҳои қаблӣ боқӣ монда метавонанд, хориҷ кунед.
Дар маҷмӯъ, барои филтр кардани бастаҳо дар Linux бо истифода аз BPF классикӣ, шумо бояд филтр дар шакли сохтор дошта бошед struct sock_fprog ва розеткаи кушода, ки пас аз он филтрро бо истифода аз занги система ба васл кардан мумкин аст setsockopt.
Ҷолиб он аст, ки филтрро на танҳо хом, балки ба ҳама гуна розетка васл кардан мумкин аст. Ин ҷо намуна барномае, ки ҳама ба ҷуз ду байтҳои аввалро аз ҳама датаграммаҳои воридотии UDP қатъ мекунад. (Ман дар код шарҳҳо илова кардам, то мақоларо халалдор накунам.)
Ҳар як дастур 64 битро ишғол мекунад, ки дар он 16 битҳои аввал коди дастур мебошанд, баъд ду хати ҳашт-битӣ мавҷуданд, jt и jf, ва 32 бит барои далел K, ки максад аз он аз фармон ба фармон фарк мекунад. Масалан, фармон ret, ки барномаро қатъ мекунад, код дорад 6, ва арзиши бозгашт аз доимӣ гирифта мешавад K. Дар C, як дастури BPF ҳамчун сохтор муаррифӣ карда мешавад
Аммо, ин вариант хеле қулай нест. Ин аст он чизе ки барномасозони ядрои Linux асоснок карданд ва аз ин рӯ дар феҳрист tools/bpf ядроҳо шумо метавонед ассемблер ва ислоҳкунандаро барои кор бо классикии BPF пайдо кунед.
Илова ба стандарти BPF, Linux ва tools/bpf/bpf_asm дастгирй ва маҷмӯи ғайристандартӣ. Асосан, дастурҳо барои дастрасӣ ба майдонҳои сохтор истифода мешаванд struct sk_buff, ки бастаи шабакавиро дар ядро тавсиф мекунад. Аммо, инчунин намудҳои дигари дастурҳои ёрирасон мавҷуданд, масалан ldw cpu ба реестр бор карда мешавад A натиҷаи иҷро кардани функсияи ядро raw_smp_processor_id(). (Дар версияи нави BPF, ин васеъкуниҳои ғайристандартӣ барои таъмини барномаҳо бо маҷмӯи ёрирасонҳои ядро барои дастрасӣ ба хотира, сохторҳо ва тавлиди рӯйдодҳо васеъ карда шудаанд.) Ин аст мисоли ҷолиби филтр, ки дар он мо танҳо сарлавҳаҳои бастаҳо ба фазои корбар бо истифода аз васеъкунӣ poff, ҷуброни боркашонӣ:
ld poff
ret a
Дар васеъкунии BPF наметавонанд истифода шаванд tcpdump, аммо ин як сабаби хуб барои шинос шудан бо бастаи коммуналӣ аст netsniff-ng, ки дар байни дигар чизҳо, дорои барномаи пешрафта мебошад netsniff-ng, ки ба ғайр аз филтр бо истифода аз BPF, инчунин дорои генератори самараноки трафик, ва пешрафтатар аз tools/bpf/bpf_asm, як монтажчии BPF даъват карда шуд bpfc. Маҷмӯа дорои ҳуҷҷатҳои хеле муфассал аст, инчунин ба истинодҳо дар охири мақола нигаред.
секкомп
Ҳамин тавр, мо аллакай медонем, ки чӣ тавр навиштани барномаҳои BPF-и мураккабии худсарона ва омодаем, ки мисолҳои навро бубинем, ки аввалини онҳо технологияи seccomp мебошад, ки имкон медиҳад бо истифода аз филтрҳои BPF маҷмӯа ва маҷмӯи аргументҳои зангҳои системавиро идора кунад. раванди додашуда ва наслҳои он.
Нахустин версияи seccomp ба ядро соли 2005 илова карда шуд ва он қадар маъмул набуд, зеро он танҳо як вариантро фароҳам овард - маҳдуд кардани маҷмӯи зангҳои системавӣ барои раванд ба таври зерин: read, write, exit и sigreturn, ва процессе, ки коидахоро вайрон мекард, истифода бурда кушта шуд SIGKILL. Аммо, дар соли 2012, seccomp қобилияти истифодаи филтрҳои BPF-ро илова кард, ки ба шумо имкон медиҳад, ки маҷмӯи зангҳои системавии иҷозатдодашударо муайян кунед ва ҳатто далелҳои онҳоро тафтиш кунед. (Ҷолиб он аст, ки Chrome яке аз аввалин корбарони ин функсия буд ва мардуми Chrome дар айни замон механизми KRSI-ро дар асоси версияи нави BPF таҳия мекунанд ва ба мутобиқсозии Модулҳои Амнияти Linux иҷозат медиҳанд.) Истинодҳо ба ҳуҷҷатҳои иловагиро дар охир пайдо кардан мумкин аст. аз мақола.
Аҳамият диҳед, ки дар марказ аллакай мақолаҳо дар бораи истифодаи seccomp мавҷуданд, шояд касе мехоҳад онҳоро пеш аз хондани зерфаслҳои зерин (ё ба ҷои) хонад. Дар макола Контейнерҳо ва амният: seccomp намунаҳои истифодаи seccomp, ҳам версияи 2007 ва ҳам версияи истифодаи BPF (филтрҳо бо истифода аз libseccomp тавлид мешаванд), дар бораи пайвасти seccomp бо Docker сӯҳбат мекунанд ва инчунин истинодҳои муфидро пешкаш мекунанд. Дар макола Ҷудо кардани демонҳо бо systemd ё "барои ин ба шумо Docker лозим нест!" Он, аз ҷумла, чӣ гуна илова кардани рӯйхати сиёҳ ё рӯйхати сафеди зангҳои системаро барои демонҳои системавӣ дар бар мегирад.
Минбаъд мо мебинем, ки чӣ гуна филтрҳоро навиштан ва бор кардан лозим аст seccomp дар C луч ва бо истифода аз китобхона libseccomp ва тарафҳои мусбӣ ва манфии ҳар як вариант чист ва дар ниҳоят биёед бубинем, ки seccomp аз ҷониби барнома чӣ гуна истифода мешавад strace.
Навиштан ва боркунии филтрҳо барои seccomp
Мо аллакай медонем, ки чӣ гуна барномаҳои BPF нависед, аз ин рӯ биёед аввал интерфейси барномасозии seccomp-ро бубинем. Шумо метавонед филтрро дар сатҳи раванд насб кунед ва ҳамаи равандҳои кӯдак маҳдудиятҳоро мерос мегиранд. Ин бо истифода аз занги система анҷом дода мешавад seccomp(2):
Агар шумо хоҳед бинед, ки филтрҳои ҷустуҷӯии дуӣ чӣ гуна кор мекунанд, ба он назар андозед скрипти оддӣ, ки чунин барномаҳоро дар ассемблер BPF тавассути зангзании рақамҳои занги система тавлид мекунад, масалан:
$ echo 1 3 6 8 13 | ./generate_bin_search_bpf.py
ld [0]
jeq #6, bad
jgt #6, check8
jeq #1, bad
jeq #3, bad
ret #0x7fff0000
check8:
jeq #8, bad
jeq #13, bad
ret #0x7fff0000
bad: ret #0
Фоидаро ҳама медонад strace воситаи муҳим барои омӯзиши рафтори равандҳо дар Linux мебошад. Бо вуҷуди ин, бисёриҳо дар бораи он шунидаанд масъалаҳои иҷроиш ҳангоми истифодаи ин утилита. Гап дар сари он аст strace истифода бурда мешавад ptrace(2), ва дар ин механизм мо наметавонем муайян кунем, ки дар кадом маҷмӯи зангҳои система ба мо лозим аст, ки равандро қатъ кунем, масалан, фармонҳо.
$ time strace du /usr/share/ >/dev/null 2>&1
real 0m3.081s
user 0m0.531s
sys 0m2.073s
и
$ time strace -e open du /usr/share/ >/dev/null 2>&1
real 0m2.404s
user 0m0.193s
sys 0m1.800s
тақрибан дар як вақт коркард мешаванд, гарчанде ки дар ҳолати дуюм мо мехоҳем танҳо як занги системаро пайгирӣ кунем.
Варианти нав --seccomp-bpf, илова ба strace версияи 5.3, ба шумо имкон медиҳад, ки равандро чанд маротиба суръат бахшед ва вақти оғозёбӣ дар зери як занги система аллакай бо вақти оғози муқаррарӣ муқоиса карда мешавад:
$ time strace --seccomp-bpf -e open du /usr/share/ >/dev/null 2>&1
real 0m0.148s
user 0m0.017s
sys 0m0.131s
$ time du /usr/share/ >/dev/null 2>&1
real 0m0.140s
user 0m0.024s
sys 0m0.116s
(Дар ин ҷо, албатта, як фиреби каме вуҷуд дорад, ки мо занги асосии ин фармонро пайгирӣ намекунем. Агар мо пайгирӣ мекардем, масалан, newfsstat, он гоҳ strace тормоз мекард, мисли он ки бидуни он --seccomp-bpf.)
Ин вариант чӣ гуна кор мекунад? Бе вай strace ба раванд пайваст мешавад ва онро ба истифода оғоз мекунад PTRACE_SYSCALL. Вақте ки раванди идорашаванда (ҳар гуна) занги системаро медиҳад, назорат ба он интиқол дода мешавад strace, ки ба далелҳои занги система назар мекунад ва онро бо истифода аз он иҷро мекунад PTRACE_SYSCALL. Пас аз чанд вақт, раванд занги системаро анҷом медиҳад ва ҳангоми баромадан аз он, назорат дубора интиқол дода мешавад strace, ки ба арзишҳои бозгашт назар мекунад ва равандро бо истифода оғоз мекунад PTRACE_SYSCALL, ва ғайра.
Бо seccomp, ин равандро метавон маҳз ҳамон тавре ки мо мехоҳем оптимизатсия кард. Маҳз, агар мо хоҳем, ки танҳо занги системаро бубинем X, он гоҳ мо метавонем филтри BPF нависем, ки барои X арзиш бармегардонад SECCOMP_RET_TRACE, ва барои зангҳое, ки барои мо манфиатдор нестанд - SECCOMP_RET_ALLOW:
ld [0]
jneq #X, ignore
trace: ret #0x7ff00000
ignore: ret #0x7fff0000
Дар ин ҳолат strace дар аввал процессро чун PTRACE_CONT, филтри мо барои ҳар як занги система коркард мешавад, агар занги система набошад X, пас процесс давом дорад, аммо агар ин X, пас seccomp назоратро интиқол медиҳад straceки ба далелхо назар карда, процесси монанди PTRACE_SYSCALL (зеро seccomp қобилияти иҷро кардани барномаро ҳангоми баромадан аз занги система надорад). Вақте ки занги система бармегардад, strace бо истифода аз раванди аз нав оғоз хоҳад кард PTRACE_CONT ва паёмҳои навро аз seccomp интизор мешаванд.