BPF для самых ΠΌΠ°Π»Π΅Π½ΡŒΠΊΠΈΡ…, Ρ‡Π°ΡΡ‚ΡŒ нулСвая: classic BPF

Berkeley Packet Filters (BPF) β€” это тСхнология ядра Linux, которая Π½Π΅ сходит с ΠΏΠ΅Ρ€Π²Ρ‹Ρ… полос англоязычных тСхничСских ΠΈΠ·Π΄Π°Π½ΠΈΠΉ Π²ΠΎΡ‚ ΡƒΠΆΠ΅ нСсколько Π»Π΅Ρ‚ подряд. ΠšΠΎΠ½Ρ„Π΅Ρ€Π΅Π½Ρ†ΠΈΠΈ Π·Π°Π±ΠΈΡ‚Ρ‹ Π΄ΠΎΠΊΠ»Π°Π΄Π°ΠΌΠΈ ΠΏΡ€ΠΎ использованиС ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ BPF. David Miller, ΠΌΠ°Π½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ сСтСвой подсистСмы Linux, Π½Π°Π·Ρ‹Π²Π°Π΅Ρ‚ свой Π΄ΠΎΠΊΠ»Π°Π΄ Π½Π° Linux Plumbers 2018 Β«This talk is not about XDPΒ» (XDP – это ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² использования BPF). Brendan Gregg Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ Π΄ΠΎΠΊΠ»Π°Π΄Ρ‹ ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ Linux BPF Superpowers. Toke HΓΈiland-JΓΈrgensen смССтся, Ρ‡Ρ‚ΠΎ ядро это Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ microkernel. Thomas Graf Ρ€Π΅ΠΊΠ»Π°ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ идСю ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ BPF β€” это javascript для ядра.

На Π₯Π°Π±Ρ€Π΅ Π΄ΠΎ сих ΠΏΠΎΡ€ Π½Π΅Ρ‚ систСматичСского описания BPF, ΠΈ поэтому я Π² сСрии статСй ΠΏΠΎΡΡ‚Π°Ρ€Π°ΡŽΡΡŒ Ρ€Π°ΡΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΏΡ€ΠΎ ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ, ΠΎΠΏΠΈΡΠ°Ρ‚ΡŒ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΈ срСдства Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, ΠΎΡ‡Π΅Ρ€Ρ‚ΠΈΡ‚ΡŒ области примСнСния ΠΈ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ использования BPF. Π’ этой, Π½ΡƒΠ»Π΅Π²ΠΎΠΉ, ΡΡ‚Π°Ρ‚ΡŒΠ΅ Ρ†ΠΈΠΊΠ»Π° рассказываСтся история ΠΈ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° классичСского BPF, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°ΡΠΊΡ€Ρ‹Π²Π°ΡŽΡ‚ΡΡ Ρ‚Π°ΠΉΠ½Ρ‹ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ tcpdump, seccomp, strace, ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ΅.

Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° BPF контролируСтся сСтСвым сообщСством Linux, основныС ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ примСнСния BPF связаны с сСтями ΠΈ поэтому, с позволСния @eucariot, я Π½Π°Π·Π²Π°Π» ΡΠ΅Ρ€ΠΈΡŽ "BPF для самых ΠΌΠ°Π»Π΅Π½ΡŒΠΊΠΈΡ…", Π² Ρ‡Π΅ΡΡ‚ΡŒ Π²Π΅Π»ΠΈΠΊΠΎΠΉ сСрии "Π‘Π΅Ρ‚ΠΈ для самых ΠΌΠ°Π»Π΅Π½ΡŒΠΊΠΈΡ…".

ΠšΡ€Π°Ρ‚ΠΊΠΈΠΉ курс истории BPF(c)

БоврСмСнная тСхнология BPF β€” это ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½Π½Π°Ρ ΠΈ дополнСнная вСрсия старой Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ с Ρ‚Π΅ΠΌ ΠΆΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ, Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠΉ Π½Ρ‹Π½Ρ‡Π΅, Π²ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Π½ΠΈΠ΅ ΠΏΡƒΡ‚Π°Π½ΠΈΡ†Ρ‹, classic BPF. На основС классичСского BPF Π±Ρ‹Π»ΠΈ созданы всСм извСстная ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Π° tcpdump, ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ seccomp, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠ΅Π½Π΅Π΅ извСстныС ΠΌΠΎΠ΄ΡƒΠ»ΡŒ xt_bpf для iptables ΠΈ классификатор cls_bpf. Π’ соврСмСнном Linux классичСскиС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ BPF автоматичСски Ρ‚Ρ€Π°Π½ΡΠ»ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π² Π½ΠΎΠ²ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ, ΠΎΠ΄Π½Π°ΠΊΠΎ, с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния, API остался Π½Π° мСстС ΠΈ Π½ΠΎΠ²Ρ‹Π΅ примСнСния классичСского BPF, ΠΊΠ°ΠΊ ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅, находятся Π΄ΠΎ сих ΠΏΠΎΡ€. По этой ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ слСдуя Π·Π° историСй развития классичСской BPF Π² Linux, станСт яснСС ΠΊΠ°ΠΊ ΠΈ ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΎΠ½Π° ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π»Π° Π² ΡΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ, я Ρ€Π΅ΡˆΠΈΠ» Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΈΠΌΠ΅Π½Π½ΠΎ со ΡΡ‚Π°Ρ‚ΡŒΠΈ ΠΏΡ€ΠΎ классичСский BPF.

Π’ ΠΊΠΎΠ½Ρ†Π΅ Π²ΠΎΡΡŒΠΌΠΈΠ΄Π΅ΡΡΡ‚Ρ‹Ρ… Π³ΠΎΠ΄ΠΎΠ² ΠΏΡ€ΠΎΡˆΠ»ΠΎΠ³ΠΎ Π²Π΅ΠΊΠ° ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€Ρ‹ ΠΈΠ· Π·Π½Π°ΠΌΠ΅Π½ΠΈΡ‚ΠΎΠΉ Lawrence Berkeley Laboratory Π·Π°ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΠΎΠ²Π°Π»ΠΈΡΡŒ вопросом ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ сСтСвыС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ Π½Π° соврСмСнном для ΠΊΠΎΠ½Ρ†Π° Π²ΠΎΡΡŒΠΌΠΈΠ΄Π΅ΡΡΡ‚Ρ‹Ρ… Π³ΠΎΠ΄ΠΎΠ² ΠΏΡ€ΠΎΡˆΠ»ΠΎΠ³ΠΎ Π²Π΅ΠΊΠ° ΠΆΠ΅Π»Π΅Π·Π΅. Базовая идСя Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ, рСализованная ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ Π² Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ CSPF (CMU/Stanford Packet Filter), состояла Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ лишниС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°Π½ΡŒΡˆΠ΅, Ρ‚.Π΅. Π² пространствС ядра, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это позволяСт Π½Π΅ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ лишниС Π΄Π°Π½Π½Ρ‹Π΅ Π² пространство ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния для запуска ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° Π² пространствС ядра, использовалась Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина β€” пСсочница.

Однако Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ для ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Π²ΡˆΠΈΡ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² Π±Ρ‹Π»ΠΈ спроСктированы для запуска Π½Π° ΠΌΠ°ΡˆΠΈΠ½Π°Ρ… со стСковой Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€ΠΎΠΉ ΠΈ Π½Π° Π½ΠΎΠ²Ρ‹Ρ… RISC ΠΌΠ°ΡˆΠΈΠ½Π°Ρ… Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ Π½Π΅ Ρ‚Π°ΠΊ эффСктивно. Π’ ΠΈΡ‚ΠΎΠ³Π΅ усилиями ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€ΠΎΠ² ΠΈΠ· Berkeley Labs Π±Ρ‹Π»Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Π½Π° новая тСхнология BPF (Berkeley Packet Filters), Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π±Ρ‹Π»Π° спроСктирована Π½Π° основС процСссора Motorola 6502 β€” Ρ€Π°Π±ΠΎΡ‡Π΅ΠΉ лошадки Ρ‚Π°ΠΊΠΈΡ… извСстных ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ² ΠΊΠ°ΠΊ Apple II ΠΈΠ»ΠΈ NES. Новая Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π»Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² Π² дСсятки Ρ€Π°Π· ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Π²ΡˆΠΈΠΌΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΠΌΠΈ.

АрхитСктура ΠΌΠ°ΡˆΠΈΠ½Ρ‹ BPF

ΠœΡ‹ познакомимся с Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€ΠΎΠΉ ΠΏΠΎ-Ρ€Π°Π±ΠΎΡ‡Π΅ΠΌΡƒ, разбирая ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹. Однако для Π½Π°Ρ‡Π°Π»Π° всС ΠΆΠ΅ скаТСм, Ρ‡Ρ‚ΠΎ Ρƒ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ Π±Ρ‹Π»ΠΎ Π΄Π²Π° доступных для ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ 32-Π±ΠΈΡ‚Π½Ρ‹Ρ… рСгистра, аккумулятор A ΠΈ индСксный рСгистр X, 64 Π±Π°ΠΉΡ‚Π° памяти (16 слов), доступной для записи ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ чтСния, ΠΈ нСбольшая систСма ΠΊΠΎΠΌΠ°Π½Π΄ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с этими ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ. Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°Ρ… Π±Ρ‹Π»ΠΈ доступны ΠΈ инструкции ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ условных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ для Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ своСврСмСнного окончания Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²ΠΏΠ΅Ρ€Π΅Π΄, Ρ‚.Π΅., Π² частности, Π·Π°ΠΏΡ€Π΅Ρ‰Π°Π»ΠΎΡΡŒ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Ρ†ΠΈΠΊΠ»Ρ‹.

