Китоби "BPF барои мониторинги Linux"

Китоби "BPF барои мониторинги Linux"Салом, сокинони Хабро! Мошини виртуалии BPF яке аз муҳимтарин ҷузъҳои ядрои Linux мебошад. Истифодаи дурусти он ба муҳандисони система имкон медиҳад, ки камбудиҳоро пайдо кунанд ва ҳатто мушкилоти мураккабтаринро ҳал кунанд. Шумо тарзи навиштани барномаҳоеро меомӯзед, ки рафтори ядроро назорат ва тағир медиҳанд, чӣ гуна бехатар татбиқ кардани код барои мониторинги рӯйдодҳо дар ядро ​​​​ва ғайра. Дэвид Калавера ва Лоренцо Фонтана ба шумо дар кушодани қудрати BPF кӯмак мекунанд. Дониши худро дар бораи оптимизатсияи фаъолият, шабакасозӣ ва амният васеъ кунед. - Барои назорат ва тағир додани рафтори ядрои Linux BPF-ро истифода баред. - Рамзро ворид кунед, то рӯйдодҳои ядроро бехатар назорат кунед, бидуни тарк кардани ядро ​​ё аз нав оғоз кардани система. — Намунаҳои рамзи мувофиқро дар C, Go ё Python истифода баред. - Бо соҳиби давраи ҳаёти барномаи BPF назорат кунед.

Амнияти ядрои Linux, Хусусиятҳои он ва Seccomp

BPF роҳи пурқудрати васеъ кардани ядроро бидуни қурбонии субот, амният ва суръат таъмин мекунад. Аз ин сабаб, таҳиягарони ядро ​​фикр мекарданд, ки истифодаи универсалии он барои беҳтар кардани ҷудокунии раванд дар Seccomp тавассути татбиқи филтрҳои Seccomp, ки аз ҷониби барномаҳои BPF дастгирӣ мешаванд, инчунин бо номи Seccomp BPF маъруф аст. Дар ин боб мо мефаҳмонем, ки Seccomp чист ва он чӣ гуна истифода мешавад. Он гоҳ шумо мефаҳмед, ки чӣ тавр бо истифода аз барномаҳои BPF филтрҳои Seccomp нависед. Баъд аз ин, мо ба қалмоқҳои дарунсохташудаи BPF, ки ба ядро ​​​​барои модулҳои амнияти Linux дохил карда шудаанд, дида мебароем.

Модулҳои Амнияти Linux (LSM) чаҳорчӯбае мебошанд, ки маҷмӯи функсияҳоро таъмин мекунанд, ки метавонанд барои татбиқи моделҳои гуногуни амниятӣ ба таври стандартӣ истифода шаванд. LSM-ро мустақиман дар дарахти манбаи ядро ​​истифода бурдан мумкин аст, ба монанди Apparmor, SELinux ва Tomoyo.

Биёед аз муҳокимаи имкониятҳои Linux оғоз кунем.

Хусусиятҳои

Моҳияти қобилиятҳои Linux дар он аст, ки шумо бояд ба раванди беимтиёз барои иҷрои вазифаи муайян иҷозат диҳед, аммо бидуни истифодаи suid барои ин мақсад, ё ба таври дигар равандро имтиёзнок созед, эҳтимолияти ҳамларо коҳиш диҳед ва ба раванд барои иҷрои вазифаҳои муайян иҷозат диҳед. Масалан, агар замимаи шумо бояд бандари имтиёзнок кушояд, масалан 80, ба ҷои он ки раванд ҳамчун реша иҷро шавад, шумо метавонед ба он танҳо қобилияти CAP_NET_BIND_SERVICE диҳед.

Барномаи Go-ро бо номи main.go баррасӣ кунед:

package main
import (
            "net/http"
            "log"
)
func main() {
     log.Fatalf("%v", http.ListenAndServe(":80", nil))
}

Ин барнома ба сервери HTTP дар порти 80 хизмат мерасонад (ин порти имтиёзнок аст). Одатан мо онро фавран пас аз тартиб додан иҷро мекунем:

$ go build -o capabilities main.go
$ ./capabilities

Аммо, азбаски мо имтиёзҳои решавӣ намедиҳем, ин код ҳангоми пайваст кардани порт хато хоҳад кард:

