Knjiga "BPF za spremljanje Linuxa"

Knjiga "BPF za spremljanje Linuxa"Pozdravljeni, prebivalci Khabra! Virtualni stroj BPF je ena najpomembnejših komponent jedra Linuxa. Njegova pravilna uporaba bo sistemskim inženirjem omogočila iskanje napak in reševanje še tako zapletenih težav. Naučili se boste, kako napisati programe, ki spremljajo in spreminjajo obnašanje jedra, kako varno implementirati kodo za spremljanje dogodkov v jedru in še veliko več. David Calavera in Lorenzo Fontana vam bosta pomagala odkleniti moč BPF. Razširite svoje znanje o optimizaciji delovanja, povezovanju v omrežja, varnosti. - Uporabite BPF za spremljanje in spreminjanje obnašanja jedra Linuxa. - Vbrizgajte kodo za varno spremljanje dogodkov v jedru, ne da bi morali ponovno prevesti jedro ali ponovno zagnati sistem. — Uporabite priročne primere kod v C, Go ali Python. - Prevzemite nadzor z lastništvom življenjskega cikla programa BPF.

Varnost jedra Linuxa, njegove funkcije in Seccomp

BPF zagotavlja močan način za razširitev jedra brez žrtvovanja stabilnosti, varnosti ali hitrosti. Iz tega razloga so razvijalci jedra menili, da bi bilo dobro uporabiti njegovo vsestranskost za izboljšanje izolacije procesov v Seccompu z implementacijo filtrov Seccomp, ki jih podpirajo programi BPF, znani tudi kot Seccomp BPF. V tem poglavju bomo razložili, kaj je Seccomp in kako se uporablja. Nato se boste naučili pisati filtre Seccomp s programi BPF. Nato si bomo ogledali vgrajene kljuke BPF, ki so vključene v jedro za varnostne module Linux.

Varnostni moduli Linuxa (LSM) so ogrodje, ki zagotavlja nabor funkcij, ki se lahko uporabljajo za implementacijo različnih varnostnih modelov na standardiziran način. LSM je mogoče uporabiti neposredno v izvornem drevesu jedra, kot so Apparmor, SELinux in Tomoyo.

Začnimo z razpravo o zmogljivostih Linuxa.

možnosti

Bistvo zmožnosti Linuxa je, da morate neprivilegiranemu procesu podeliti dovoljenje za izvedbo določene naloge, vendar brez uporabe suid za ta namen, ali kako drugače narediti proces privilegiran, kar zmanjša možnost napada in omogoči procesu, da izvede določene naloge. Na primer, če mora vaša aplikacija odpreti privilegirana vrata, recimo 80, namesto da bi zagnali proces kot root, ji lahko preprosto dodelite zmogljivost CAP_NET_BIND_SERVICE.

Razmislite o programu Go z imenom main.go:

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

Ta program služi strežniku HTTP na vratih 80 (to so privilegirana vrata). Običajno ga zaženemo takoj po kompilaciji:

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

Ker pa ne dodeljujemo korenskih pravic, bo ta koda vrgla napako pri povezovanju vrat:

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

capsh (shell manager) je orodje, ki poganja lupino z določenim naborom zmogljivosti.

V tem primeru, kot že omenjeno, lahko namesto podelitve polnih korenskih pravic omogočite privilegirano povezovanje vrat tako, da zagotovite zmogljivost cap_net_bind_service skupaj z vsem ostalim, kar je že v programu. Če želite to narediti, lahko naš program priložimo v 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"

Dajmo malo razumeti to ekipo.

  • capsh - uporabite capsh kot lupino.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - ker moramo spremeniti uporabnika (ne želimo izvajati kot root), bomo določili cap_net_bind_service in možnost dejanske spremembe ID-ja uporabnika iz root nikomur, in sicer cap_setuid in cap_setgid.
  • —keep=1 — ob preklopu s korenskega računa želimo ohraniti nameščene zmogljivosti.
  • —user=“nobody” — končni uporabnik, ki izvaja program, bo nihče.
  • —addamb=cap_net_bind_service — nastavite brisanje povezanih zmožnosti po preklopu iz korenskega načina.
  • - -c "./capabilities" - samo zaženite program.

Povezane zmožnosti so posebna vrsta zmožnosti, ki jih podedujejo podrejeni programi, ko jih trenutni program izvaja z uporabo execve(). Podedujejo se lahko samo zmožnosti, ki jih je dovoljeno povezovati, ali z drugimi besedami, kot zmožnosti okolja.