ΠžΠ±Ρ‰Π°Ρ схСма запуска ΠΌΠ°ΡˆΠΈΠ½Ρ‹ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ. ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ создаСт ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ для Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ BPF ΠΈ, ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Ρ‚ΠΎ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° ядра (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, систСмного Π²Ρ‹Π·ΠΎΠ²Π°), Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΊ ΠΊΠ°ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Ρƒ событий Π² ядрС (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, событиС β€” это ΠΏΡ€ΠΈΡ…ΠΎΠ΄ ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π½Π° ΡΠ΅Ρ‚Π΅Π²ΡƒΡŽ ΠΊΠ°Ρ€Ρ‚Ρƒ). ΠŸΡ€ΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠΈ события ядро запускаСт ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€Π΅), ΠΏΡ€ΠΈ этом ΠΏΠ°ΠΌΡΡ‚ΡŒ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ соотвСтствуСт ΠΊΠ°ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ Ρ€Π΅Π³ΠΈΠΎΠ½Ρƒ памяти ядра (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π΄Π°Π½Π½Ρ‹ΠΌ ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠ΅Π³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π°).

Π‘ΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Π²Ρ‹ΡˆΠ΅ Π½Π°ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ достаточно для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°Ρ‡Π°Ρ‚ΡŒ Ρ€Π°Π·Π±ΠΈΡ€Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹: ΠΌΡ‹ познакомимся с систСмой ΠΈ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠΌ ΠΊΠΎΠΌΠ°Π½Π΄ ΠΏΠΎ нСобходимости. Если ΠΆΠ΅ Π²Π°ΠΌ хочСтся сразу ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ систСму ΠΊΠΎΠΌΠ°Π½Π΄ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ ΠΈ ΡƒΠ·Π½Π°Ρ‚ΡŒ ΠΏΡ€ΠΎ всС Π΅Π΅ возмоТности, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ ΡΡ‚Π°Ρ‚ΡŒΡŽ The BSD Packet Filter ΠΈ/ΠΈΠ»ΠΈ ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Ρƒ Ρ„Π°ΠΉΠ»Π° Documentation/networking/filter.txt ΠΈΠ· Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ ядра. ΠšΡ€ΠΎΠΌΠ΅ этого, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π·Π΅Π½Ρ‚Π°Ρ†ΠΈΡŽ libpcap: An Architecture and Optimization Methodology for Packet Capture, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ McCanne, ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² BPF, рассказываСт ΠΏΡ€ΠΎ ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ создания libpcap.

ΠœΡ‹ ΠΆΠ΅ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ ΠΊ Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Π½ΠΈΡŽ всСх сущСствСнных ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² примСнСния классичСского BPF Π² Linux: tcpdump (libpcap), seccomp, xt_bpf, cls_bpf.

tcpdump

Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° BPF вСлась ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ с Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Π° для Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² β€” всСм извСстной ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ tcpdump. И, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это самый старый ΠΈ самый извСстный ΠΏΡ€ΠΈΠΌΠ΅Ρ€ использования классичСского BPF, доступный Π½Π° мноТСствС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… систСм, с Π½Π΅Π³ΠΎ ΠΌΡ‹ ΠΈΠ·ΡƒΡ‡Π΅Π½ΠΈΠ΅ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ ΠΈ Π½Π°Ρ‡Π½Π΅ΠΌ.

(ВсС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ я запускал Π½Π° Linux 5.6.0-rc6. Π’Ρ‹Π²ΠΎΠ΄ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΊΠΎΠΌΠ°Π½Π΄ ΠΎΡ‚Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ для большСй удобочитаСмости.)

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: наблюдаСм IPv6 ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ ΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π½Π° всС IPv6 ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ Π½Π° интСрфСйсС eth0. Для этого ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ tcpdump с ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΌ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠΌ ip6:

$ sudo tcpdump -i eth0 ip6

ΠŸΡ€ΠΈ этом tcpdump скомпилируСт Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ip6 Π² Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ BPF ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ Π΅Π³ΠΎ Π² ядро (см. подробности Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ Tcpdump: Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ°). Π—Π°Π³Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹ΠΉ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π°, проходящСго Ρ‡Π΅Ρ€Π΅Π· интСрфСйс eth0. Если Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π²Π΅Ρ€Π½Π΅Ρ‚ Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ n, Ρ‚ΠΎ Π΄ΠΎ n Π±Π°ΠΉΡ‚ΠΎΠ² ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π±ΡƒΠ΄Π΅Ρ‚ скопировано Π² пространство ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈ ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ Π΅Π³ΠΎ Π² Π²Ρ‹Π²ΠΎΠ΄Π΅ tcpdump.

BPF для самых ΠΌΠ°Π»Π΅Π½ΡŒΠΊΠΈΡ…, Ρ‡Π°ΡΡ‚ΡŒ нулСвая: classic BPF

ΠžΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ΡΡ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π»Π΅Π³ΠΊΠΎ ΡƒΠ·Π½Π°Ρ‚ΡŒ ΠΊΠ°ΠΊΠΎΠΉ ΠΈΠΌΠ΅Π½Π½ΠΎ Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΠ» Π² ядро tcpdump ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ самого tcpdump, Ссли запустим Π΅Π³ΠΎ с ΠΎΠΏΡ†ΠΈΠ΅ΠΉ -d:

$ sudo tcpdump -i eth0 -d ip6
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 3
(002) ret      #262144
(003) ret      #0

На Π½ΡƒΠ»Π΅Π²ΠΎΠΉ строчкС ΠΌΡ‹ запускаСм ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ ldh [12], которая Ρ€Π°ΡΡˆΠΈΡ„Ρ€ΠΎΠ²Ρ‹Π²Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊ Β«Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ Π² рСгистр A ΠΏΠΎΠ»-слова (16 Π±ΠΈΡ‚), находящиСся ΠΏΠΎ адрСсу 12Β» ΠΈ СдинствСнный вопрос β€” это Ρ‡Ρ‚ΠΎ Π·Π° ΠΏΠ°ΠΌΡΡ‚ΡŒ ΠΌΡ‹ адрСсуСм? ΠžΡ‚Π²Π΅Ρ‚ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠΎ адрСсу x начинаСтся (x+1)-ΠΉ Π±Π°ΠΉΡ‚ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ³ΠΎ сСтСвого ΠΏΠ°ΠΊΠ΅Ρ‚Π°. ΠœΡ‹ Ρ‡ΠΈΡ‚Π°Π΅ΠΌ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ с Ethernet интСрфСйса eth0, Π° это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ (для простоты ΠΌΡ‹ считаСм, Ρ‡Ρ‚ΠΎ Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π΅ Π½Π΅Ρ‚ VLAN тэгов):

       6              6          2
|Destination MAC|Source MAC|Ether Type|...|

Π—Π½Π°Ρ‡ΠΈΡ‚ послС выполнСния ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ldh [12] Π² рСгистрС A окаТСтся ΠΏΠΎΠ»Π΅ Ether Type β€” Ρ‚ΠΈΠΏ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΠΎΠ³ΠΎ Π² Π΄Π°Π½Π½ΠΎΠΌ Ethernet-Ρ„Ρ€Π΅ΠΉΠΌΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π°. На строчкС 1 ΠΌΡ‹ сравниваСм содСрТимоС рСгистра A (Ρ‚ΠΈΠΏ ΠΏΠ°ΠΊΠ΅Ρ‚Π°) c 0x86dd, Π° это ΠΈ Π΅ΡΡ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰ΠΈΠΉ нас Ρ‚ΠΈΠΏ IPv6. На строчкС 1 ΠΊΡ€ΠΎΠΌΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ сравнСния Π΅ΡΡ‚ΡŒ Π΅Ρ‰Π΅ Π΄Π²Π° столбца β€” jt 2 ΠΈ jf 3 β€” ΠΌΠ΅Ρ‚ΠΊΠΈ, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π² случаС ΡƒΠ΄Π°Ρ‡Π½ΠΎΠ³ΠΎ сравнСния (A == 0x86dd) ΠΈ Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎΠ³ΠΎ. Π˜Ρ‚Π°ΠΊ, Π² ΡƒΠ΄Π°Ρ‡Π½ΠΎΠΌ случаС (IPv6) ΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ Π½Π° строчку 2, Π° Π² Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎΠΌ β€” Π½Π° строчку 3. На строчкС 3 ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ с ΠΊΠΎΠ΄ΠΎΠΌ 0 (Π½Π΅ ΠΊΠΎΠΏΠΈΡ€ΡƒΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚), Π½Π° строчкС 2 ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ с ΠΊΠΎΠ΄ΠΎΠΌ 262144 (скопируй ΠΌΠ½Π΅ максимум 256 ΠΊΠΈΠ»ΠΎΠ±Π°ΠΉΡ‚ ΠΏΠ°ΠΊΠ΅Ρ‚Π°).

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ послоТнСС: смотрим Π½Π° TCP ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΏΠΎ ΠΏΠΎΡ€Ρ‚Ρƒ назначСния

ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ ΠΊΠ°ΠΊ выглядит Ρ„ΠΈΠ»ΡŒΡ‚Ρ€, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ всС TCP ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ с ΠΏΠΎΡ€Ρ‚ΠΎΠΌ назначСния 666. ΠœΡ‹ рассмотрим случай IPv4, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ случай IPv6 ΠΏΡ€ΠΎΡ‰Π΅. ПослС изучСния Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π² качСствС упраТнСния ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ для IPv6 (ip6 and tcp dst port 666) ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ для ΠΎΠ±Ρ‰Π΅Π³ΠΎ случая (tcp dst port 666). Π˜Ρ‚Π°ΠΊ, ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰ΠΈΠΉ нас Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

$ sudo tcpdump -i eth0 -d ip and tcp dst port 666
(000) ldh      [12]
(001) jeq      #0x800           jt 2    jf 10
(002) ldb      [23]
(003) jeq      #0x6             jt 4    jf 10
(004) ldh      [20]
(005) jset     #0x1fff          jt 10   jf 6
(006) ldxb     4*([14]&0xf)
(007) ldh      [x + 16]
(008) jeq      #0x29a           jt 9    jf 10
(009) ret      #262144
(010) ret      #0