2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1

capsh (менеҷери ниҳонӣ) абзорест, ки ҷабҳаро бо маҷмӯи мушаххаси қобилиятҳо идора мекунад.

Дар ин ҳолат, тавре ки аллакай зикр гардид, ба ҷои додани ҳуқуқи пурраи реша, шумо метавонед пайвасти имтиёзноки портро тавассути таъмин намудани қобилияти cap_net_bind_service дар баробари ҳама чизҳои дар барнома мавҷудбуда фаъол созед. Барои ин, мо метавонем барномаи худро бо capsh замима кунем:

# capsh --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' 
   --keep=1 --user="nobody" 
   --addamb=cap_net_bind_service -- -c "./capabilities"

Биёед ин дастаро каме фаҳмем.

  • capsh - capsh ҳамчун ҷилди истифода баред.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - азбаски мо бояд корбарро иваз кунем (мо намехоҳем ҳамчун реша кор кунем), мо cap_net_bind_service ва қобилияти воқеан тағир додани ID-и корбарро аз реша ба ҳеҷ кас, яъне cap_setuid ва cap_setgid.
  • —keep=1 — мо мехоҳем, ки ҳангоми гузаштан аз ҳисоби решавӣ қобилиятҳои насбшударо нигоҳ дорем.
  • —user=“ҳеҷ кас” — корбари ниҳоӣ, ки барномаро иҷро мекунад, ҳеҷ кас нахоҳад буд.
  • —addamb=cap_net_bind_service — тозакунии қобилиятҳои алоқамандро пас аз гузаштан аз решавӣ муқаррар кунед.
  • - -c "./capabilities" - танҳо барномаро иҷро кунед.

Имкониятҳои алоқаманд як намуди махсуси қобилиятҳо мебошанд, ки аз ҷониби барномаҳои кӯдакон мерос гирифта мешаванд, вақте ки барномаи ҷорӣ онҳоро бо истифода аз execve() иҷро мекунад. Танҳо қобилиятҳое, ки барои алоқаманд шудан иҷозат дода шудаанд, ё ба ибораи дигар, ҳамчун қобилиятҳои муҳити зист, метавонанд мерос шаванд.

Эҳтимол шумо дар ҳайрат бошед, ки +eip пас аз муайян кардани қобилият дар опсияи --caps чӣ маъно дорад. Ин парчамҳо барои муайян кардани қобилият истифода мешаванд:

-бояд фаъол карда шавад (р);

- барои истифода дастрас (д);

-метавонад тавассути равандҳои кӯдак мерос гирифта шавад (i).

Азбаски мо мехоҳем cap_net_bind_service -ро истифода барем, мо бояд инро бо парчами e иҷро кунем. Пас аз он мо дар фармон shell оғоз мекунем. Ин имконотро бинарӣ иҷро мекунад ва мо бояд онро бо парчами i қайд кунем. Ниҳоят, мо мехоҳем, ки ин хусусият фаъол карда шавад (мо ин корро бидуни тағир додани UID анҷом додем) бо p. Чунин ба назар мерасад cap_net_bind_service+eip.

Шумо метавонед натиҷаро бо истифода аз ss тафтиш кунед. Биёед баромадро каме кӯтоҳ кунем, то дар саҳифа мувофиқат кунад, аммо он порти алоқаманд ва ID корбарро ғайр аз 0 нишон медиҳад, дар ин ҳолат 65:

# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0

Дар ин мисол мо capsh-ро истифода мебарем, аммо шумо метавонед бо истифода аз libcap shell нависед. Барои маълумоти иловагӣ, ба man 3 libcap нигаред.

Ҳангоми навиштани барномаҳо, аксар вақт таҳиякунанда ҳама хусусиятҳоеро, ки барнома дар вақти иҷро лозим аст, пешакӣ намедонад; Ғайр аз он, ин хусусиятҳо метавонанд дар версияҳои нав тағйир диҳанд.

Барои беҳтар фаҳмидани имкониятҳои барномаи мо, мо метавонем асбоби қобилияти BCC-ро гирем, ки kprobe-ро барои функсияи ядрои cap_capable муқаррар мекунад:

/usr/share/bcc/tools/capable
TIME      UID  PID   TID   COMM               CAP    NAME           AUDIT
10:12:53 0 424     424     systemd-udevd 12 CAP_NET_ADMIN         1
10:12:57 0 1103   1101   timesync        25 CAP_SYS_TIME         1
10:12:57 0 19545 19545 capabilities       10 CAP_NET_BIND_SERVICE 1

Мо метавонем ба ҳамин чиз бо истифода аз bpftrace бо kprobe як-лайнер дар функсияи ядрои cap_capable ноил шавем:

bpftrace -e 
   'kprobe:cap_capable {
      time("%H:%M:%S ");
      printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
    }' 
    | grep -i capabilities

Агар имкониятҳои барномаи мо пас аз kprobe фаъол карда шаванд, ин як чизи зеринро медиҳад:

12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 21 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 12 0
12:01:56 1000 13524 capabilities 10 1

Сутуни панҷум қобилиятҳое мебошад, ки раванд ба онҳо ниёз дорад ва азбаски ин натиҷа воқеаҳои ғайриаудитро дар бар мегирад, мо ҳама санҷишҳои ғайриаудитиро мебинем ва дар ниҳоят қобилияти заруриро бо парчами аудит (охирин дар натиҷа) ба 1 муқаррар карда мешавад. он чизе, ки мо ба он таваҷҷӯҳ дорем, CAP_NET_BIND_SERVICE аст, он ҳамчун доимӣ дар коди сарчашмаи ядро ​​​​дар файли include/uapi/linux/ability.h бо идентификатори 10 муайян карда мешавад:

/* Allows binding to TCP/UDP sockets below 1024 */
/* Allows binding to ATM VCIs below 32 */
#define CAP_NET_BIND_SERVICE 10<source lang="go">

Имкониятҳо аксар вақт дар вақти корӣ барои контейнерҳо ба монанди runC ё Docker фаъол карда мешаванд, то ба онҳо дар ҳолати беимтиёз кор кунанд, аммо ба онҳо танҳо имкониятҳое иҷозат дода мешавад, ки барои иҷрои аксари барномаҳо лозиманд. Вақте ки барнома қобилиятҳои муайянро талаб мекунад, Docker метавонад онҳоро бо истифода аз --cap-add таъмин кунад:

docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummy

Ин фармон ба контейнер қобилияти CAP_NET_ADMIN медиҳад ва ба он имкон медиҳад, ки пайванди шабакаро барои илова кардани интерфейси dummy0 танзим кунад.

Бахши навбатӣ нишон медиҳад, ки чӣ тавр истифода бурдани хусусиятҳо ба монанди филтр, аммо бо истифода аз техникаи дигар, ки ба мо имкон медиҳад, ки филтрҳои шахсии худро ба таври барномавӣ амалӣ кунем.

Seccomp

Seccomp маънои Computing Secure аст ва як қабати амниятӣ дар ядрои Linux амалӣ карда мешавад, ки ба таҳиягарон имкон медиҳад, ки зангҳои муайяни системаро филтр кунанд. Гарчанде ки Seccomp аз ҷиҳати қобилиятҳо бо Linux муқоиса карда мешавад, қобилияти он барои идоракунии зангҳои системавӣ онро нисбат ба онҳо хеле чандиртар мекунад.

Хусусиятҳои Seccomp ва Linux аз ҳамдигар истисно нестанд ва аксар вақт якҷоя истифода мешаванд, то аз ҳарду равиш баҳра баранд. Масалан, шумо метавонед ба раванд қобилияти CAP_NET_ADMIN диҳед, аммо ба он иҷозат надиҳед, ки пайвастҳои розеткаро қабул кунад ва зангҳои системаро қабул ва қабул кунад4.

Усули филтркунии Seccomp ба филтрҳои BPF, ки дар реҷаи SECCOMP_MODE_FILTER кор мекунанд, асос ёфтааст ва филтркунии зангҳои система ҳамон тавре ки барои бастаҳо иҷро карда мешавад.