Verjetno se sprašujete, kaj pomeni +eip po določitvi zmožnosti v možnosti --caps. Te zastavice se uporabljajo za ugotavljanje, ali je zmogljivost:

-mora biti aktiviran (p);

- na voljo za uporabo (e);

- lahko podedujejo podrejeni procesi (i).

Ker želimo uporabiti storitev cap_net_bind_service, moramo to narediti z zastavico e. Nato bomo lupino zagnali v ukazu. To bo zagnalo zmogljivosti binarno in to moramo označiti z zastavico i. Nazadnje želimo, da je funkcija omogočena (to smo naredili, ne da bi spremenili UID) s p. Videti je kot cap_net_bind_service+eip.

Rezultat lahko preverite s ss. Nekoliko skrajšajmo izpis, da bo ustrezal strani, vendar bo prikazal povezana vrata in ID uporabnika, ki ni 0, v tem primeru 65:

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

V tem primeru smo uporabili capsh, lupino pa lahko napišete z libcap. Za več informacij glejte man 3 libcap.

Pri pisanju programov razvijalec pogosto ne pozna vnaprej vseh funkcij, ki jih program potrebuje med izvajanjem; Poleg tega se te funkcije lahko spremenijo v novih različicah.

Za boljše razumevanje zmožnosti našega programa lahko uporabimo orodje, ki podpira BCC, ki nastavi kprobe za funkcijo jedra 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

Enako lahko dosežemo z uporabo bpftrace z enovrstično kprobe v funkciji jedra 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

Če so zmožnosti našega programa omogočene po kprobe, bo to izpisalo nekaj takega:

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

Peti stolpec so zmožnosti, ki jih proces potrebuje, in ker ta izhod vključuje nerevizijske dogodke, vidimo vsa nerevizijska preverjanja in končno zahtevano zmogljivost z revizijsko zastavico (zadnja v izhodu), nastavljeno na 1. Zmogljivost. ena, ki nas zanima, je CAP_NET_BIND_SERVICE, definirana je kot konstanta v izvorni kodi jedra v datoteki include/uapi/linux/ability.h z identifikatorjem 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">

Zmogljivosti so pogosto omogočene med izvajanjem za vsebnike, kot sta runC ali Docker, da se lahko izvajajo v neprivilegiranem načinu, vendar so jim dovoljene le zmožnosti, potrebne za izvajanje večine aplikacij. Ko aplikacija zahteva določene zmogljivosti, jih lahko Docker zagotovi z --cap-add:

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

Ta ukaz bo vsebniku dal zmogljivost CAP_NET_ADMIN, kar mu bo omogočilo konfiguracijo omrežne povezave za dodajanje vmesnika dummy0.

Naslednji razdelek prikazuje, kako uporabljati funkcije, kot je filtriranje, vendar z uporabo drugačne tehnike, ki nam omogoča programsko implementacijo lastnih filtrov.

Seccomp

Seccomp pomeni varno računalništvo in je varnostna plast, implementirana v jedru Linuxa, ki razvijalcem omogoča filtriranje določenih sistemskih klicev. Čeprav je Seccomp po zmogljivostih primerljiv z Linuxom, je zaradi njegove zmožnosti upravljanja določenih sistemskih klicev veliko bolj prilagodljiv v primerjavi z njimi.

Funkcije Seccomp in Linux se med seboj ne izključujejo in se pogosto uporabljajo skupaj, da izkoristita oba pristopa. Na primer, morda želite dati procesu zmogljivost CAP_NET_ADMIN, vendar mu ne dovoliti sprejemanja povezav vtičnic, s čimer blokirate sistemske klice accept in accept4.

Metoda filtriranja Seccomp temelji na filtrih BPF, ki delujejo v načinu SECCOMP_MODE_FILTER, filtriranje sistemskih klicev pa se izvaja na enak način kot pri paketih.

Filtri Seccomp se naložijo z uporabo prctl prek operacije PR_SET_SECCOMP. Ti filtri so v obliki programa BPF, ki se izvede za vsak paket Seccomp, ki ga predstavlja struktura seccomp_data. Ta struktura vsebuje referenčno arhitekturo, kazalec na navodila procesorja v času sistemskega klica in največ šest argumentov sistemskega klica, izraženih kot uint64.

Tako je videti struktura seccomp_data iz izvorne kode jedra v datoteki linux/seccomp.h:

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

Kot lahko vidite iz te strukture, lahko filtriramo po sistemskem klicu, njegovih argumentih ali kombinaciji obojega.