Π§Ρ‚ΠΎ Π΄Π΅Π»Π°ΡŽΡ‚ строчки 0 ΠΈ 1 ΠΌΡ‹ ΡƒΠΆΠ΅ Π·Π½Π°Π΅ΠΌ. На строкС 2 ΠΌΡ‹ ΡƒΠΆΠ΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠ»ΠΈ, Ρ‡Ρ‚ΠΎ это IPv4 ΠΏΠ°ΠΊΠ΅Ρ‚ (Ether Type = 0x800) ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π² рСгистр A 24-ΠΉ Π±Π°ΠΉΡ‚ ΠΏΠ°ΠΊΠ΅Ρ‚Π°. Наш ΠΏΠ°ΠΊΠ΅Ρ‚ выглядит ΠΊΠ°ΠΊ

       14            8      1     1
|ethernet header|ip fields|ttl|protocol|...|

Π° Π·Π½Π°Ρ‡ΠΈΡ‚ ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π² рСгистр A ΠΏΠΎΠ»Π΅ Protocol Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° IP, Ρ‡Ρ‚ΠΎ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ, вСдь ΠΌΡ‹ ΠΆΠ΅ Ρ…ΠΎΡ‚ΠΈΠΌ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ TCP ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. ΠœΡ‹ сравниваСм Protocol с 0x6 (IPPROTO_TCP) Π½Π° строкС 3.

На строках 4 ΠΈ 5 ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ полслова, находящиСся ΠΏΠΎ адрСсу 20, ΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ jset провСряСм, Π½Π΅ выставлСн Π»ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Ρ‚Ρ€Π΅Ρ… Ρ„Π»Π°Π³ΠΎΠ² β€” Π² маскС Π²Ρ‹Π΄Π°Π½Π½ΠΎΠΉ jset ΠΎΡ‡ΠΈΡ‰Π΅Π½Ρ‹ Ρ‚Ρ€ΠΈ ΡΡ‚Π°Ρ€ΡˆΠΈΠ΅ Π±ΠΈΡ‚Π°. Π”Π²Π° Π±ΠΈΡ‚Π° ΠΈΠ· Ρ‚Ρ€Π΅Ρ… говорят Π½Π°ΠΌ, являСтся Π»ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ Ρ‡Π°ΡΡ‚ΡŒΡŽ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ IP ΠΏΠ°ΠΊΠ΅Ρ‚Π°, ΠΈ Ссли Π΄Π°, Ρ‚ΠΎ являСтся Π»ΠΈ ΠΎΠ½ послСдним Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΎΠΌ. Π’Ρ€Π΅Ρ‚ΠΈΠΉ Π±ΠΈΡ‚ Π·Π°Ρ€Π΅Π·Π΅Ρ€Π²ΠΈΡ€ΠΎΠ²Π°Π½ ΠΈ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ. ΠœΡ‹ Π½Π΅ Ρ…ΠΎΡ‚ΠΈΠΌ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ Π½ΠΈ Π½Π΅Ρ†Π΅Π»Ρ‹Π΅ Π½ΠΈ Π±ΠΈΡ‚Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, поэтому ΠΈ провСряСм всС Ρ‚Ρ€ΠΈ Π±ΠΈΡ‚Π°.

Π‘Ρ‚Ρ€ΠΎΡ‡ΠΊΠ° 6 β€” самая интСрСсная Π² этом листингС. Π’Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ldxb 4*([14]&0xf) ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π² рСгистр X Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ младшиС Π±ΠΈΡ‚Π° пятнадцатого Π±Π°ΠΉΡ‚Π° ΠΏΠ°ΠΊΠ΅Ρ‚Π°, ΡƒΠΌΠ½ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ Π½Π° 4. Π§Π΅Ρ‚Ρ‹Ρ€Π΅ младшиС Π±ΠΈΡ‚Π° пятнадцатого Π±Π°ΠΉΡ‚Π° β€” это ΠΏΠΎΠ»Π΅ Internet Header Length Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° IPv4, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ хранится Π΄Π»ΠΈΠ½Π° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Π² словах, поэтому ΠΈ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΡ‚ΠΎΠΌ ΡƒΠΌΠ½ΠΎΠΆΠΈΡ‚ΡŒ Π½Π° 4. Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎ, Ρ‡Ρ‚ΠΎ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ 4*([14]&0xf) β€” это ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ схСмы адрСсации, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚Π°ΠΊΠΎΠΌ Π²ΠΈΠ΄Π΅ ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для рСгистра X, Ρ‚.Π΅. ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ Π½ΠΈ ldb 4*([14]&0xf) Π½ΠΈ ldxb 5*([14]&0xf) (ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΉ offset, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 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|

НаконСц, Π½Π° строкС 8 ΠΌΡ‹ сравниваСм ΠΏΠΎΡ€Ρ‚ назначСния с искомым Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΈ Π½Π° строчках 9 ΠΈΠ»ΠΈ 10 Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ β€” ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΈΠ»ΠΈ Π½Π΅Ρ‚.

Tcpdump: Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ°

Π’ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… ΠΌΡ‹ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ Π½Π΅ ΠΎΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Π»ΠΈΡΡŒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π½Π° Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ BPF Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄ Π² ядро для Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Π’ΠΎΠΎΠ±Ρ‰Π΅ говоря, tcpdump ΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ Π½Π° ΠΌΠ½ΠΎΠ³ΠΎ систСм ΠΈ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°ΠΌΠΈ tcpdump ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ libpcap. Π’ΠΊΡ€Π°Ρ‚Ρ†Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΡΠ°Π΄ΠΈΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π½Π° интСрфСйс ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ libpcap, Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅:

  • ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ дСскриптор Ρ‚ΠΈΠΏΠ° pcap_t ΠΈΠ· ΠΈΠΌΠ΅Π½ΠΈ интСрфСйса: pcap_create,
  • Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ интСрфСйс: pcap_activate,
  • ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€: pcap_compile,
  • ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€: pcap_setfilter.

Для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΠΊΠ°ΠΊ функция pcap_setfilter Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π² Linux, ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ strace (Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ строчки Π±Ρ‹Π»ΠΈ ΡƒΠ΄Π°Π»Π΅Π½Ρ‹):

$ sudo strace -f -e trace=%network tcpdump -p -i eth0 ip
socket(AF_PACKET, SOCK_RAW, 768)        = 3
bind(3, {sa_family=AF_PACKET, sll_protocol=htons(ETH_P_ALL), sll_ifindex=if_nametoindex("eth0"), sll_hatype=ARPHRD_NETROM, sll_pkttype=PACKET_HOST, sll_halen=0}, 20) = 0
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=4, filter=0xb00bb00bb00b}, 16) = 0
...

На ΠΏΠ΅Ρ€Π²Ρ‹Ρ… Π΄Π²ΡƒΡ… строчках Π²Ρ‹Π²ΠΎΠ΄Π° ΠΌΡ‹ создаСм raw сокСт для чтСния всСх Ethernet Ρ„Ρ€Π΅ΠΉΠΌΠΎΠ² ΠΈ привязываСм Π΅Π³ΠΎ ΠΊ интСрфСйсу eth0. Из нашСго ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΡ‹ Π·Π½Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ip Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ· Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅Ρ… BPF инструкций, ΠΈ Π½Π° Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ строчкС ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, ΠΊΠ°ΠΊ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΎΠΏΡ†ΠΈΠΈ SO_ATTACH_FILTER систСмного Π²Ρ‹Π·ΠΎΠ²Π° setsockopt ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΈ подсоСдиняСм Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π΄Π»ΠΈΠ½Ρ‹ 4. Π­Ρ‚ΠΎ ΠΈ Π΅ΡΡ‚ΡŒ наш Ρ„ΠΈΠ»ΡŒΡ‚Ρ€.

Π‘Ρ‚ΠΎΠΈΡ‚ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π² классичСском BPF Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΈ подсоСдинСниС Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° всСгда происходит ΠΊΠ°ΠΊ атомарная опСрация, Π° Π² Π½ΠΎΠ²ΠΎΠΉ вСрсии BPF Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ привязка Π΅Π΅ ΠΊ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Ρƒ событий Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Ρ‹ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.

Бкрытая ΠΏΡ€Π°Π²Π΄Π°

Π§ΡƒΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ полная вСрсия Π²Ρ‹Π²ΠΎΠ΄Π° выглядит Ρ‚Π°ΠΊ:

$ sudo strace -f -e trace=%network tcpdump -p -i eth0 ip
socket(AF_PACKET, SOCK_RAW, 768)        = 3
bind(3, {sa_family=AF_PACKET, sll_protocol=htons(ETH_P_ALL), sll_ifindex=if_nametoindex("eth0"), sll_hatype=ARPHRD_NETROM, sll_pkttype=PACKET_HOST, sll_halen=0}, 20) = 0
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=1, filter=0xbeefbeefbeef}, 16) = 0
recvfrom(3, 0x7ffcad394257, 1, MSG_TRUNC, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, {len=4, filter=0xb00bb00bb00b}, 16) = 0
...

Как Π±Ρ‹Π»ΠΎ сказано Π²Ρ‹ΡˆΠ΅, ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΈ подсоСдиняСм ΠΊ сокСту наш Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π½Π° строкС 5, Π½ΠΎ Ρ‡Ρ‚ΠΎ происходит Π½Π° строчках 3 ΠΈ 4? ΠžΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ΡΡ, это libpcap заботится ΠΎ нас β€” для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π² Π²Ρ‹Π²ΠΎΠ΄ нашСго Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° Π½Π΅ ΠΏΠΎΠΏΠ°Π»ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, Π΅ΠΌΡƒ Π½Π΅ ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€ΡΡŽΡ‰ΠΈΠ΅, Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° подсоСдиняСт Ρ„ΠΈΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ret #0 (Π΄Ρ€ΠΎΠΏΠ½ΡƒΡ‚ΡŒ всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹), ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΈΡ‚ сокСт Π² Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π΅ΠΆΠΈΠΌ ΠΈ пытаСтся Π²Ρ‹Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³Π»ΠΈ ΠΎΡΡ‚Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ ΠΏΡ€ΠΎΡˆΠ»Ρ‹Ρ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ².