Филтрҳои Seccomp бо истифода аз prctl тавассути амалиёти PR_SET_SECCOMP бор карда мешаванд. Ин филтрҳо шакли барномаи BPF-ро мегиранд, ки барои ҳар як бастаи Seccomp, ки бо сохтори seccomp_data муаррифӣ мешавад, иҷро мешавад. Ин сохтор дорои меъмории истинод, ишора ба дастурҳои протсессори ҳангоми занги система ва ҳадди аксар шаш далели занги система, ки ҳамчун uint64 ифода шудааст, иборат аст.

Чунин аст сохтори seccomp_data аз рамзи сарчашмаи ядро ​​дар файли linux/seccomp.h:

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

Тавре ки шумо аз ин сохтор мебинед, мо метавонем аз рӯи занги система, далелҳои он ё омезиши ҳарду филтр кунем.

Пас аз гирифтани ҳар як бастаи Seccomp, филтр бояд коркардро анҷом диҳад, то қарори ниҳоӣ қабул кунад ва ба ядро ​​бигӯяд, ки дар оянда чӣ кор кунад. Қарори ниҳоӣ бо яке аз арзишҳои баргардонидан (рамзҳои ҳолати) ифода карда мешавад.

- SECCOMP_RET_KILL_PROCESS - тамоми равандро фавран пас аз филтр кардани занги система, ки аз ин сабаб иҷро намешавад, мекушад.

- SECCOMP_RET_KILL_THREAD - риштаи ҷорӣро фавран пас аз филтр кардани занги система, ки аз ин сабаб иҷро намешавад, қатъ мекунад.

— SECCOMP_RET_KILL — тахаллус барои SECCOMP_RET_KILL_THREAD, барои мутобиқат ба ақиб мондааст.

- SECCOMP_RET_TRAP - занги системавӣ манъ аст ва сигнали SIGSYS (Занги системаи бад) ба вазифае, ки онро даъват мекунад, фиристода мешавад.

- SECCOMP_RET_ERRNO - Занги система иҷро намешавад ва як қисми арзиши баргардонидани филтри SECCOMP_RET_DATA ба фазои корбар ҳамчун арзиши errno интиқол дода мешавад. Вобаста аз сабаби хато, арзишҳои гуногуни хато баргардонида мешаванд. Рӯйхати рақамҳои хато дар боби оянда оварда шудааст.

- SECCOMP_RET_TRACE - Барои огоҳ кардани пайгирии ptrace бо истифода аз - PTRACE_O_TRACESECCOMP барои боздоштани ҳангоми иҷро шудани занги система барои дидан ва назорати он раванд истифода мешавад. Агар паймоиш пайваст набошад, хато бармегардад, хато ба -ENOSYS муқаррар карда мешавад ва занги система иҷро намешавад.

- SECCOMP_RET_LOG - занги система ҳал ва сабт шудааст.

- SECCOMP_RET_ALLOW - занги системавӣ танҳо иҷозат дода мешавад.

ptrace як даъвати системавӣ барои татбиқи механизмҳои пайгирӣ дар раванде бо номи tracee бо қобилияти назорат ва назорати иҷрои раванд мебошад. Барномаи пайгирӣ метавонад ба иҷроиш муассир таъсир расонад ва регистрҳои хотираи паймоишро тағир диҳад. Дар контексти Seccomp, ptrace ҳангоми ба кор андохтани рамзи ҳолати SECCOMP_RET_TRACE истифода мешавад, аз ин рӯ тресер метавонад занги системаро аз иҷро ва амалӣ кардани мантиқи худ пешгирӣ кунад.

Хатогиҳои Seccomp

Баъзан ҳангоми кор бо Seccomp шумо ба хатогиҳои гуногун дучор мешавед, ки бо арзиши бозгашти навъи SECCOMP_RET_ERRNO муайян карда мешаванд. Барои гузориш додани хато, занги системаи seccomp ба ҷои 1 -0 бармегардад.

Хатогиҳои зерин имконпазиранд:

- EACCESS - Ба зангзананда иҷозат дода намешавад, ки занги системавӣ кунад. Ин одатан аз он сабаб рӯй медиҳад, ки он имтиёзҳои CAP_SYS_ADMIN надорад ё no_new_privs бо истифода аз prctl муқаррар карда нашудааст (дар ин бора баъдтар сӯҳбат хоҳем кард);