Po prejemu vsakega paketa Seccomp mora filter izvesti obdelavo, da sprejme končno odločitev in pove jedru, kaj naj naredi naprej. Končna odločitev je izražena z eno od vrnjenih vrednosti (statusne kode).

- SECCOMP_RET_KILL_PROCESS - ubije celoten proces takoj po filtriranju sistemskega klica, ki se zaradi tega ne izvede.

- SECCOMP_RET_KILL_THREAD - prekine trenutno nit takoj po filtriranju sistemskega klica, ki se zaradi tega ne izvede.

— SECCOMP_RET_KILL — vzdevek za SECCOMP_RET_KILL_THREAD, levo zaradi združljivosti za nazaj.

- SECCOMP_RET_TRAP - sistemski klic je prepovedan, nalogi, ki ga kliče, pa se pošlje signal SIGSYS (Bad System Call).

- SECCOMP_RET_ERRNO - sistemski klic se ne izvede in del povratne vrednosti filtra SECCOMP_RET_DATA je posredovan v uporabniški prostor kot vrednost errno. Odvisno od vzroka napake se vrnejo različne vrednosti errno. Seznam številk napak je naveden v naslednjem razdelku.

- SECCOMP_RET_TRACE - Uporablja se za obveščanje sledilnika ptrace z uporabo - PTRACE_O_TRACESECCOMP za prestrezanje, ko se izvede sistemski klic za ogled in nadzor tega procesa. Če sledilnik ni povezan, se vrne napaka, errno je nastavljen na -ENOSYS in sistemski klic se ne izvede.

- SECCOMP_RET_LOG - sistemski klic je razrešen in zabeležen.

- SECCOMP_RET_ALLOW - sistemski klic je preprosto dovoljen.

ptrace je sistemski klic za implementacijo mehanizmov sledenja v proces, imenovan tracee, z možnostjo spremljanja in nadzora izvajanja procesa. Program za sledenje lahko učinkovito vpliva na izvajanje in spreminja pomnilniške registre tracee. V kontekstu Seccomp se ptrace uporablja, ko ga sproži statusna koda SECCOMP_RET_TRACE, tako da lahko sledilnik prepreči izvedbo sistemskega klica in implementira svojo logiko.

Napake Seccomp

Med delom s Seccompom boste od časa do časa naleteli na različne napake, ki jih prepozna vrnjena vrednost tipa SECCOMP_RET_ERRNO. Za poročanje o napaki bo sistemski klic seccomp vrnil -1 namesto 0.

Možne so naslednje napake:

- EACCESS - Klicatelj ne sme opraviti sistemskega klica. To se običajno zgodi, ker nima privilegijev CAP_SYS_ADMIN ali no_new_privs ni nastavljen z uporabo prctl (o tem bomo govorili kasneje);

— EFAULT — posredovani argumenti (argi v strukturi seccomp_data) nimajo veljavnega naslova;

— EINVAL — tukaj so lahko štirje razlogi:

- zahtevana operacija ni znana ali je jedro v trenutni konfiguraciji ne podpira;

- navedene zastavice niso veljavne za zahtevano operacijo;

-operacija vključuje BPF_ABS, vendar obstajajo težave s podanim odmikom, ki lahko presega velikost strukture seccomp_data;

- število ukazov, posredovanih filtru, presega največje;

— ENOMEM — ni dovolj pomnilnika za izvajanje programa;

- EOPNOTSUPP - operacija je pokazala, da je s SECCOMP_GET_ACTION_AVAIL dejanje na voljo, vendar jedro ne podpira vrnitev v argumentih;

— ESRCH — prišlo je do težave pri sinhronizaciji drugega toka;

- ENOSYS - Dejanju SECCOMP_RET_TRACE ni priložen sledilnik.

prctl je sistemski klic, ki omogoča programu v uporabniškem prostoru, da manipulira (nastavi in ​​pridobi) določene vidike procesa, kot so razporeditev bajtov, imena niti, način varnega računanja (Seccomp), privilegiji, dogodki Perf itd.

Seccomp se vam morda zdi kot tehnologija peskovnika, vendar ni. Seccomp je pripomoček, ki uporabnikom omogoča razvoj mehanizma peskovnika. Zdaj pa poglejmo, kako so programi za interakcijo z uporabniki ustvarjeni z uporabo filtra, ki ga kliče neposredno sistemski klic Seccomp.

Primer filtra Seccomp BPF

Tukaj bomo pokazali, kako združiti dva prej obravnavana dejanja, in sicer:

— napisali bomo program Seccomp BPF, ki bo uporabljen kot filter z različnimi povratnimi kodami glede na sprejete odločitve;