Π˜Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ Π½Π° Linux ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ классичСского BPF, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π² Π²ΠΈΠ΄Π΅ структуры Ρ‚ΠΈΠΏΠ° struct sock_fprog ΠΈ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΉ сокСт, послС Ρ‡Π΅Π³ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΊ сокСту ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ систСмного Π²Ρ‹Π·ΠΎΠ²Π° setsockopt.

Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎ, Ρ‡Ρ‚ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΡΡ‚ΡŒ ΠΊ Π»ΡŽΠ±ΠΎΠΌΡƒ сокСту, Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊ raw. Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, которая ΠΎΡ‚Ρ€Π΅Π·Π°Π΅Ρ‚ всС, ΠΊΡ€ΠΎΠΌΠ΅ Π΄Π²ΡƒΡ… ΠΏΠ΅Ρ€Π²Ρ‹Ρ… Π±Π°ΠΉΡ‚ Ρƒ всСх входящих UDP Π΄Π°Ρ‚Π°Π³Ρ€Π°ΠΌΠΌ. (ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ я Π΄ΠΎΠ±Π°Π²ΠΈΠ» Π² ΠΊΠΎΠ΄Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π·Π°Π³Ρ€ΠΎΠΌΠΎΠΆΠ΄Π°Ρ‚ΡŒ ΡΡ‚Π°Ρ‚ΡŒΡŽ.)

ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΏΡ€ΠΎ использованиС setsockopt для подсоСдинСния Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² см. Π² socket(7), Π° ΠΏΡ€ΠΎ написаниС своих Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² Π²ΠΈΠ΄Π° struct sock_fprog Π±Π΅Π· ΠΏΠΎΠΌΠΎΡ‰ΠΈ tcpdump ΠΌΡ‹ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΡƒΠ΅ΠΌ BPF ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ собствСнных Ρ€ΡƒΠΊ.

ΠšΠ»Π°ΡΡΠΈΡ‡Π΅ΡΠΊΠΈΠΉ BPF ΠΈ XXI Π²Π΅ΠΊ

BPF Π±Ρ‹Π» Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ Π² Linux Π² 1997 Π³ΠΎΠ΄Ρƒ ΠΈ Π΄ΠΎΠ»Π³ΠΎΠ΅ врСмя оставался Ρ€Π°Π±ΠΎΡ‡Π΅ΠΉ лошадкой libpcap Π±Π΅Π· особых ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ (Linux-спСцифичныС измСнСния, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, Π±Ρ‹Π»ΠΈ, Π½ΠΎ ΠΎΠ½ΠΈ Π½Π΅ мСняли глобальной ΠΊΠ°Ρ€Ρ‚ΠΈΠ½Ρ‹). ΠŸΠ΅Ρ€Π²Ρ‹Π΅ ΡΠ΅Ρ€ΡŒΠ΅Π·Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠ·Π½Π°ΠΊΠΈ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ BPF Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ появились Π² 2011 Π³ΠΎΠ΄Ρƒ, ΠΊΠΎΠ³Π΄Π° Eric Dumazet ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠΈΠ» ΠΏΠ°Ρ‚Ρ‡, Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ Π² ядро Just In Time Compiler β€” транслятор для ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄Π° BPF Π² Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΉ x86_64 ΠΊΠΎΠ΄.

JIT compiler Π±Ρ‹Π» ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ: Π² 2012 Π³ΠΎΠ΄Ρƒ появилась Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ для seccomp, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ BPF, Π² январС 2013 Π±Ρ‹Π» Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ xt_bpf, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»Π° для iptables ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ BPF, Π° Π² октябрС 2013 Π±Ρ‹Π» Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π΅Ρ‰Π΅ ΠΈ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ cls_bpf, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ BPF классификаторы Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°.

ΠœΡ‹ скоро рассмотрим всС эти ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅, ΠΎΠ΄Π½Π°ΠΊΠΎ сначала Π½Π°ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π½Π°ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ для BPF, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ возмоТности, прСдоставляСмыС Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ libpcap ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Ρ‹ (простой ΠΏΡ€ΠΈΠΌΠ΅Ρ€: Ρ„ΠΈΠ»ΡŒΡ‚Ρ€, сгСнСрированный libpcap ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π²Π° значСния β€” 0 ΠΈΠ»ΠΈ 0x40000) ΠΈΠ»ΠΈ Π²ΠΎΠΎΠ±Ρ‰Π΅, ΠΊΠ°ΠΊ Π² случаС seccomp, Π½Π΅ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌΡ‹.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΡƒΠ΅ΠΌ BPF ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ собствСнных Ρ€ΡƒΠΊ

Познакомимся с Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΌ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠΌ инструкций BPF, ΠΎΠ½ ΠΎΡ‡Π΅Π½ΡŒ простой:

   16    8    8     32
| code | jt | jf |  k  |

КаТдая инструкция Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ 64 Π±ΠΈΡ‚Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΏΠ΅Ρ€Π²Ρ‹Π΅ 16 Π±ΠΈΡ‚ β€” это ΠΊΠΎΠ΄ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹, ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΠ΄ΡƒΡ‚ Π΄Π²Π° Π²ΠΎΡΡŒΠΌΠΈΠ±ΠΈΡ‚Π½Ρ‹Ρ… отступа, jt ΠΈ jf, ΠΈ 32 Π±ΠΈΡ‚Π° для Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° K, Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ мСняСтся ΠΎΡ‚ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΊ ΠΊΠΎΠΌΠ°Π½Π΄Π΅. НапримСр, ΠΊΠΎΠΌΠ°Π½Π΄Π° ret, Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰Π°Ρ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΊΠΎΠ΄ 6, Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ бСрСтся ΠΈΠ· константы K. На языкС C ΠΎΠ΄Π½Π° инструкция BPF прСдставляСтся Π² Π²ΠΈΠ΄Π΅ структуры

struct sock_filter {
        __u16   code;
        __u8    jt;
        __u8    jf;
        __u32   k;
}

Π° цСлая ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° β€” Π² Π²ΠΈΠ΄Π΅ структуры

struct sock_fprog {
        unsigned short len;
        struct sock_filter *filter;
}

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΌΡ‹ ΡƒΠΆΠ΅ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ (ΠΊΠΎΠ΄Ρ‹ инструкций ΠΌΡ‹, допустим, Π·Π½Π°Π΅ΠΌ ΠΈΠ· [1]). Π’ΠΎΡ‚ Ρ‚Π°ΠΊ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ip6 ΠΈΠ· нашСго ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

struct sock_filter code[] = {
        { 0x28, 0, 0, 0x0000000c },
        { 0x15, 0, 1, 0x000086dd },
        { 0x06, 0, 0, 0x00040000 },
        { 0x06, 0, 0, 0x00000000 },
};
struct sock_fprog prog = {
        .len = ARRAY_SIZE(code),
        .filter = code,
};

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ prog ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ лСгально ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π²Ρ‹Π·ΠΎΠ²Π΅

setsockopt(sk, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog))

ΠŸΠΈΡΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² Π²ΠΈΠ΄Π΅ ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹Ρ… ΠΊΠΎΠ΄ΠΎΠ² Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ ΡƒΠ΄ΠΎΠ±Π½ΠΎ, Π½ΠΎ ΠΈΠ½ΠΎΠ³Π΄Π° приходится (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ, создания ΡŽΠ½ΠΈΡ‚-тСстов, написания статСй Π½Π° Ρ…Π°Π±Ρ€Π΅ ΠΈ Ρ‚.ΠΏ.). Для удобства Π² Ρ„Π°ΠΉΠ»Π΅ <linux/filter.h> ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ΡΡ макросы-ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊΠΈ β€” Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‡Ρ‚ΠΎ ΠΈ Π²Ρ‹ΡˆΠ΅, ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΊΠ°ΠΊ

struct sock_filter code[] = {
        BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 12),
        BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ETH_P_IPV6, 0, 1),
        BPF_STMT(BPF_RET|BPF_K, 0x00040000),
        BPF_STMT(BPF_RET|BPF_K, 0),
}

Однако, ΠΈ Ρ‚Π°ΠΊΠΎΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ-Ρ‚ΠΎ ΡƒΠ΄ΠΎΠ±Π΅Π½. Π’Π°ΠΊ рассудили ΠΈ программисты ядра Linux ΠΈ поэтому Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ tools/bpf ядра ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ ассСмблСр ΠΈ Π΄Π΅Π±Π°Π³Π΅Ρ€ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с классичСским BPF.

Π―Π·Ρ‹ΠΊ ассСмблСра ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΡ…ΠΎΠΆ Π½Π° ΠΎΡ‚Π»Π°Π΄ΠΎΡ‡Π½Ρ‹ΠΉ Π²Ρ‹Π²ΠΎΠ΄ tcpdump, Π½ΠΎ Π² Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ символичСскиС ΠΌΠ΅Ρ‚ΠΊΠΈ. НапримСр, Π²ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°, которая Π΄Ρ€ΠΎΠΏΠ°Π΅Ρ‚ всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, ΠΊΡ€ΠΎΠΌΠ΅ TCP/IPv4:

$ cat /tmp/tcp-over-ipv4.bpf
ldh [12]
jne #0x800, drop
ldb [23]
jneq #6, drop
ret #-1
drop: ret #0

По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ассСмблСр Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΊΠΎΠ΄ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ <количСство инструкций>,<code1> <jt1> <jf1> <k1>,..., для нашСго ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° с TCP получится