— EFAULT — аргументҳои гузаронидашуда (args дар сохтори seccomp_data) суроғаи дуруст надоранд;

— EINVAL — дар ин чо чор сабаб шуда метавонад:

-амали дархостшуда номаълум аст ё аз ҷониби ядро ​​​​дар конфигуратсияи ҷорӣ дастгирӣ намешавад;

-парчамҳои зикршуда барои амалиёти дархостшуда эътибор надоранд;

-амалиёт BPF_ABS-ро дар бар мегирад, аммо бо ҷуброни муайяншуда мушкилот вуҷуд доранд, ки метавонанд аз андозаи сохтори seccomp_data зиёд бошанд;

-шумораи дастурҳои ба филтр интиқолшуда аз ҳадди аксар зиёд бошад;

— ENOMEM — барои иҷрои барнома хотираи кофӣ нест;

- EOPNOTSUPP - амалиёт нишон дод, ки бо SECCOMP_GET_ACTION_AVAIL амал дастрас буд, аммо ядро ​​баргардонидани аргументҳоро дастгирӣ намекунад;

— ESRCH — ҳангоми ҳамоҳангсозии ҷараёни дигар мушкилот ба миён омад;

- ENOSYS - Ягон паймоиш ба амали SECCOMP_RET_TRACE замима карда нашудааст.

prctl як занги системаест, ки ба барномаи фазои корбар имкон медиҳад, ки ҷанбаҳои мушаххаси равандро идора кунад (муқаррар ва ба даст орад), аз қабили эндиании байт, номҳои ришта, ҳолати ҳисобкунии бехатар (Seccomp), имтиёзҳо, рӯйдодҳои Perf ва ғайра.

Seccomp метавонад ба шумо як технологияи қуттии қумӣ монанд бошад, аммо ин тавр нест. Seccomp як хидматест, ки ба корбарон имкон медиҳад, ки механизми қуттии қумро таҳия кунанд. Акнун биёед бубинем, ки чӣ гуна барномаҳои муштараки корбарон бо истифода аз филтр, ки мустақиман бо занги системаи Seccomp даъват карда мешаванд, сохта мешаванд.

Намунаи филтри BPF Seccomp

Дар ин ҷо мо нишон медиҳем, ки чӣ гуна ду амали қаблан муҳокимашударо якҷоя кардан мумкин аст, яъне:

— мо барномаи Seccomp BPF-ро менависем, ки он вобаста ба қарорҳои қабулшуда ҳамчун филтр бо рамзҳои бозгашти гуногун истифода мешавад;

— филтрро бо истифода аз prctl бор кунед.

Аввалан ба шумо сарлавҳаҳо аз китобхонаи стандартӣ ва ядрои Linux лозиманд:

#include <errno.h>
#include <linux/audit.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <unistd.h>

Пеш аз кӯшиши ин мисол, мо бояд боварӣ ҳосил кунем, ки ядро ​​бо CONFIG_SECCOMP ва CONFIG_SECCOMP_FILTER ба y муқаррар карда шудааст. Дар мошини корӣ шумо метавонед инро чунин тафтиш кунед:

cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP

Қисми боқимондаи код функсияи ду қисмати install_filter мебошад. Қисми аввал рӯйхати дастурҳои филтркунии BPF-ро дар бар мегирад:

static int install_filter(int nr, int arch, int error) {
  struct sock_filter filter[] = {
    BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, arch))),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3),
    BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, nr))),
    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
    BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)),
    BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
  };