— naložite filter z uporabo prctl.

Najprej potrebujete glave iz standardne knjižnice in jedra Linuxa:

#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>

Pred poskusom tega primera moramo zagotoviti, da je jedro prevedeno z CONFIG_SECCOMP in CONFIG_SECCOMP_FILTER nastavljeno na y. Na delujočem stroju lahko to preverite takole:

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

Preostanek kode je dvodelna funkcija install_filter. Prvi del vsebuje naš seznam navodil za filtriranje 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),
  };

Navodila so nastavljena z uporabo makrov BPF_STMT in BPF_JUMP, definiranih v datoteki linux/filter.h.
Pojdimo skozi navodila.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - sistem nalaga in kopiči iz BPF_LD v obliki besede BPF_W, paketni podatki se nahajajo na fiksnem odmiku BPF_ABS.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - preveri z uporabo BPF_JEQ, ali je arhitekturna vrednost v akumulatorski konstanti BPF_K enaka arch. Če je tako, skoči pri odmiku 0 na naslednje navodilo, sicer skoči pri odmiku 3 (v tem primeru), da vrže napako, ker se arch ne ujema.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Naloži in zbere iz BPF_LD v obliki besede BPF_W, ki je sistemska klicna številka, vsebovana v fiksnem odmiku BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — primerja številko sistemskega klica z vrednostjo spremenljivke nr. Če sta enaka, se premakne na naslednje navodilo in onemogoči sistemski klic, sicer dovoli sistemski klic s SECCOMP_RET_ALLOW.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)) - zaključi program z BPF_RET in posledično ustvari napako SECCOMP_RET_ERRNO s številko iz spremenljivke err.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - prekine program z BPF_RET in omogoči izvedbo sistemskega klica s SECCOMP_RET_ALLOW.

SECCOMP JE CBPF
Morda se sprašujete, zakaj se uporablja seznam navodil namesto prevedenega predmeta ELF ali programa C, prevedenega JIT.

Za to sta dva razloga.

• Prvič, Seccomp uporablja cBPF (klasični BPF) in ne eBPF, kar pomeni: nima registrov, ampak samo akumulator za shranjevanje zadnjega rezultata izračuna, kot je razvidno iz primera.

• Drugič, Seccomp neposredno sprejme kazalec na niz navodil BPF in nič drugega. Makri, ki smo jih uporabili, preprosto pomagajo določiti ta navodila na programerju prijazen način.

Če potrebujete več pomoči pri razumevanju tega sklopa, si oglejte psevdokodo, ki naredi isto:

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

Ko definirate kodo filtra v strukturi socket_filter, morate definirati sock_fprog, ki vsebuje kodo in izračunano dolžino filtra. Ta podatkovna struktura je potrebna kot argument za razglasitev postopka, ki se bo izvajal pozneje:

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

V funkciji install_filter ostane le še ena stvar - naložiti sam program! Za to uporabimo prctl, pri čemer PR_SET_SECCOMP vzamemo kot možnost za vstop v varen računalniški način. Nato povemo načinu, naj naloži filter z uporabo SECCOMP_MODE_FILTER, ki je vsebovan v spremenljivki prog tipa sock_fprog:

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

Končno lahko uporabimo našo funkcijo install_filter, vendar moramo pred tem uporabiti prctl, da nastavimo PR_SET_NO_NEW_PRIVS za trenutno izvedbo in se tako izognemo situaciji, ko podrejeni procesi prejmejo več privilegijev kot njihovi starši. S tem lahko izvajamo naslednje prctl klice v funkciji install_filter, ne da bi imeli korenske pravice.

Zdaj lahko pokličemo funkcijo install_filter. Blokirajmo vse pisalne sistemske klice, povezane z arhitekturo X86-64, in preprosto dajmo dovoljenje, ki blokira vse poskuse. Po namestitvi filtra nadaljujemo z izvajanjem s prvim argumentom:

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]);
 }

Začnimo. Za prevajanje našega programa lahko uporabimo clang ali gcc, v obeh primerih gre le za prevajanje datoteke main.c brez posebnih možnosti:

clang main.c -o filter-write

Kot že omenjeno, smo blokirali vse vnose v programu. Če želite to preizkusiti, potrebujete program, ki nekaj izpiše - zdi se dober kandidat. Običajno se obnaša takole:

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

Čudovito! Takole izgleda uporaba našega ovojnega programa: program, ki ga želimo preizkusiti, preprosto posredujemo kot prvi argument:

./filter-write "ls -la"

