Zdravo, stanovnici Khabro! BPF virtuelna mašina je jedna od najvažnijih komponenti Linux kernela. Njegova pravilna upotreba omogućit će sistemskim inženjerima da pronađu greške i riješe čak i najsloženije probleme. Naučit ćete kako pisati programe koji nadgledaju i modificiraju ponašanje kernela, kako sigurno implementirati kod za praćenje događaja u kernelu i još mnogo toga. David Calavera i Lorenzo Fontana pomoći će vam da otključate moć BPF-a. Proširite svoje znanje o optimizaciji performansi, umrežavanju, sigurnosti. - Koristite BPF za praćenje i izmjenu ponašanja Linux kernela. - Ubacite kod za bezbedno praćenje događaja kernela bez potrebe za ponovnom kompajliranjem kernela ili restartovanjem sistema. — Koristite zgodne primjere koda u C, Go ili Python. - Preuzmite kontrolu posjedovanjem životnog ciklusa BPF programa.
Sigurnost Linux kernela, njegove karakteristike i Seccomp
BPF pruža moćan način za proširenje kernela bez žrtvovanja stabilnosti, sigurnosti ili brzine. Iz tog razloga, programeri kernela su smatrali da bi bila dobra ideja iskoristiti njegovu svestranost za poboljšanje izolacije procesa u Seccompu implementacijom Seccomp filtera podržanih od BPF programa, također poznatih kao Seccomp BPF. U ovom poglavlju ćemo objasniti šta je Seccomp i kako se koristi. Zatim ćete naučiti kako pisati Seccomp filtere koristeći BPF programe. Nakon toga ćemo pogledati ugrađene BPF kuke koje su uključene u kernel za Linux sigurnosne module.
Linux sigurnosni moduli (LSM) su okvir koji pruža skup funkcija koje se mogu koristiti za implementaciju različitih sigurnosnih modela na standardiziran način. LSM se može koristiti direktno u izvornom stablu kernela, kao što su Apparmor, SELinux i Tomoyo.
Počnimo s raspravom o mogućnostima Linuxa.
Karakteristike
Suština mogućnosti Linuxa je da morate dati neprivilegiranom procesu dozvolu za obavljanje određenog zadatka, ali bez korištenja suid-a u tu svrhu, ili na drugi način učiniti proces privilegiranim, smanjujući mogućnost napada i dopuštajući procesu da izvršava određene zadatke. Na primjer, ako vaša aplikacija treba da otvori privilegirani port, recimo 80, umjesto da pokrenete proces kao root, možete joj jednostavno dati mogućnost CAP_NET_BIND_SERVICE.
Razmotrite Go program pod nazivom main.go:
package main
import (
"net/http"
"log"
)
func main() {
log.Fatalf("%v", http.ListenAndServe(":80", nil))
}Ovaj program opslužuje HTTP server na portu 80 (ovo je privilegovani port). Obično ga pokrećemo odmah nakon kompilacije:
$ go build -o capabilities main.go
$ ./capabilitiesMeđutim, budući da ne dodjeljujemo root privilegije, ovaj kod će baciti grešku prilikom povezivanja porta:
2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1capsh (menadžer ljuske) je alat koji pokreće ljusku sa određenim skupom mogućnosti.
U ovom slučaju, kao što je već spomenuto, umjesto davanja punih root prava, možete omogućiti privilegovano povezivanje porta pružanjem cap_net_bind_service mogućnosti zajedno sa svim ostalim što je već u programu. Da bismo to učinili, možemo priložiti naš program u velikim slovima:
# 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"Hajde da malo razumemo ovaj tim.
- capsh - koristite capsh kao ljusku.
- —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - s obzirom da moramo promijeniti korisnika (ne želimo da se pokrećemo kao root), specificiraćemo cap_net_bind_service i mogućnost da stvarno promijenimo ID korisnika iz root nikome, odnosno cap_setuid i cap_setgid.
- —keep=1 — želimo da zadržimo instalirane mogućnosti kada prelazimo sa root naloga.
- —user=“nobody” — krajnji korisnik koji pokreće program će biti niko.
- —addamb=cap_net_bind_service — postavite brisanje srodnih mogućnosti nakon prebacivanja iz root moda.
- - -c "./capabilities" - samo pokrenite program.
Povezane mogućnosti su posebna vrsta sposobnosti koje nasljeđuju podređeni programi kada ih trenutni program izvršava pomoću execve(). Samo sposobnosti koje je dozvoljeno da budu povezane, ili drugim riječima, kao sposobnosti okruženja, mogu se naslijediti.
Vjerovatno se pitate šta znači +eip nakon što navedete mogućnost u opciji --caps. Ove zastavice se koriste za određivanje da li je sposobnost:
-mora biti aktiviran (p);
-dostupan za upotrebu (e);
-mogu naslijediti podređeni procesi (i).
Pošto želimo da koristimo cap_net_bind_service, to moramo uraditi sa e zastavicom. Zatim ćemo pokrenuti shell u komandi. Ovo će pokrenuti binarne mogućnosti i moramo ga označiti sa zastavicom i. Konačno, želimo da se funkcija omogući (to smo uradili bez promjene UID-a) sa p. Izgleda kao cap_net_bind_service+eip.
Rezultat možete provjeriti koristeći ss. Skratimo malo izlaz da stane na stranicu, ali će pokazati povezani port i korisnički ID koji nije 0, u ovom slučaju 65:
# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0U ovom primjeru koristili smo capsh, ali možete napisati ljusku koristeći libcap. Za više informacija pogledajte man 3 libcap.
Prilikom pisanja programa, programer često ne zna unaprijed sve karakteristike koje su potrebne programu u vrijeme rada; Štaviše, ove karakteristike se mogu promijeniti u novim verzijama.
Da bismo bolje razumjeli mogućnosti našeg programa, možemo uzeti BCC sposoban alat, koji postavlja kprobe za cap_capable funkciju kernela:
/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 1Istu stvar možemo postići korištenjem bpftracea s kprobe s jednom linijom u funkciji jezgre cap_capable:
bpftrace -e
'kprobe:cap_capable {
time("%H:%M:%S ");
printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
}'
| grep -i capabilitiesOvo će dati nešto poput sljedećeg ako su mogućnosti našeg programa omogućene nakon 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 1Peti stupac su mogućnosti koje su potrebne procesu, a pošto ovaj izlaz uključuje nerevizijske događaje, vidimo sve nerevizijske provjere i na kraju potrebnu sposobnost sa zastavicom revizije (posljednja u izlazu) postavljenom na 1. Sposobnost jedan koji nas zanima je CAP_NET_BIND_SERVICE, definiran je kao konstanta u izvornom kodu kernela u datoteci include/uapi/linux/ability.h sa identifikatorom 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">Mogućnosti su često omogućene u vrijeme izvođenja za kontejnere kao što su runC ili Docker kako bi im se omogućilo pokretanje u neprivilegiranom načinu rada, ali su im dozvoljene samo mogućnosti potrebne za pokretanje većine aplikacija. Kada aplikacija zahtijeva određene mogućnosti, Docker ih može pružiti pomoću --cap-add:
docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummyOva komanda će kontejneru dati mogućnost CAP_NET_ADMIN, omogućavajući mu da konfiguriše mrežnu vezu za dodavanje dummy0 interfejsa.
Sljedeći odjeljak pokazuje kako koristiti funkcije kao što je filtriranje, ali koristeći drugu tehniku koja nam omogućava da programski implementiramo vlastite filtere.
Seccomp
Seccomp je skraćenica za Secure Computing i sigurnosni je sloj implementiran u Linux kernel koji omogućava programerima da filtriraju određene sistemske pozive. Iako je Seccomp po mogućnostima uporediv sa Linuxom, njegova sposobnost upravljanja određenim sistemskim pozivima ga čini mnogo fleksibilnijim u odnosu na njih.
Seccomp i Linux karakteristike se međusobno ne isključuju i često se koriste zajedno kako bi imali koristi od oba pristupa. Na primjer, možda ćete htjeti dati procesu CAP_NET_ADMIN sposobnost, ali mu ne dozvoliti da prihvati veze utičnice, blokirajući prihvaćanje i prihvaćanje4 sistemskih poziva.
Seccomp metoda filtriranja je bazirana na BPF filterima koji rade u načinu rada SECCOMP_MODE_FILTER, a filtriranje sistemskih poziva se izvodi na isti način kao i za pakete.
Seccomp filteri se učitavaju korištenjem prctl kroz operaciju PR_SET_SECCOMP. Ovi filteri imaju oblik BPF programa koji se izvršava za svaki Seccomp paket predstavljen strukturom seccomp_data. Ova struktura sadrži referentnu arhitekturu, pokazivač na instrukcije procesora u vrijeme sistemskog poziva i najviše šest argumenata sistemskog poziva, izraženih kao uint64.
Ovako izgleda struktura seccomp_data iz izvornog koda kernela u datoteci linux/seccomp.h:
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};Kao što možete vidjeti iz ove strukture, možemo filtrirati prema sistemskom pozivu, njegovim argumentima ili kombinaciji oboje.
Nakon što primi svaki Seccomp paket, filter mora izvršiti obradu kako bi donio konačnu odluku i rekao kernelu što dalje. Konačna odluka se izražava jednom od vraćenih vrijednosti (kodova statusa).
- SECCOMP_RET_KILL_PROCESS - ubija cijeli proces odmah nakon filtriranja sistemskog poziva koji se zbog toga ne izvršava.
- SECCOMP_RET_KILL_THREAD - prekida trenutnu nit odmah nakon filtriranja sistemskog poziva koji se zbog toga ne izvršava.
— SECCOMP_RET_KILL — alias za SECCOMP_RET_KILL_THREAD, lijevo za kompatibilnost unatrag.
- SECCOMP_RET_TRAP - sistemski poziv je zabranjen, a signal SIGSYS (Loš sistemski poziv) se šalje zadatku koji ga poziva.
- SECCOMP_RET_ERRNO - Sistemski poziv se ne izvršava, a dio povratne vrijednosti filtera SECCOMP_RET_DATA se prosljeđuje korisničkom prostoru kao errno vrijednost. Ovisno o uzroku greške, vraćaju se različite errno vrijednosti. Lista brojeva grešaka nalazi se u sljedećem odjeljku.
- SECCOMP_RET_TRACE - Koristi se za obavještavanje ptrace tracera koristeći - PTRACE_O_TRACESECCOMP za presretanje kada se sistemski poziv izvrši da vidi i kontrolira taj proces. Ako tragač nije povezan, vraća se greška, errno se postavlja na -ENOSYS i sistemski poziv se ne izvršava.
- SECCOMP_RET_LOG - sistemski poziv je riješen i evidentiran.
- SECCOMP_RET_ALLOW - sistemski poziv je jednostavno dozvoljen.
ptrace je sistemski poziv za implementaciju mehanizama praćenja u procesu koji se zove tracee, sa mogućnošću praćenja i kontrole izvršenja procesa. Program praćenja može djelotvorno utjecati na izvršenje i modificirati memorijske registre traga. U Seccomp kontekstu, ptrace se koristi kada ga aktivira statusni kod SECCOMP_RET_TRACE, tako da tracer može spriječiti izvršavanje sistemskog poziva i implementirati vlastitu logiku.
Seccomp greške
S vremena na vrijeme, dok radite sa Seccompom, naići ćete na razne greške, koje se identificiraju povratnom vrijednošću tipa SECCOMP_RET_ERRNO. Za prijavu greške, sistemski poziv seccomp će vratiti -1 umjesto 0.
Moguće su sljedeće greške:
- EACCESS - Pozivaocu nije dozvoljeno da uputi sistemski poziv. Ovo se obično dešava zato što nema privilegije CAP_SYS_ADMIN ili no_new_privs nije postavljen pomoću prctl-a (o tome ćemo kasnije);
— EFAULT — proslijeđeni argumenti (argovi u strukturi seccomp_data) nemaju valjanu adresu;
— EINVAL — ovdje mogu biti četiri razloga:
-tražena operacija je nepoznata ili je kernel ne podržava u trenutnoj konfiguraciji;
-navedene zastavice nisu važeće za traženu operaciju;
-operacija uključuje BPF_ABS, ali postoje problemi sa specificiranim pomakom, koji može premašiti veličinu strukture seccomp_data;
-broj instrukcija prosleđenih filteru premašuje maksimum;
— ENOMEM — nema dovoljno memorije za izvršavanje programa;
- EOPNOTSUPP - operacija je pokazala da je sa SECCOMP_GET_ACTION_AVAIL akcija bila dostupna, ali kernel ne podržava povratak u argumentima;
— ESRCH — došlo je do problema prilikom sinhronizacije drugog toka;
- ENOSYS - Za akciju SECCOMP_RET_TRACE ne postoji nikakav trag.
prctl je sistemski poziv koji omogućava programu u korisničkom prostoru da manipuliše (postavi i dobije) specifične aspekte procesa, kao što su endianness bajtova, imena niti, način bezbednog izračunavanja (Secomp), privilegije, Perf događaji, itd.
Seccomp vam se može činiti kao pješčana tehnologija, ali nije. Seccomp je uslužni program koji korisnicima omogućava da razviju sandbox mehanizam. Pogledajmo sada kako se kreiraju programi za interakciju korisnika pomoću filtera koji se direktno poziva Seccomp sistemskim pozivom.
Primjer BPF Seccomp filtera
Ovdje ćemo pokazati kako kombinirati dvije radnje o kojima smo ranije govorili, naime:
— napisaćemo Seccomp BPF program, koji će se koristiti kao filter sa različitim povratnim kodovima u zavisnosti od donetih odluka;
— učitajte filter koristeći prctl.
Prvo su vam potrebna zaglavlja iz standardne biblioteke i Linux kernela:
#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>Prije pokušaja ovog primjera, moramo osigurati da je kernel kompajliran sa CONFIG_SECCOMP i CONFIG_SECCOMP_FILTER postavljenim na y. Na radnoj mašini ovo možete provjeriti ovako:
cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP
Ostatak koda je dvodijelna funkcija install_filter. Prvi dio sadrži našu listu uputa za BPF filtriranje:
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),
}; Instrukcije se postavljaju korištenjem makronaredbi BPF_STMT i BPF_JUMP definiranih u datoteci linux/filter.h.
Idemo kroz uputstva.
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - sistem se učitava i akumulira iz BPF_LD u obliku riječi BPF_W, paketni podaci se nalaze na fiksnom pomaku BPF_ABS.
- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - provjerava pomoću BPF_JEQ da li je vrijednost arhitekture u konstanti akumulatora BPF_K jednaka arch. Ako je tako, skače na pomaku 0 na sljedeću instrukciju, u suprotnom skače na pomak 3 (u ovom slučaju) da bi doveo do greške jer se arch ne podudara.
- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Učitava i akumulira iz BPF_LD u obliku riječi BPF_W, što je broj sistemskog poziva sadržan u fiksnom pomaku BPF_ABS.
— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — upoređuje broj sistemskog poziva sa vrijednošću varijable nr. Ako su jednaki, prelazi na sljedeću instrukciju i onemogućuje sistemski poziv, u suprotnom dozvoljava sistemski poziv sa SECCOMP_RET_ALLOW.
- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (greška & SECCOMP_RET_DATA)) - završava program sa BPF_RET i kao rezultat proizvodi grešku SECCOMP_RET_ERRNO sa brojem iz varijable greške.
- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - završava program sa BPF_RET i dozvoljava da se sistemski poziv izvrši pomoću SECCOMP_RET_ALLOW.
SECCOMP JE CBPF
Možda se pitate zašto se lista instrukcija koristi umjesto prevedenog ELF objekta ili JIT kompajliranog C programa.Dva su razloga za to.
• Prvo, Seccomp koristi cBPF (klasični BPF), a ne eBPF, što znači: nema registre, već samo akumulator za pohranjivanje posljednjeg rezultata izračuna, kao što se može vidjeti u primjeru.
• Drugo, Seccomp direktno prihvata pokazivač na niz BPF instrukcija i ništa drugo. Makroi koje smo koristili jednostavno pomažu u specificiranju ovih instrukcija na način koji je prilagođen programerima.
Ako vam je potrebna dodatna pomoć u razumijevanju ovog sklopa, razmotrite pseudokod koji radi istu stvar:
if (arch != AUDIT_ARCH_X86_64) {
return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;Nakon definiranja koda filtera u strukturi socket_filter, trebate definirati sock_fprog koji sadrži kod i izračunatu dužinu filtera. Ova struktura podataka je potrebna kao argument za deklarisanje procesa za kasnije pokretanje:
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};U funkciji install_filter preostaje samo jedna stvar - učitati sam program! Da bismo to uradili, koristimo prctl, uzimajući PR_SET_SECCOMP kao opciju za ulazak u režim bezbednog računarstva. Zatim kažemo modu da učita filter koristeći SECCOMP_MODE_FILTER, koji je sadržan u prog varijabli tipa sock_fprog:
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
perror("prctl(PR_SET_SECCOMP)");
return 1;
}
return 0;
}Konačno, možemo koristiti našu install_filter funkciju, ali prije toga moramo koristiti prctl da postavimo PR_SET_NO_NEW_PRIVS za trenutno izvršenje i na taj način izbjegnemo situaciju u kojoj podređeni procesi dobiju više privilegija od svojih roditelja. Sa ovim možemo izvršiti sljedeće prctl pozive u funkciji install_filter bez root prava.
Sada možemo pozvati funkciju install_filter. Hajde da blokiramo sve sistemske pozive za pisanje koji se odnose na arhitekturu X86-64 i jednostavno damo dozvolu koja blokira sve pokušaje. Nakon instaliranja filtera, nastavljamo s izvršavanjem koristeći prvi argument:
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]);
}Hajde da počnemo. Za kompajliranje našeg programa možemo koristiti ili clang ili gcc, u svakom slučaju to je samo kompajliranje main.c datoteke bez posebnih opcija:
clang main.c -o filter-writeKao što je navedeno, blokirali smo sve unose u programu. Da biste ovo testirali, potreban vam je program koji daje nešto - ls izgleda kao dobar kandidat. Ovako se ona obično ponaša:
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
Divno! Evo kako izgleda korištenje našeg programa omotača: Jednostavno prosljeđujemo program koji želimo testirati kao prvi argument:
./filter-write "ls -la"Kada se izvrši, ovaj program proizvodi potpuno prazan izlaz. Međutim, možemo koristiti strace da vidimo šta se dešava:
strace -f ./filter-write "ls -la"Rezultat rada je znatno skraćen, ali pripadajući dio pokazuje da su zapisi blokirani sa EPERM greškom - istom onom koju smo konfigurirali. To znači da program ne ispisuje ništa jer ne može pristupiti pozivu sistema za pisanje:
[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)Sada razumijete kako funkcionira Seccomp BPF i imate dobru ideju o tome šta možete učiniti s njim. Ali zar ne biste željeli postići istu stvar sa eBPF-om umjesto cBPF-om kako biste iskoristili njegovu punu snagu?
Kada razmišljaju o eBPF programima, većina ljudi misli da ih jednostavno pišu i učitavaju s administratorskim privilegijama. Iako je ova izjava generalno tačna, kernel implementira skup mehanizama za zaštitu eBPF objekata na različitim nivoima. Ovi mehanizmi se nazivaju BPF LSM zamke.
BPF LSM zamke
Da bi se omogućilo praćenje sistemskih događaja nezavisno od arhitekture, LSM implementira koncept zamki. Prekid poziva je tehnički sličan sistemskom pozivu, ali je nezavisan od sistema i integrisan sa infrastrukturom. LSM pruža novi koncept u kojem sloj apstrakcije može pomoći da se izbjegnu problemi koji se javljaju kada se radi sa sistemskim pozivima na različitim arhitekturama.
U vrijeme pisanja, kernel ima sedam zakačiva povezanih s BPF programima, a SELinux je jedini ugrađeni LSM koji ih implementira.
Izvorni kod za zamke se nalazi u stablu kernela u datoteci 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);Svaki od njih će biti pozvan u različitim fazama izvršenja:
— security_bpf — vrši početnu provjeru izvršenih BPF sistemskih poziva;
- security_bpf_map - provjerava kada kernel vraća deskriptor datoteke za mapu;
- security_bpf_prog - provjerava kada kernel vraća deskriptor datoteke za eBPF program;
— security_bpf_map_alloc — provjerava da li je sigurnosno polje unutar BPF mapa inicijalizirano;
- security_bpf_map_free - provjerava da li je sigurnosno polje očišćeno unutar BPF mapa;
— security_bpf_prog_alloc — provjerava da li je sigurnosno polje inicijalizirano unutar BPF programa;
- security_bpf_prog_free - provjerava da li je sigurnosno polje očišćeno unutar BPF programa.
Sada, kada vidimo sve ovo, razumijemo: ideja iza LSM BPF presretača je da oni mogu pružiti zaštitu svakom eBPF objektu, osiguravajući da samo oni sa odgovarajućim privilegijama mogu obavljati operacije na karticama i programima.
Rezime
Sigurnost nije nešto što možete implementirati na jedinstven način za sve što želite zaštititi. Važno je biti u stanju zaštititi sisteme na različitim nivoima i na različite načine. Vjerovali ili ne, najbolji način da se osigura sistem je organiziranje različitih nivoa zaštite sa različitih pozicija, tako da smanjenje sigurnosti jednog nivoa ne omogući pristup cijelom sistemu. Glavni programeri su uradili odličan posao dajući nam skup različitih slojeva i dodirnih tačaka. Nadamo se da smo vam dali dobro razumevanje šta su slojevi i kako da koristite BPF programe za rad sa njima.
O autorima
David Calavera je CTO u Netlifyju. Radio je u podršci za Docker i doprinio razvoju Runc, Go i BCC alata, kao i drugih projekata otvorenog koda. Poznat po svom radu na Docker projektima i razvoju ekosistema dodataka Docker. David je veoma strastven za grafove plamena i uvijek želi optimizirati performanse.
Lorenzo Fontana radi u timu otvorenog koda u Sysdigu, gdje je prvenstveno fokusiran na Falco, projekat Cloud Native Computing Foundation koji obezbjeđuje sigurnost izvođenja kontejnera i otkrivanje anomalija kroz modul kernela i eBPF. On je strastven za distribuirane sisteme, softverski definisano umrežavanje, Linux kernel i analizu performansi.
» Za više informacija o knjizi, posjetite
»
»
Za Khabrozhiteli 25% popusta na kupon - Linux
Po uplati papirne verzije knjige, e-knjiga se šalje na e-mail.
izvor: www.habr.com