Дастурҳо бо истифода аз макросҳои BPF_STMT ва BPF_JUMP, ки дар файли linux/filter.h муайян шудаанд, муқаррар карда мешаванд.
Биёед дастурҳоро аз назар гузаронем.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - система аз BPF_LD дар шакли калимаи BPF_W бор мекунад ва ҷамъ мешавад, маҷмӯаи маълумот дар ҷуброни собит BPF_ABS ҷойгир аст.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - бо истифода аз BPF_JEQ месанҷад, ки оё арзиши меъморӣ дар константаи аккумулятории BPF_K ба arch баробар аст. Агар ин тавр бошад, аз ҷуброни 0 ба дастури навбатӣ мегузарад, дар акси ҳол ба офсети 3 (дар ин ҳолат) ҷаҳиш мекунад, то хатогӣ диҳад, зеро арк мувофиқат намекунад.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Аз BPF_LD дар шакли калимаи BPF_W бор мекунад ва ҷамъ мешавад, ки рақами занги система дар ҷуброни собит BPF_ABS мавҷуд аст.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — рақами занги системаро бо арзиши тағирёбандаи nr муқоиса мекунад. Агар онҳо баробар бошанд, ба дастури навбатӣ мегузарад ва занги системаро ғайрифаъол мекунад, вагарна занги системаро бо SECCOMP_RET_ALLOW иҷозат медиҳад.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (хато & SECCOMP_RET_DATA)) - барномаро бо BPF_RET қатъ мекунад ва дар натиҷа хатои SECCOMP_RET_ERRNO бо рақами тағирёбандаи err ба вуҷуд меорад.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - барномаро бо BPF_RET қатъ мекунад ва имкон медиҳад занги система бо истифода аз SECCOMP_RET_ALLOW иҷро шавад.

SECCOMP CBPF аст
Шояд шумо дар ҳайрат бошед, ки чаро рӯйхати дастурҳо ба ҷои объекти тартибдодашудаи ELF ё барномаи JIT тартибдодашудаи C истифода мешаванд.

Ин ду сабаб дорад.

• Аввалан, Seccomp cBPF (BPF классикӣ)-ро истифода мебарад, на eBPF, яъне он чунин маъно дорад: он реестр надорад, балки танҳо аккумулятор барои нигоҳ доштани натиҷаи охирини ҳисоб, тавре ки дар мисол дида мешавад.

• Дуюм, Seccomp ишоракунакро ба як қатор дастурҳои BPF бевосита қабул мекунад, на чизи дигаре. Макросҳое, ки мо истифода кардем, ба таври оддӣ барои муайян кардани ин дастурҳо ба барномасоз кӯмак мекунанд.

Агар ба шумо барои фаҳмидани ин маҷлис кӯмаки бештар лозим бошад, псевдокоди псевдокоди якхеларо баррасӣ кунед:

if (arch != AUDIT_ARCH_X86_64) {
    return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
    return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;

Пас аз муайян кардани рамзи филтр дар сохтори socket_filter, шумо бояд sock_fprog-ро муайян кунед, ки дорои рамз ва дарозии ҳисобшудаи филтр мебошад. Ин сохтори додаҳо ҳамчун далел барои эълон кардани раванд барои баъдтар иҷрошаванда лозим аст:

struct sock_fprog prog = {
   .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
   .filter = filter,
};

Дар функсияи install_filter танҳо як кор боқӣ мондааст - худи барномаро бор кунед! Барои ин, мо prctl-ро истифода мебарем, ки PR_SET_SECCOMP-ро ҳамчун вариант барои ворид шудан ба ҳолати ҳисоббарории бехатар қабул мекунем. Сипас, мо ба режим мегӯем, ки филтрро бо истифода аз SECCOMP_MODE_FILTER, ки дар тағирёбандаи prog навъи sock_fprog мавҷуд аст, бор кунад:

  if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
    perror("prctl(PR_SET_SECCOMP)");
    return 1;
  }
  return 0;
}

Ниҳоят, мо метавонем функсияи install_filter-и худро истифода барем, аммо пеш аз он мо бояд prctl-ро барои иҷрои ҷорӣ PR_SET_NO_NEW_PRIVS таъин кунем ва ба ин васила аз вазъияте канорагирӣ кунем, ки равандҳои кӯдакон нисбат ба волидонашон имтиёзҳои бештар мегиранд. Бо ин, мо метавонем зангҳои зерини prctl-ро дар функсияи install_filter бидуни доштани ҳуқуқи реша анҷом диҳем.

Акнун мо метавонем функсияи install_filter -ро даъват кунем. Биёед ҳамаи зангҳои системаи навиштани марбут ба меъмории X86-64-ро маҳкам кунем ва танҳо иҷозат диҳем, ки ҳама кӯшишҳоро манъ кунад. Пас аз насб кардани филтр, мо бо истифода аз аргументи аввал иҷроишро идома медиҳем:

int main(int argc, char const *argv[]) {
  if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
   perror("prctl(NO_NEW_PRIVS)");
   return 1;
  }
   install_filter(__NR_write, AUDIT_ARCH_X86_64, EPERM);
  return system(argv[1]);
 }

Биёед оғоз кунем. Барои тартиб додани барномаи мо мо метавонем ё clang ё gcc -ро истифода барем, дар ҳар сурат он танҳо файли main.c -ро бидуни имконоти махсус тартиб медиҳад:

clang main.c -o filter-write

Тавре зикр гардид, мо ҳама вурудоти барномаро маҳкам кардем. Барои санҷидани ин ба шумо барномае лозим аст, ки чизе мебарорад - ls ҳамчун номзади хуб ба назар мерасад. Вай одатан чунин рафтор мекунад:

ls -la
total 36
drwxr-xr-x 2 fntlnz users 4096 Apr 28 21:09 .
drwxr-xr-x 4 fntlnz users 4096 Apr 26 13:01 ..
-rwxr-xr-x 1 fntlnz users 16800 Apr 28 21:09 filter-write
-rw-r--r-- 1 fntlnz users 19 Apr 28 21:09 .gitignore
-rw-r--r-- 1 fntlnz users 1282 Apr 28 21:08 main.c

Аҷоиб! Ин аст он чизе ки бо истифода аз барномаи печонидани мо чунин аст: Мо танҳо барномаеро, ки мехоҳем озмоиш кунем, ҳамчун далели аввал мегузарем:

./filter-write "ls -la"

Ҳангоми иҷро шудан, ин барнома натиҷаи комилан холӣ медиҳад. Бо вуҷуди ин, мо метавонем strace-ро истифода барем, то бубинем, ки чӣ рӯй дода истодааст:

strace -f ./filter-write "ls -la"

Натиҷаи кор хеле кӯтоҳ карда шудааст, аммо қисми мувофиқи он нишон медиҳад, ки сабтҳо бо хатои EPERM баста шудаанд - ҳамон чизе, ки мо танзим кардем. Ин маънои онро дорад, ки барнома чизе намебарорад, зеро он ба занги системаи навиштан дастрасӣ надорад:

[pid 25099] write(2, "ls: ", 4) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "write error", 11) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "n", 1) = -1 EPERM (Operation not permitted)

Акнун шумо мефаҳмед, ки чӣ тавр Seccomp BPF кор мекунад ва дар бораи он, ки шумо бо он чӣ кор карда метавонед, фикри хуб доред. Аммо оё шумо намехоҳед ҳамон чизеро бо eBPF ба ҷои cBPF ба даст оред, то қудрати пурраи онро истифода баред?

Ҳангоми фикр кардан дар бораи барномаҳои eBPF, аксари одамон фикр мекунанд, ки онҳо танҳо онҳоро менависанд ва онҳоро бо имтиёзҳои администратор бор мекунанд. Гарчанде ки ин изҳорот умуман дуруст аст, ядро ​​​​маҷмӯи механизмҳоро барои ҳифзи объектҳои eBPF дар сатҳҳои гуногун амалӣ мекунад. Ин механизмҳо домҳои BPF LSM номида мешаванд.

Домҳои BPF LSM

Барои таъмини мониторинги мустақили меъмории рӯйдодҳои система, LSM консепсияи домҳоро амалӣ мекунад. Занг аз ҷиҳати техникӣ ба занги система шабоҳат дорад, аммо аз система мустақил аст ва бо инфрасохтор ҳамгиро шудааст. LSM консепсияи наверо пешниҳод мекунад, ки дар он қабати абстраксия метавонад барои пешгирӣ кардани мушкилоте, ки ҳангоми кор бо зангҳои система дар меъмории гуногун дучор меоянд, кӯмак кунад.

Дар замони навиштан, ядро ​​дорои ҳафт қалмоқе мебошад, ки бо барномаҳои BPF алоқаманданд ва SELinux ягона LSM-и дарунсохт аст, ки онҳоро амалӣ мекунад.

Рамзи сарчашмаи домҳо дар дарахти ядро ​​дар файли include/linux/security.h ҷойгир аст:

extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
extern int security_bpf_prog(struct bpf_prog *prog);
extern int security_bpf_map_alloc(struct bpf_map *map);
extern void security_bpf_map_free(struct bpf_map *map);
extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
extern void security_bpf_prog_free(struct bpf_prog_aux *aux);

Ҳар яке аз онҳо дар марҳилаҳои гуногуни иҷро даъват карда мешаванд:

— security_bpf — санҷиши ибтидоии зангҳои системаи BPF-ро иҷро мекунад;

- security_bpf_map - месанҷад, вақте ки ядро ​​барои харита тавсифкунандаи файлро бармегардонад;

- security_bpf_prog - месанҷад, ки кай ядро ​​дескриптори файлро барои барномаи eBPF бармегардонад;

— security_bpf_map_alloc — тафтиш мекунад, ки майдони бехатарӣ дар дохили харитаҳои BPF оғоз шудааст ё не;

- security_bpf_map_free - тафтиш мекунад, ки оё майдони амният дар дохили харитаҳои BPF тоза карда шудааст;

— security_bpf_prog_alloc — тафтиш мекунад, ки майдони амният дар дохили барномаҳои BPF оғоз карда шудааст ё не;

- security_bpf_prog_free - тафтиш мекунад, ки оё майдони амният дар дохили барномаҳои BPF тоза карда шудааст.

Ҳоло, бо дидани ҳамаи ин, мо мефаҳмем: идеяи паси интерсепторҳои LSM BPF ин аст, ки онҳо метавонанд ҳар як объекти eBPF-ро муҳофизат кунанд ва кафолат диҳанд, ки танҳо онҳое, ки имтиёзҳои мувофиқ доранд, дар кортҳо ва барномаҳо амалиёт анҷом диҳанд.

Натиҷа

Амният чизе нест, ки шумо метавонед барои ҳама чизеро, ки муҳофизат кардан мехоҳед, ба таври якхела амалӣ кунед. Муҳим аст, ки системаҳоро дар сатҳҳои гуногун ва бо роҳҳои гуногун муҳофизат карда тавонед. Бовар кунед ё не, беҳтарин роҳи муҳофизати система ин ташкили сатҳҳои гуногуни муҳофизат аз мавқеъҳои гуногун мебошад, то коҳиш додани амнияти як сатҳ имкони дастрасӣ ба тамоми системаро надиҳад. Таҳиягарони аслӣ кори бузургеро анҷом доданд, ки ба мо як қатор қабатҳо ва нуқтаҳои тамосро пешкаш кунанд. Мо умедворем, ки мо ба шумо фаҳмиши хубе додем, ки чӣ гуна қабатҳо ва чӣ гуна истифода бурдани барномаҳои BPF барои кор бо онҳо.

Дар бораи муаллифон

Дэвид Калавера CTO дар Netlify мебошад. Вай дар дастгирии Docker кор мекард ва дар таҳияи абзорҳои Runc, Go ва BCC, инчунин дигар лоиҳаҳои кушодаасос саҳм гузоштааст. Бо кори худ дар лоиҳаҳои Docker ва таҳияи экосистемаи плагинҳои Docker маълум аст. Дэвид ба графикҳои шӯъла хеле дилчасп аст ва ҳамеша мекӯшад, ки иҷрои онро оптимизатсия кунад.

Лоренцо Фонтана дар гурӯҳи кушодаасос дар Sysdig кор мекунад, ки дар он асосан ба Falco, як лоиҳаи Cloud Native Computing Foundation, ки амнияти контейнерӣ ва ошкоркунии аномалияро тавассути модули ядро ​​​​ва eBPF таъмин мекунад, тамаркуз кардааст. Вай дар бораи системаҳои тақсимшуда, шабакаҳои муайяншудаи нармафзор, ядрои Linux ва таҳлили фаъолият дилчасп аст.

» Тафсилоти бештар дар бораи китобро метавонед дар ин ҷо пайдо кунед вебсайти ношир
» Мундариҷа
» Иқтибос

Барои Khabrozhiteley 25% тахфиф бо истифода аз купон - Linux

Ҳангоми пардохти версияи коғазии китоб, китоби электронӣ тавассути почтаи электронӣ фиристода мешавад.

Манбаъ: will.com

Илова Эзоҳ