$ tools/bpf/bpf_asm /tmp/tcp-over-ipv4.bpf
6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 6,6 0 0 4294967295,6 0 0 0,

Для удобства C программистов ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π²Ρ‹Π²ΠΎΠ΄Π°:

$ tools/bpf/bpf_asm -c /tmp/tcp-over-ipv4.bpf
{ 0x28,  0,  0, 0x0000000c },
{ 0x15,  0,  3, 0x00000800 },
{ 0x30,  0,  0, 0x00000017 },
{ 0x15,  0,  1, 0x00000006 },
{ 0x06,  0,  0, 0xffffffff },
{ 0x06,  0,  0, 0000000000 },

Π­Ρ‚ΠΎΡ‚ тСкст ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ структуры Ρ‚ΠΈΠΏΠ° struct sock_filter, ΠΊΠ°ΠΊ ΠΌΡ‹ ΠΈ ΠΏΡ€ΠΎΠ΄Π΅Π»Π°Π»ΠΈ Π² Π½Π°Ρ‡Π°Π»Π΅ этого Ρ€Π°Π·Π΄Π΅Π»Π°.

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Linux ΠΈ netsniff-ng

ΠšΡ€ΠΎΠΌΠ΅ стандартных инструкций BPF, Linux ΠΈ tools/bpf/bpf_asm ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ ΠΈ нСстандартный Π½Π°Π±ΠΎΡ€. Π’ основном, инструкции слуТат для доступа ΠΊ полям структуры struct sk_buff, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰Π΅ΠΉ сСтСвой ΠΏΠ°ΠΊΠ΅Ρ‚ Π² ядрС. Однако, Π΅ΡΡ‚ΡŒ ΠΈ инструкции-ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ldw cpu Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ Π² рСгистр A Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ запуска Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ядра raw_smp_processor_id(). (Π’ Π½ΠΎΠ²ΠΎΠΉ вСрсии BPF эти нСстандартныС Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Π±Ρ‹Π»ΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½Ρ‹ Π² Π²ΠΈΠ΄Π΅ прСдоставлСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°ΠΌ Π½Π°Π±ΠΎΡ€Π° kernel helpers для доступа ΠΊ памяти, структурам, ΠΈ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ событий.) Π’ΠΎΡ‚ интСрСсный ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΌΡ‹ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Π² пространство ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ poff, payload offset:

ld poff
ret a

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ BPF Π½Π΅ получится ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² tcpdump, Π½ΠΎ это Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΉ ΠΏΠΎΠ²ΠΎΠ΄ ΠΏΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ с ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠΌ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ netsniff-ng, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ, ΠΊΡ€ΠΎΠΌΠ΅ всСго ΠΏΡ€ΠΎΡ‡Π΅Π³ΠΎ, содСрТит ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ netsniff-ng, которая, ΠΊΡ€ΠΎΠΌΠ΅ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ BPF содСрТит Ρ‚Π°ΠΊΠΆΠ΅ ΠΈ эффСктивный Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°, ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚Ρ‹ΠΉ, Ρ‡Π΅ΠΌ tools/bpf/bpf_asm, ассСмблСр BPF ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ bpfc. ΠŸΠ°ΠΊΠ΅Ρ‚ содСрТит довольно ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΡƒΡŽ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ, см. Ρ‚Π°ΠΊΠΆΠ΅ ссылки Π² ΠΊΠΎΠ½Ρ†Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ.

seccomp

Π˜Ρ‚Π°ΠΊ, ΠΌΡ‹ ΡƒΠΆΠ΅ ΡƒΠΌΠ΅Π΅ΠΌ ΠΏΠΈΡΠ°Ρ‚ΡŒ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎΠΉ слоТности ΠΈ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π½Π° Π½ΠΎΠ²Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹, ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… β€” это тСхнология seccomp, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰Π°Ρ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² BPF ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ мноТСством ΠΈ Π½Π°Π±ΠΎΡ€ΠΎΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ², доступных Π΄Π°Π½Π½ΠΎΠΌΡƒ процСссу ΠΈ Π΅Π³ΠΎ ΠΏΠΎΡ‚ΠΎΠΌΠΊΠ°ΠΌ.

ΠŸΠ΅Ρ€Π²Π°Ρ вСрсия seccomp Π±Ρ‹Π»Π° Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° Π² ядро Π² 2005 Π³ΠΎΠ΄Ρƒ ΠΈ Π½Π΅ пользовалась большой ΠΏΠΎΠΏΡƒΠ»ΡΡ€Π½ΠΎΡΡ‚ΡŒΡŽ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ прСдоставляла лишь Π΅Π΄ΠΈΠ½ΡΡ‚Π²Π΅Π½Π½ΡƒΡŽ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ β€” ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚ΡŒ мноТСство систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ², доступных процСссу, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ: read, write, exit ΠΈ sigreturn, Π° процСсс, Π½Π°Ρ€ΡƒΡˆΠΈΠ²ΡˆΠΈΠΉ ΠΏΡ€Π°Π²ΠΈΠ»Π° убивался ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ SIGKILL. Однако Π² 2012 Π³ΠΎΠ΄Ρƒ Π² seccomp Π±Ρ‹Π»Π° Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ BPF Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ мноТСство Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½Π½Ρ‹Ρ… систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΈ Π΄Π°ΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π½Π°Π΄ ΠΈΡ… Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ. (Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· ΠΏΠ΅Ρ€Π²Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ являлся Chrome, Π° Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ людьми ΠΈΠ· Chrome разрабатываСтся ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ KRSI, основанный Π½Π° Π½ΠΎΠ²ΠΎΠΉ вСрсии BPF ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΊΠ°ΡΡ‚ΠΎΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Linux Security Modules.) Бсылки Π½Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π² ΠΊΠΎΠ½Ρ†Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ.

ΠžΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° Ρ…Π°Π±Ρ€Π΅ ΡƒΠΆΠ΅ Π±Ρ‹Π»ΠΈ ΡΡ‚Π°Ρ‚ΡŒΠΈ ΠΏΡ€ΠΎ использованиС seccomp, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ захочСтся ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΈΡ… Π΄ΠΎ (ΠΈΠ»ΠΈ вмСсто) чтСния ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΏΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π»ΠΎΠ². Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ: seccomp ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования seccomp, ΠΊΠ°ΠΊ вСрсии 2007 Π³ΠΎΠ΄Π°, Ρ‚Π°ΠΊ ΠΈ вСрсии с использованиСм BPF (Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ libseccomp), рассказываСтся ΠΏΡ€ΠΎ связь seccomp с Docker, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ссылок. Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π˜Π·ΠΎΠ»ΠΈΡ€ΡƒΠ΅ΠΌ Π΄Π΅ΠΌΠΎΠ½Ρ‹ с systemd ΠΈΠ»ΠΈ Β«Π²Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ΅Π½ Docker для этого!Β» рассказываСтся, Π² частности, ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ Ρ‡Π΅Ρ€Π½Ρ‹Π΅ ΠΈΠ»ΠΈ Π±Π΅Π»Ρ‹Π΅ списки систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² для Π΄Π΅ΠΌΠΎΠ½ΠΎΠ² ΠΏΠΎΠ΄ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ systemd.

Π”Π°Π»ΡŒΡˆΠ΅ ΠΌΡ‹ посмотрим ΠΊΠ°ΠΊ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ для seccomp Π½Π° Π³ΠΎΠ»ΠΎΠΌ C ΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ libseccomp ΠΈ ΠΊΠ°ΠΊΠΈΠ΅ ΠΏΠ»ΡŽΡΡ‹ ΠΈ минусы Π΅ΡΡ‚ΡŒ Ρƒ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°, Π° напослСдок посмотрим ΠΊΠ°ΠΊ seccomp ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ strace.

ПишСм ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ для seccomp

ΠœΡ‹ ΡƒΠΆΠ΅ ΡƒΠΌΠ΅Π΅ΠΌ ΠΏΠΈΡΠ°Ρ‚ΡŒ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ поэтому посмотрим сначала Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ интСрфСйс seccomp. Π£ΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΌΠΎΠΆΠ½ΠΎ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ процСсса, ΠΏΡ€ΠΈ этом всС Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы Π±ΡƒΠ΄ΡƒΡ‚ ограничСния Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ. ДСлаСтся это ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ систСмного Π²Ρ‹Π·ΠΎΠ²Π° seccomp(2):

seccomp(SECCOMP_SET_MODE_FILTER, flags, &filter)

Π³Π΄Π΅ &filter β€” это ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΡƒΠΆΠ΅ Π·Π½Π°ΠΊΠΎΠΌΡƒΡŽ Π½Π°ΠΌ структуру struct sock_fprog, Ρ‚.Π΅. ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ BPF.

Π§Π΅ΠΌ ΠΆΠ΅ ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ для seccomp ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ для сокСтов? ΠŸΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹ΠΌ контСкстом. Π’ случаС сокСтов, Π½Π°ΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π»Π°ΡΡŒ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ памяти, содСрТащая ΠΏΠ°ΠΊΠ΅Ρ‚, Π° Π² случаС seccomp Π½Π°ΠΌ пСрСдаСтся структура Π²ΠΈΠ΄Π°

struct seccomp_data {
    int   nr;
    __u32 arch;
    __u64 instruction_pointer;
    __u64 args[6];
};

Π—Π΄Π΅ΡΡŒ nr β€” это Π½ΠΎΠΌΠ΅Ρ€ запускаСмого систСмного Π²Ρ‹Π·ΠΎΠ²Π°, arch β€” тСкущая Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° (ΠΎΠ± этом Π½ΠΈΠΆΠ΅), args β€” Π΄ΠΎ ΡˆΠ΅ΡΡ‚ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² систСмного Π²Ρ‹Π·ΠΎΠ²Π°, Π° instruction_pointer β€” это ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΈΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ Π² пространствС ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, которая сдСлала Π΄Π°Π½Π½Ρ‹ΠΉ систСмный Π²Ρ‹Π·ΠΎΠ². Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ Π½ΠΎΠΌΠ΅Ρ€ систСмного Π²Ρ‹Π·ΠΎΠ²Π° Π² рСгистр A ΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ

ldw [0]

Для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ seccomp ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ особСнности, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, доступ ΠΊ контСксту Π²ΠΎΠ·ΠΌΠΎΠΆΠ΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ 32-Π±ΠΈΡ‚Π½ΠΎΠΌΡƒ Π²Ρ‹Ρ€Π°Π²Π½ΠΈΠ²Π°Π½ΠΈΡŽ ΠΈ нСльзя Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ ΠΏΠΎΠ»-слова ΠΈΠ»ΠΈ Π±Π°ΠΉΡ‚ β€” ΠΏΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ldh [0] систСмный Π²Ρ‹Π·ΠΎΠ² seccomp Π²Π΅Ρ€Π½Π΅Ρ‚ EINVAL. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² выполняСт функция seccomp_check_filter() ядра. (Из смСшного, Π² ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΌ ΠΊΠΎΠΌΠΌΠΈΡ‚Π΅, Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‰Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ seccomp, Π² эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π·Π°Π±Ρ‹Π»ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π½Π° использованиС инструкции mod (остаток ΠΎΡ‚ дСлСния) ΠΈ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΠ½Π° нСдоступна для seccomp BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π΅Π΅ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ сломаСт ABI.)

Π’ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, ΠΌΡ‹ ΡƒΠΆΠ΅ Π·Π½Π°Π΅ΠΌ всС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ seccomp ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. ΠžΠ±Ρ‹Ρ‡Π½ΠΎ Π»ΠΎΠ³ΠΈΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ устроСна ΠΊΠ°ΠΊ Π±Π΅Π»Ρ‹ΠΉ ΠΈΠ»ΠΈ Ρ‡Π΅Ρ€Π½Ρ‹ΠΉ список систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ², Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°

ld [0]
jeq #304, bad
jeq #176, bad
jeq #239, bad
jeq #279, bad
good: ret #0x7fff0000 /* SECCOMP_RET_ALLOW */
bad: ret #0

провСряСт Ρ‡Π΅Ρ€Π½Ρ‹ΠΉ список ΠΈΠ· Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅Ρ… систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΏΠΎΠ΄ Π½ΠΎΠΌΠ΅Ρ€Π°ΠΌΠΈ 304, 176, 239, 279. Π§Ρ‚ΠΎ ΠΆΠ΅ это Π·Π° систСмныС Π²Ρ‹Π·ΠΎΠ²Ρ‹? ΠœΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ Ρ‚ΠΎΡ‡Π½ΠΎ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΌΡ‹ Π½Π΅ Π·Π½Π°Π΅ΠΌ для ΠΊΠ°ΠΊΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ писалась ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π°Π²Ρ‚ΠΎΡ€Ρ‹ seccomp ΠΏΡ€Π΅Π΄Π»Π°Π³Π°ΡŽΡ‚ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒ всС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ с ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ (тСкущая Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° указываСтся Π² контСкстС ΠΊΠ°ΠΊ ΠΏΠΎΠ»Π΅ arch структуры struct seccomp_data). Π‘ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ Π½Π°Ρ‡Π°Π»ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° выглядСло Π±Ρ‹ ΠΊΠ°ΠΊ:

ld [4]
jne #0xc000003e, bad_arch ; SCMP_ARCH_X86_64

ΠΈ Ρ‚ΠΎΠ³Π΄Π° наши Π½ΠΎΠΌΠ΅Ρ€Π° систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Π±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ значСния.

ПишСм ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ для seccomp ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ libseccomp

НаписаниС Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² Π² ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹Ρ… ΠΊΠΎΠ΄Π°Ρ… ΠΈΠ»ΠΈ для ассСмблСра BPF позволяСт ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Π½Π°Π΄ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ, Π½ΠΎ Π² Ρ‚ΠΎ ΠΆΠ΅ врСмя ΠΈΠ½ΠΎΠ³Π΄Π° ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½Π΅Π΅ ΠΈΠΌΠ΅Ρ‚ΡŒ пСрСносимый ΠΈ/ΠΈΠ»ΠΈ Ρ‡ΠΈΡ‚Π°Π΅ΠΌΡ‹ΠΉ ΠΊΠΎΠ΄. Π’ этом Π½Π°ΠΌ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libseccomp, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π°Ρ стандартный интСрфСйс для написания Ρ‡Π΅Ρ€Π½Ρ‹Ρ… ΠΈΠ»ΠΈ Π±Π΅Π»Ρ‹Ρ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ².

Π”Π°Π²Π°ΠΉΡ‚Π΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, напишСм ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, которая запускаСт Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΏΠΎ Π²Ρ‹Π±ΠΎΡ€Ρƒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, установив, ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, Ρ‡Π΅Ρ€Π½Ρ‹ΠΉ список систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΈΠ· Π²Ρ‹ΡˆΠ΅ΡƒΠΏΠΎΠΌΡΠ½ΡƒΡ‚ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ (ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½Π° для большСй читаСмости, ΠΏΠΎΠ»Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Ρ‚ΡƒΡ‚):

#include <seccomp.h>
#include <unistd.h>
#include <err.h>

static int sys_numbers[] = {
        __NR_mount,
        __NR_umount2,
       // ... Π΅Ρ‰Π΅ 40 систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ...
        __NR_vmsplice,
        __NR_perf_event_open,
};

int main(int argc, char **argv)
{
        scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);

        for (size_t i = 0; i < sizeof(sys_numbers)/sizeof(sys_numbers[0]); i++)
                seccomp_rule_add(ctx, SCMP_ACT_TRAP, sys_numbers[i], 0);

        seccomp_load(ctx);

        execvp(argv[1], &argv[1]);
        err(1, "execlp: %s", argv[1]);
}

Π’Π½Π°Ρ‡Π°Π»Π΅ ΠΌΡ‹ опрСдСляСм массив sys_numbers ΠΈΠ· 40+ Π½ΠΎΠΌΠ΅Ρ€ΠΎΠ² систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² для Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ. Π—Π°Ρ‚Π΅ΠΌ, ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ контСкст ctx ΠΈ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΡ‚ΡŒ (SCMP_ACT_ALLOW) всС систСмныС Π²Ρ‹Π·ΠΎΠ²Ρ‹ ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ (ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π½Ρ‹Π΅ списки ΠΏΡ€ΠΎΡ‰Π΅). Π—Π°Ρ‚Π΅ΠΌ, ΠΎΠ΄ΠΈΠ½ Π·Π° ΠΎΠ΄Π½ΠΈΠΌ, ΠΌΡ‹ добавляСм всС систСмныС Π²Ρ‹Π·ΠΎΠ²Ρ‹ ΠΈΠ· Ρ‡Π΅Ρ€Π½ΠΎΠ³ΠΎ списка. Π’ качСствС Ρ€Π΅Π°ΠΊΡ†ΠΈΠΈ Π½Π° систСмный Π²Ρ‹Π·ΠΎΠ² ΠΈΠ· списка ΠΌΡ‹ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌ SCMP_ACT_TRAP, Π² этом случаС seccomp ΠΏΠΎΡˆΠ»Π΅Ρ‚ процСссу сигнал SIGSYS с описаниСм Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊΠΎΠΉ ΠΈΠΌΠ΅Π½Π½ΠΎ систСмный Π²Ρ‹Π·ΠΎΠ² Π½Π°Ρ€ΡƒΡˆΠΈΠ» ΠΏΡ€Π°Π²ΠΈΠ»Π°. НаконСц, ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Π² ядро ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ seccomp_load, которая скомпилируСт ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ Π΅Π΅ ΠΊ процСссу ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ систСмного Π²Ρ‹Π·ΠΎΠ²Π° seccomp(2).

Для ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΉ компиляции ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Π½ΡƒΠΆΠ½ΠΎ ΡΠ»ΠΈΠ½ΠΊΠΎΠ²Π°Ρ‚ΡŒ с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ libseccomp, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

cc -std=c17 -Wall -Wextra -c -o seccomp_lib.o seccomp_lib.c
cc -o seccomp_lib seccomp_lib.o -lseccomp

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ запуска:

$ ./seccomp_lib echo ok
ok

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ систСмного Π²Ρ‹Π·ΠΎΠ²Π°:

$ sudo ./seccomp_lib mount -t bpf bpf /tmp
Bad system call

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ strace, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ·Π½Π°Ρ‚ΡŒ подробности:

$ sudo strace -e seccomp ./seccomp_lib mount -t bpf bpf /tmp
seccomp(SECCOMP_SET_MODE_FILTER, 0, {len=50, filter=0x55d8e78428e0}) = 0
--- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0xboobdeadbeef, si_syscall=__NR_mount, si_arch=AUDIT_ARCH_X86_64} ---
+++ killed by SIGSYS (core dumped) +++
Bad system call

ΠΎΡ‚ΠΊΡƒΠ΄Π° ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡƒΠ·Π½Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π±Ρ‹Π»Π° Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° ΠΈΠ·-Π·Π° использования Π·Π°ΠΏΡ€Π΅Ρ‰Π΅Π½Π½ΠΎΠ³ΠΎ систСмного Π²Ρ‹Π·ΠΎΠ²Π° mount(2).

Π˜Ρ‚ΠΎΠ³ΠΎ, ΠΌΡ‹ написали Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ libseccomp, умСстив Π½Π΅Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ Π² Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ строчки. Π’ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ большого количСства систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² врСмя выполнСния ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Ρ‚Π½ΠΎ ΠΏΠΎΠ½ΠΈΠ·ΠΈΡ‚ΡŒΡΡ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° β€” это просто список сравнСний. Для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π΅Π΄Π°Π²Π½ΠΎ Π² libseccomp Π±Ρ‹Π» Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ ΠΏΠ°Ρ‚Ρ‡, Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π° Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° SCMP_FLTATR_CTL_OPTIMIZE. Если ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ этот Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ Ρ€Π°Π²Π½Ρ‹ΠΌ 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