Ko se ta program izvede, ustvari popolnoma prazen izpis. Vendar pa lahko uporabimo strace, da vidimo, kaj se dogaja:

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

Rezultat dela je močno skrajšan, vendar njegov ustrezni del kaže, da so zapisi blokirani z napako EPERM - isto, kot smo jo konfigurirali. To pomeni, da program ne izda ničesar, ker ne more dostopati do sistemskega klica write:

[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)

Zdaj razumete, kako deluje Seccomp BPF, in imate dobro predstavo o tem, kaj lahko storite z njim. Toda ali ne bi radi dosegli iste stvari z eBPF namesto cBPF, da bi izkoristili njegovo polno moč?

Ko razmišljajo o programih eBPF, večina ljudi misli, da jih preprosto napišejo in naložijo s skrbniškimi pravicami. Čeprav je ta izjava na splošno resnična, jedro implementira nabor mehanizmov za zaščito objektov eBPF na različnih ravneh. Ti mehanizmi se imenujejo pasti BPF LSM.

BPF LSM pasti

Da bi zagotovil spremljanje sistemskih dogodkov, neodvisno od arhitekture, LSM izvaja koncept pasti. Poklicni klic je tehnično podoben sistemskemu klicu, vendar je neodvisen od sistema in integriran z infrastrukturo. LSM zagotavlja nov koncept, v katerem lahko abstraktna plast pomaga preprečiti težave, do katerih pride pri obravnavanju sistemskih klicev na različnih arhitekturah.

V času pisanja tega članka ima jedro sedem kavljev, povezanih s programi BPF, in SELinux je edini vgrajeni LSM, ki jih izvaja.

Izvorna koda za pasti se nahaja v drevesu jedra v datoteki 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);

Vsak od njih bo poklican na različnih stopnjah izvajanja:

— security_bpf — izvede začetni pregled izvedenih sistemskih klicev BPF;

- security_bpf_map - preveri, kdaj jedro vrne deskriptor datoteke za zemljevid;

- security_bpf_prog - preveri, kdaj jedro vrne deskriptor datoteke za program eBPF;

— security_bpf_map_alloc — preveri, ali je varnostno polje znotraj preslikav BPF inicializirano;

- security_bpf_map_free - preveri, ali je varnostno polje počiščeno znotraj zemljevidov BPF;

— security_bpf_prog_alloc — preveri, ali je varnostno polje inicializirano znotraj programov BPF;

- security_bpf_prog_free - preveri, ali je varnostno polje počiščeno znotraj programov BPF.

Zdaj, ko vidimo vse to, razumemo: ideja za prestrezniki LSM BPF je, da lahko zagotovijo zaščito za vsak objekt eBPF in zagotovijo, da lahko samo tisti z ustreznimi privilegiji izvajajo operacije na karticah in programih.

Povzetek

Varnost ni nekaj, kar bi lahko implementirali na univerzalen način za vse, kar želite zaščititi. Pomembno je, da lahko zaščitimo sisteme na različnih ravneh in na različne načine. Verjeli ali ne, najboljši način za zaščito sistema je organiziranje različnih ravni zaščite z različnih pozicij, tako da zmanjšanje varnosti ene ravni ne omogoča dostopa do celotnega sistema. Glavni razvijalci so opravili odlično delo in nam ponudili nabor različnih slojev in stičnih točk. Upamo, da smo vam dobro razumeli, kaj so plasti in kako uporabljati programe BPF za delo z njimi.

O avtorjih

David Calavera je tehnični direktor pri Netlify. Delal je v podpori za Docker in prispeval k razvoju orodij Runc, Go in BCC ter drugih odprtokodnih projektov. Znan po svojem delu na projektih Docker in razvoju ekosistema vtičnikov Docker. David je zelo navdušen nad grafi plamena in vedno išče optimizacijo delovanja.

Lorenzo Fontana dela v odprtokodni ekipi pri Sysdigu, kjer je osredotočen predvsem na Falco, projekt Cloud Native Computing Foundation, ki zagotavlja varnost med izvajanjem vsebnika in odkrivanje anomalij prek modula jedra in eBPF. Navdušen je nad porazdeljenimi sistemi, programsko definiranim omrežjem, jedrom Linuxa in analizo zmogljivosti.

» Več o knjigi najdete na spletno stran založbe
» Kazalo
» Izvleček

Za Khabrozhiteley 25% popust z uporabo kupona - Linux

Ob plačilu papirne različice knjige vam po elektronski pošti pošljemo elektronsko knjigo.

Vir: www.habr.com

Dodaj komentar