НичСго сущСствСнно Π±ΠΎΠ»Π΅Π΅ быстроС Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π½Π΅ получится, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ BPF Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠΎΠ²Π΅Ρ€ΡˆΠ°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρ‹ ΠΏΠΎ отступу (ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, jmp A ΠΈΠ»ΠΈ jmp [label+X]) ΠΈ поэтому всС ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρ‹ статичСскиС.

seccomp ΠΈ strace

ВсС Π·Π½Π°ΡŽΡ‚ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρƒ 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, ΠΈ Ρ‚.ΠΏ.

BPF для самых ΠΌΠ°Π»Π΅Π½ΡŒΠΊΠΈΡ…, Ρ‡Π°ΡΡ‚ΡŒ нулСвая: classic BPF

ΠŸΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ 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.

BPF для самых ΠΌΠ°Π»Π΅Π½ΡŒΠΊΠΈΡ…, Ρ‡Π°ΡΡ‚ΡŒ нулСвая: classic BPF

ΠŸΡ€ΠΈ использовании ΠΎΠΏΡ†ΠΈΠΈ --seccomp-bpf Π΅ΡΡ‚ΡŒ Π΄Π²Π° ограничСния. Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Π½Π΅ получится ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒΡΡ ΠΊ ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΌΡƒ процСссу (опция -p ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ strace), Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это Π½Π΅ поддСрТиваСтся seccomp. Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, Π½Π΅Ρ‚ возмоТности Π½Π΅ ΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π½Π° Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ seccomp Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ Π½Π°ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ΡΡ всСми Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ процСссами Π±Π΅Π· возмоТности ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ это.

Π§ΡƒΡ‚ΡŒ большС подробностСй ΠΎ Ρ‚ΠΎΠΌ ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ strace Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ с seccomp ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ·Π½Π°Ρ‚ΡŒ ΠΈΠ· Π½Π΅Π΄Π°Π²Π½Π΅Π³ΠΎ Π΄ΠΎΠΊΠ»Π°Π΄Π°. Для нас ΠΆΠ΅ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ интСрСсным Ρ„Π°ΠΊΡ‚ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ классичСский BPF Π² Π»ΠΈΡ†Π΅ seccomp Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ примСнСния Π΄ΠΎ сих ΠΏΠΎΡ€.

xt_bpf

ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΠΌΡΡ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Π² ΠΌΠΈΡ€ сСтСй.

ΠŸΡ€Π΅Π΄Ρ‹ΡΡ‚ΠΎΡ€ΠΈΡ: Π΄Π°Π²Π½Ρ‹ΠΌ-Π΄Π°Π²Π½ΠΎ, Π² 2007 Π³ΠΎΠ΄Ρƒ, Π² ядро Π±Ρ‹Π» Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ xt_u32 для netfilter. Он Π±Ρ‹Π» написан ΠΏΠΎ Π°Π½Π°Π»ΠΎΠ³ΠΈΠΈ с Π΅Ρ‰Π΅ Π±ΠΎΠ»Π΅Π΅ Π΄Ρ€Π΅Π²Π½ΠΈΠΌ классификатором Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° cls_u32 ΠΈ позволял ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹Π΅ Π±ΠΈΠ½Π°Ρ€Π½Ρ‹Π΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° для iptables ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… простых ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ: Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ 32 Π±ΠΈΡ‚Π° ΠΈΠ· ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ ΠΏΡ€ΠΎΠ΄Π΅Π»Π°Ρ‚ΡŒ с Π½ΠΈΠΌΠΈ Π½Π°Π±ΠΎΡ€ арифмСтичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. НапримСр,

sudo iptables -A INPUT -m u32 --u32 "6&0xFF=1" -j LOG --log-prefix "seen-by-xt_u32"

Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ 32 Π±ΠΈΡ‚Π° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° IP, начиная с отступа 6, ΠΈ примСняСт ΠΊ Π½ΠΈΠΌ маску 0xFF (Π²Π·ΡΡ‚ΡŒ младший Π±Π°ΠΉΡ‚). Π­Ρ‚ΠΎ β€” ΠΏΠΎΠ»Π΅ protocol Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° IP ΠΈ ΠΌΡ‹ Π΅Π³ΠΎ сравниваСм с 1 (ICMP). Π’ ΠΎΠ΄Π½ΠΎΠΌ ΠΏΡ€Π°Π²ΠΈΠ»Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ, Π° Π΅Ρ‰Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ @ β€” ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π½Π° X Π±Π°ΠΉΡ‚ Π²ΠΏΡ€Π°Π²ΠΎ. НапримСр, ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ

iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4=0x29"

провСряСт, Π½Π΅ Ρ€Π°Π²Π΅Π½ Π»ΠΈ TCP Sequence Number 0x29. НС Π±ΡƒΠ΄Ρƒ дальшС Π²Π΄Π°Π²Π°Ρ‚ΡŒΡΡ Π² подробности, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΡƒΠΆΠ΅ ясно, Ρ‡Ρ‚ΠΎ Ρ€ΡƒΠΊΠ°ΠΌΠΈ Ρ‚Π°ΠΊΠΈΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° ΠΏΠΈΡΠ°Ρ‚ΡŒ Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ ΡƒΠ΄ΠΎΠ±Π½ΠΎ. Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ BPF β€” the forgotten bytecode, Π΅ΡΡ‚ΡŒ нСсколько ссылок с ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ использования ΠΈ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΏΡ€Π°Π²ΠΈΠ» для xt_u32. Π‘ΠΌ. Ρ‚Π°ΠΊΠΆΠ΅ ссылки Π² ΠΊΠΎΠ½Ρ†Π΅ этой ΡΡ‚Π°Ρ‚ΡŒΠΈ.

Начиная с 2013 Π³ΠΎΠ΄Π° ΠΌΠΎΠ΄ΡƒΠ»ΡŒ вмСсто модуля xt_u32 ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ основанный Π½Π° BPF ΠΌΠΎΠ΄ΡƒΠ»ΡŒ xt_bpf. ВсСм Π΄ΠΎΡ‡ΠΈΡ‚Π°Π²ΡˆΠΈΠΌ Π΄ΠΎ сюда ΡƒΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ясСн ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ Π΅Π³ΠΎ Ρ€Π°Π±ΠΎΡ‚Ρ‹: Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄ BPF Π² качСствС ΠΏΡ€Π°Π²ΠΈΠ» iptables. Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²ΠΎΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ ΠΌΠΎΠΆΠ½ΠΎ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‚Π°ΠΊ:

iptables -A INPUT -m bpf --bytecode <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> -j LOG

здСсь <Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄> β€” это ΠΊΠΎΠ΄ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ Π²Ρ‹Π²ΠΎΠ΄Π° ассСмблСра bpf_asm ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€,

$ cat /tmp/test.bpf
ldb [9]
jneq #17, ignore
ret #1
ignore: ret #0

$ bpf_asm /tmp/test.bpf
4,48 0 0 9,21 0 1 17,6 0 0 1,6 0 0 0,

# iptables -A INPUT -m bpf --bytecode "$(bpf_asm /tmp/test.bpf)" -j LOG

Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΡƒΠ΅ΠΌ всС UDP ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ для BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² ΠΌΠΎΠ΄ΡƒΠ»Π΅ xt_bpf, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π°, Π² случаС iptables β€” Π½Π° Π½Π°Ρ‡Π°Π»ΠΎ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° IPv4. Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π±ΡƒΠ»Π΅Π²ΠΎ, Π³Π΄Π΅ false ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ Π½Π΅ совпал.

ΠŸΠΎΠ½ΡΡ‚Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ xt_bpf ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Π±ΠΎΠ»Π΅Π΅ слоТныС Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹, Ρ‡Π΅ΠΌ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π²Ρ‹ΡˆΠ΅. Π”Π°Π²Π°ΠΉΡ‚Π΅ посмотрим Π½Π° настоящиС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΎΡ‚ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ Cloudfare. Π”ΠΎ Π½Π΅Π΄Π°Π²Π½Π΅Π³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΎΠ½ΠΈ использовали ΠΌΠΎΠ΄ΡƒΠ»ΡŒ xt_bpf для Π·Π°Ρ‰ΠΈΡ‚Ρ‹ ΠΎΡ‚ DDoS Π°Ρ‚Π°ΠΊ. Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ Introducing the BPF Tools ΠΎΠ½ΠΈ Ρ€Π°ΡΡΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ ΠΊΠ°ΠΊ (ΠΈ ΠΏΠΎΡ‡Π΅ΠΌΡƒ) ΠΎΠ½ΠΈ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΡŽΡ‚ BPF Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ ссылки Π½Π° Π½Π°Π±ΠΎΡ€ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ для создания Ρ‚Π°ΠΊΠΈΡ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ². НапримСр, ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ bpfgen ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, которая ΠΌΠ°Ρ‚Ρ‡ΠΈΡ‚ DNS-запрос Π½Π° имя habr.com:

$ ./bpfgen --assembly dns -- habr.com
ldx 4*([0]&0xf)
ld #20
add x
tax

lb_0:
    ld [x + 0]
    jneq #0x04686162, lb_1
    ld [x + 4]
    jneq #0x7203636f, lb_1
    ldh [x + 8]
    jneq #0x6d00, lb_1
    ret #65535

lb_1:
    ret #0

Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΌΡ‹ сначала Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π² рСгистр X адрСс Π½Π°Ρ‡Π°Π»Π° строки x04habrx03comx00 Π²Π½ΡƒΡ‚Ρ€ΠΈ UDP-Π΄Π°Ρ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ ΠΏΠΎΡ‚ΠΎΠΌ провСряСм запрос: 0x04686162 <-> "x04hab" ΠΈ Ρ‚.Π΄.

НСмного ΠΏΠΎΠ·ΠΆΠ΅ Cloudfare ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π»Π° ΠΊΠΎΠ΄ компилятора p0f -> BPF. Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ Introducing the p0f BPF compiler ΠΎΠ½ΠΈ Ρ€Π°ΡΡΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ p0f ΠΈ ΠΊΠ°ΠΊ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ p0f сигнатуры Π² BPF:

$ ./bpfgen p0f -- 4:64:0:0:*,0::ack+:0
39,0 0 0 0,48 0 0 8,37 35 0 64,37 0 34 29,48 0 0 0,
84 0 0 15,21 0 31 5,48 0 0 9,21 0 29 6,40 0 0 6,
...

Π’ настоящий ΠΌΠΎΠΌΠ΅Π½Ρ‚ Cloudfare большС Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ xt_bpf, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ ΠΏΠ΅Ρ€Π΅Π΅Ρ…Π°Π»ΠΈ Π½Π° XDP β€” ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² использования Π½ΠΎΠ²ΠΎΠΉ вСрсии BPF, см. L4Drop: XDP DDoS Mitigations.

cls_bpf

ПослСдний ΠΈΠ· ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² использования классичСского BPF Π² ядрС β€” это классификатор cls_bpf для подсистСмы контроля Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Π² Linux, Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½Ρ‹ΠΉ Π² Linux Π² ΠΊΠΎΠ½Ρ†Π΅ 2013 Π³ΠΎΠ΄Π° ΠΈ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎ замСнивший Π΄Ρ€Π΅Π²Π½ΠΈΠΉ cls_u32.

ΠœΡ‹, ΠΎΠ΄Π½Π°ΠΊΠΎ, Π½Π΅ Π±ΡƒΠ΄Π΅ΠΌ сСйчас ΠΎΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ cls_bpf, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Π·Π½Π°Π½ΠΈΠΉ ΠΎ классичСском BPF это Π½Π°ΠΌ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ даст β€” ΠΌΡ‹ ΡƒΠΆΠ΅ познакомились со всСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΡŽ. К Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅, Π² ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΡΡ‚Π°Ρ‚ΡŒΡΡ…, Ρ€Π°ΡΡΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΡ… ΠΎΠ± Extended BPF, ΠΌΡ‹ Π΅Ρ‰Π΅ Π½Π΅ Ρ€Π°Π· встрСтимся с этим классификатором.

Π•Ρ‰Π΅ ΠΎΠ΄Π½Π° ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π° Π½Π΅ Ρ€Π°ΡΡΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΎΠ± использовании классичСского BPF c cls_bpf Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с Extended BPF Π² этом случаС ΠΊΠ°Ρ€Π΄ΠΈΠ½Π°Π»ΡŒΠ½ΠΎ суТаСтся ΠΎΠ±Π»Π°ΡΡ‚ΡŒ примСнимости: классичСскиС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΠΌΠ΅Π½ΡΡ‚ΡŒ содСрТимоС ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ состояниС ΠΌΠ΅ΠΆΠ΄Ρƒ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ.

Π’Π°ΠΊ Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΡˆΠ»ΠΎ врСмя ΠΏΠΎΠΏΡ€ΠΎΡ‰Π°Ρ‚ΡŒΡΡ с классичСским BPF ΠΈ Π·Π°Π³Π»ΡΠ½ΡƒΡ‚ΡŒ Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅Π΅.

ΠŸΡ€ΠΎΡ‰Π°Π½ΠΈΠ΅ с classic BPF

ΠœΡ‹ посмотрСли Π½Π° Ρ‚ΠΎ, ΠΊΠ°ΠΊ тСхнология BPF, разработанная Π² Π½Π°Ρ‡Π°Π»Π΅ дСвяностых ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ ΠΏΡ€ΠΎΠΆΠΈΠ»Π° Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚ΡŒ Π²Π΅ΠΊΠ° ΠΈ Π΄ΠΎ ΠΊΠΎΠ½Ρ†Π° Π½Π°Ρ…ΠΎΠ΄ΠΈΠ»Π° Π½ΠΎΠ²Ρ‹Π΅ примСнСния. Однако, ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρƒ со стСковых машин Π½Π° RISC, ΠΏΠΎΡΠ»ΡƒΠΆΠΈΠ²ΡˆΠ΅ΠΌΡƒ Ρ‚ΠΎΠ»Ρ‡ΠΊΠΎΠΌ ΠΊ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ классичСского BPF, Π² двухтысячныС случился ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ с 32-Π±ΠΈΡ‚Π½Ρ‹Ρ… Π½Π° 64-Π±ΠΈΡ‚Π½Ρ‹Π΅ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ ΠΈ классичСский BPF стал ΡƒΡΡ‚Π°Ρ€Π΅Π²Π°Ρ‚ΡŒ. ΠšΡ€ΠΎΠΌΠ΅ этого, возмоТности классичСского BPF сильно ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Ρ‹ ΠΈ ΠΏΠΎΠΌΠΈΠΌΠΎ ΡƒΡΡ‚Π°Ρ€Π΅Π²ΡˆΠ΅ΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ β€” Ρƒ нас Π½Π΅Ρ‚ возмоТности ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ состояниС ΠΌΠ΅ΠΆΠ΄Ρƒ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, Π½Π΅Ρ‚ возмоТности прямого взаимодСйствия с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ, Π½Π΅Ρ‚ возмоТности взаимодСйствия с ядром, ΠΊΡ€ΠΎΠΌΠ΅ чтСния ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ количСства ΠΏΠΎΠ»Π΅ΠΉ структуры sk_buff ΠΈ запуска ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΡ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ-ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊΠΎΠ², нСльзя ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ содСрТимоС ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΈ ΠΏΠ΅Ρ€Π΅Π°Π΄Ρ€Π΅ΡΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡ….

На самом Π΄Π΅Π»Π΅, Π² настоящСС врСмя ΠΎΡ‚ классичСского BPF Π² Linux остался Ρ‚ΠΎΠ»ΡŒΠΊΠΎ API интСрфСйс, Π° Π²Π½ΡƒΡ‚Ρ€ΠΈ ядра всС классичСскиС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π±ΡƒΠ΄ΡŒ Ρ‚ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ сокСтов ΠΈΠ»ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ seccomp, автоматичСски Ρ‚Ρ€Π°Π½ΡΠ»ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π² Π½ΠΎΠ²Ρ‹ΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, Extended BPF. (ΠœΡ‹ расскаТСм ΠΏΡ€ΠΎ Ρ‚ΠΎ ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ это происходит Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅.)

ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π½Π° Π½ΠΎΠ²ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ начался Π² 2013 Π³ΠΎΠ΄Ρƒ, ΠΊΠΎΠ³Π΄Π° АлСксСй Π‘Ρ‚Π°Ρ€ΠΎΠ²ΠΎΠΉΡ‚ΠΎΠ² ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠΈΠ» схСму обновлСния BPF. Π’ 2014 Π³ΠΎΠ΄Ρƒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠ°Ρ‚Ρ‡ΠΈ стали ΠΏΠΎΡΠ²Π»ΡΡ‚ΡŒΡΡ Π² ядрС. Насколько я понимаю, ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Π°Π»ΠΎΡΡŒ лишь ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΈ JIT-compiler для Π±ΠΎΠ»Π΅Π΅ эффСктивной Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π½Π° 64-Π±ΠΈΡ‚Π½Ρ‹Ρ… ΠΌΠ°ΡˆΠΈΠ½Π°Ρ…, Π½ΠΎ вмСсто этого эти ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ»ΠΎΠΆΠΈΠ»ΠΈ Π½Π°Ρ‡Π°Π»ΠΎ Π½ΠΎΠ²ΠΎΠΉ Π³Π»Π°Π²Π΅ Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ Linux.

Π”Π°Π»ΡŒΠ½Π΅ΠΉΡˆΠΈΠ΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ Π² этой сСрии расскаТут ΠΎΠ± Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π΅ ΠΈ примСнСниях Π½ΠΎΠ²ΠΎΠΉ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ, ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ извСстной ΠΊΠ°ΠΊ internal BPF, Π·Π°Ρ‚Π΅ΠΌ extended BPF, Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠ°ΠΊ просто BPF.

Бсылки

  1. Steven McCanne and Van Jacobson, "The BSD Packet Filter: A New Architecture for User-level Packet Capture", https://www.tcpdump.org/papers/bpf-usenix93.pdf
  2. Steven McCanne, "libpcap: An Architecture and Optimization Methodology for Packet Capture", https://sharkfestus.wireshark.org/sharkfest.11/presentations/McCanne-Sharkfest'11_Keynote_Address.pdf
  3. tcpdump, libpcap: https://www.tcpdump.org/
  4. IPtable U32 Match Tutorial.
  5. BPF β€” the forgotten bytecode: https://blog.cloudflare.com/bpf-the-forgotten-bytecode/
  6. Introducing the BPF Tool: https://blog.cloudflare.com/introducing-the-bpf-tools/
  7. bpf_cls: http://man7.org/linux/man-pages/man8/tc-bpf.8.html
  8. A seccomp overview: https://lwn.net/Articles/656307/
  9. https://github.com/torvalds/linux/blob/master/Documentation/userspace-api/seccomp_filter.rst
  10. habr: ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ: seccomp
  11. habr: Π˜Π·ΠΎΠ»ΠΈΡ€ΡƒΠ΅ΠΌ Π΄Π΅ΠΌΠΎΠ½Ρ‹ с systemd ΠΈΠ»ΠΈ Β«Π²Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ΅Π½ Docker для этого!Β»
  12. Paul Chaignon, "strace —seccomp-bpf: a look under the hood", https://fosdem.org/2020/schedule/event/debugging_strace_bpf/
  13. netsniff-ng: http://netsniff-ng.org/

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