Bogen "BPF til overvågning af Linux"

Bogen "BPF til overvågning af Linux"Hej, Habr-beboere! BPF-virtuelle maskiner er en af de vigtigste komponenter i Linux-kernen. Korrekt anvendelse gør det muligt for systemingeniører at finde fejl og løse selv de mest komplekse problemer. Du vil lære at oprette programmer, der overvåger og modificerer kerneladfærd, kan sikkert implementere kode til at overvåge begivenheder i kernen og meget mere. David Calavera og Lorenzo Fontana vil hjælpe dig med at udforske BPF's muligheder. Udvid din viden om ydeevneoptimering, netværk, sikkerhed. — Brug BPF til at overvåge og modificere adfærd i Linux-kernen. — Implementer kode til sikker overvågning af begivenheder i kernen — uden at skulle recompilere kernen eller genstarte systemet. — Benyt dig af nyttige eksempler på kode i C, Go eller Python. — Tag kontrol over situationen ved at forstå livscyklussen for et BPF-program.

Sikkerhed i Linux-kernen, dens muligheder og Seccomp

BPF giver en kraftfuld måde at udvide kernen på uden at gå på kompromis med stabilitet, sikkerhed og hastighed. Af denne grund mente kerneludviklerne, at det ville være en god idé at bruge dens alsidighed til at forbedre procesisolering i Seccomp ved at implementere Seccomp-filtre understøttet af BPF-programmer, også kendt som Seccomp BPF. I dette kapitel vil vi forklare, hvad Seccomp er, og hvordan det anvendes. Derefter vil du lære at skrive Seccomp-filtre med BPF-programmer. Til sidst vil vi se på de indbyggede BPF-fælder i kernen til sikkerhedsmoduler i Linux.

Linux-sikkerhedsmoduler (LSM) er en platform, der giver et sæt funktioner, der kan anvendes til standardiseret implementering af forskellige sikkerhedsmodeller. LSM kan anvendes direkte i kildetræet for kernen, f.eks. AppArmor, SELinux og Tomoyo.

Lad os begynde med at diskutere Linux' muligheder.

Muligheder

Essensen af mulighederne i Linux er, at du skal give en ikke-privilegeret proces tilladelse til at udføre en bestemt opgave, men uden at bruge suid til dette formål, eller på anden måde gøre processen privilegeret, hvilket reducerer muligheden for angreb og giver processen mulighed for at udføre specifikke opgaver. For eksempel, hvis din applikation har brug for at åbne en privilegeret port, lad os sige 80, kan du i stedet for at køre processen som root blot give den muligheden CAP_NET_BIND_SERVICE.

Lad os overveje et Go-program ved navn main.go:

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

Dette program serverer en HTTP-server på port 80 (dette er en privilegeret port). Normalt kører vi det straks efter kompilering:

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

Men da vi ikke giver root-rettigheder, vil denne kode returnere en fejl ved binding til porten:

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

capsh (shell management tool) er et værktøj, der starter en shell med et bestemt sæt af muligheder.

I dette tilfælde, som allerede nævnt, i stedet for at give fulde root-rettigheder kan vi tillade binding af privilegerede porte ved at give muligheden cap_net_bind_service sammen med alle de andre, der allerede er i programmet. For at gøre dette kan vi indkapsle vores program i 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"

Lad os se nærmere på denne kommando.

  • capsh — brug capsh som shell.
  • —caps=’cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep’ — da vi skal skifte bruger (vi ønsker ikke at køre med root-rettigheder), angiver vi cap_net_bind_service og muligheden for faktisk at ændre bruger-id fra root til nobody, nemlig cap_setuid og cap_setgid.
  • —keep=1 — vi ønsker at bevare de indstillede muligheder, når der skiftes fra root-kontoen.
  • —user=«nobody» — den endelige bruger, der kører programmet, vil være nobody.
  • —addamb=cap_net_bind_service — vi angiver, at relaterede muligheder skal rydde op efter at have skiftet fra root-tilstand.
  • — -c ". /capabilities" — vi kører blot programmet.

Relaterede muligheder er en særlig type muligheder, der arves af datterprogrammer, når det nuværende program udfører dem via execve(). Kun muligheder, der er godkendt som relaterede, kan arves, eller med andre ord, som miljømuligheder.

Du er sikkert nysgerrig efter, hvad +eip betyder efter angivelsen af en mulighed i kommandoen —caps. Disse flag bruges til at definere, hvad muligheden:

-skal være aktiveret (p);

-er tilgængelig til anvendelse (e);

-kan arves af datterprocesser (i).

Da vi ønsker at bruge cap_net_bind_service, skal vi gøre dette med flaget e. Derefter skal vi starte shell'en i kommandoen. Som resultat vil binære fil capabilities blive startet, og vi skal markere det med flaget i. Endelig ønsker vi, at muligheden skal være aktiveret (vi gjorde dette uden at ændre UID) ved hjælp af p. Dette ser ud som cap_net_bind_service+eip.

Du kan kontrollere resultatet med ss. Vi forkorter output noget, så det passer på siden, men det vil vise den tilknyttede port og bruger-id, der er forskellig fra 0, i dette tilfælde 65 534:

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

I dette eksempel brugte vi capsh, men du kan skrive en shell ved hjælp af libcap. For mere information, henvises der til man 3 libcap.

Når programmører skriver programmer, ved de ofte ikke på forhånd, hvilke muligheder programmet vil have brug for under kørsel; desuden kan disse muligheder ændre sig i nye versioner.

For bedre at forstå mulighederne i vores program, kan vi tage værktøjet BCC capable, som sætter kprobe for kernel-funktionen 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

Vi kan opnå det samme ved at bruge bpftrace med en engangskprobe i kernel-funktionen 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

Dette vil udskrive noget som følger, hvis mulighederne i vores program er aktiveret efter 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

Den femte kolonne angiver de muligheder, processen har brug for, og da disse output inkluderer ikke-revisionerede begivenheder, ser vi alle ikke-revisionerede kontroller og til sidst den nødvendige mulighed med revisionsflaget (den sidste i outputtet), der er sat til 1. Den mulighed, vi er interesseret i, er CAP_NET_BIND_SERVICE, som er defineret som en konstant i kernens kildekode i filen include/uapi/linux/ability.h med identifikatoren 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">

Muligheder anvendes ofte under udførelsen af containere som runC eller Docker, så de kan køre i uhæmmet tilstand, men kun får tildelt de nødvendige muligheder for at køre de fleste applikationer. Når en applikation har brug for specifikke muligheder, kan disse gives i Docker ved hjælp af —cap-add:

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

Denne kommando giver containeren mulighed for CAP_NET_ADMIN, hvilket gør det muligt for den at konfigurere et netværkslink til at tilføje dummy0-interfacet.

I det følgende afsnit vises brugen af sådanne muligheder som filtrering, men med en anden metode, der giver os mulighed for programmatiske implementeringer af vores egne filtre.

Seccomp

Seccomp står for Secure Computing, og det er et sikkerhedsniveau, der er implementeret i Linux-kernen, som gør det muligt for udviklere at filtrere bestemte systemopkald. Selvom Seccomp er sammenligneligt med Linux-muligheder, gør dets evne til at styre bestemte systemopkald det langt mere fleksibelt end dem.

Seccomp og Linux-muligheder udelukker ikke hinanden, og de bruges ofte sammen for at drage fordel af begge tilgange. For eksempel kan du ønske at give en proces mulighed for CAP_NET_ADMIN, men ikke tillade den at tage forbindelser via socket, ved at blokere systemopkald som accept og accept4.

Seccomp-filtermetoden er baseret på BPF-filtre, der kører i SECCOMP_MODE_FILTER-tilstand, og filtreringen af systemopkald udføres ligesom for pakker.

Seccomp-filtre indlæses ved hjælp af prctl via operationen PR_SET_SECCOMP. Disse filtre er i form af et BPF-program, der udføres for hver Seccomp-pakke, der præsenteres med struktur seccomp_data. Denne struktur indeholder referencearkitekturen, en peger til processorens instruktioner under systemopkaldet og op til seks argumenter for systemopkaldet, udtrykt som uint64.

Sådan ser strukturen seccomp_data ud fra kildekoden til kernen i filen linux/seccomp.h:

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

Som det ses i denne struktur, kan vi filtrere efter systemopkaldet, dets argumenter eller deres kombination.

Efter modtagelse af hver pakke skal Seccomp-filteret udføre behandling for at træffe en endelig beslutning og informere kernen om, hvad der skal ske derefter. Den endelige beslutning udtrykkes med en af de returnerede værdier (statuskoder).

— SECCOMP_RET_KILL_PROCESS — afslutning af hele processen straks efter filtrering af systemopkaldet, som derfor ikke udføres.

— SECCOMP_RET_KILL_THREAD — afslutning af den aktuelle tråd straks efter filtrering af systemopkaldet, som derfor ikke udføres.

— SECCOMP_RET_KILL — alias for SECCOMP_RET_KILL_THREAD, tilbageholdt for bagudkompatibilitet.

— SECCOMP_RET_TRAP — systemopkaldet er forbudt, og signalet SIGSYS (Bad System Call) sendes til den kaldende opgave.

— SECCOMP_RET_ERRNO — systemopkaldet udføres ikke, og en del af den returnerede værdi fra filteret SECCOMP_RET_DATA overføres til brugerrummet som errno-værdien. Afhængigt af fejlårsagen returneres forskellige errno-værdier. Listen over fejlnumre præsenteres i den følgende sektion.

— SECCOMP_RET_TRACE — bruges til at underrette traceren ptrace med — PTRACE_O_TRACESECCOMP for at opfange, når et systemopkald udføres, for at se og kontrollere denne proces. Hvis traceren ikke er tilsluttet, returneres en fejl, errno sættes til -ENOSYS, og systemopkaldet udføres ikke.

— SECCOMP_RET_LOG — systemopkaldet er tilladt og registreret i loggen.

— SECCOMP_RET_ALLOW — systemopkaldet er blot tilladt.

ptrace er et systemopkald til implementering af sporingsmekanismer i en proces, der kaldes tracee, med mulighed for at observere og kontrollere udførelsen af processen. Sporingsprogrammet kan effektivt påvirke udførelsen og ændre tracee's hukommelsesregistre. I konteksten af Seccomp bruges ptrace, når den aktiveres af SECCOMP_RET_TRACE-statuskoden, således at tracer kan forhindre udførelsen af systemopkaldet og implementere sin egen logik.

Seccomp-fejl

Fra tid til anden, når du arbejder med Seccomp, vil du støde på forskellige fejl, som identificeres af den returnerede værdi af typen SECCOMP_RET_ERRNO. For at rapportere en fejl vil systemopkaldet seccomp returnere -1 i stedet for 0.

Følgende fejl kan forekomme:

— EACCESS — den kaldende part har ikke tilladelse til at foretage systemopkald. Dette sker normalt fordi den ikke har CAP_SYS_ADMIN privilegier eller fordi no_new_privs ikke er sat med prctl (dette vil vi tale om senere);

— EFAULT — de overførte argumenter (args i seccomp_data strukturen) har ikke en gyldig adresse;

— EINVAL — der kan være fire årsager her:

- den anmodede operation er ukendt eller understøttes ikke af kernen i den nuværende konfiguration;

- de angivne flag er ugyldige for den anmodede operation;

- operationen inkluderer BPF_ABS, men der er problemer med den angivne forskydning, der kan overskride størrelsen af seccomp_data strukturen;

- antallet af instruktioner, der er givet til filteret, overskrider maksimum;

— ENOMEM — ikke nok hukommelse til at udføre programmet;

— EOPNOTSUPP — operationen angav, at SECCOMP_GET_ACTION_AVAIL-handlingen var tilgængelig, men kernen understøtter ikke tilbagevenden i argumenterne;

— ESRCH — der opstod et problem med synkronisering af en anden tråd;

— ENOSYS — der er ingen tracer knyttet til SECCOMP_RET_TRACE-handlingen.

prctl er et systemopkald, som gør det muligt for et brugerprogram at administrere (sætte og få) specifikke aspekter af processen, såsom byteorden, trådnavne, beskyttelsesmitteringsmodus (Seccomp), privilegier, Perf-begivenheder osv.

Seccomp kan synes at være en sandkasse teknologi, men det er ikke tilfældet. Seccomp er et værktøj, der gør det muligt for brugerne at udvikle en sandkassemekanisme. Lad os nu se, hvordan brugerinteraktionsprogrammer skabes ved hjælp af et filter, der kaldes direkte med seccomp-systemopkaldet.

Eksempel på Seccomp BPF-filter

Her vil vi vise, hvordan man forbinder de to tidligere nævnte handlinger, nemlig:

— vi vil skrive et Seccomp BPF-program, der vil blive anvendt som filter med forskellige returkoder afhængigt af de trufne beslutninger;

— vi vil indlæse filteret ved hjælp af prctl.

Til at begynde med skal vi have overskrifter fra standardbiblioteket og Linux-kernen:

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

Før vi forsøger at udføre dette eksempel, skal vi sikre os, at kernen er kompileret med CONFIG_SECCOMP og CONFIG_SECCOMP_FILTER sat til y. På en arbejdsstation kan dette kontrolleres sådan:

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

Den øvrige del af koden udgør funktionen install_filter, som består af to dele. Den første del indeholder vores liste over BPF-filter instruktioner:

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

Instruktionerne sættes med makroerne BPF_STMT og BPF_JUMP, som er defineret i filen linux/filter.h.
Lad os gennemgå instruktionerne.

— BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) — systemet indlæser og akkumulerer med BPF_LD i form af ord BPF_W, pakkedataene er placeret med et fast offset BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) — kontrollerer med BPF_JEQ, om værdien af arkitekturen i konstantakkumulatoren BPF_K er lig med arch. Hvis ja, går det videre til den næste instruktion med offset 0; ellers springes der til offset 3 for at give en fejl (i dette tilfælde), fordi arch ikke stemmer overens.

— BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) — indlæser og akkumulerer med BPF_LD i form af ord BPF_W, som er nummeret på systemkaldet, der findes på et fast offset BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — sammenligner nummeret på systemkaldet med værdien af variablen nr. Hvis de er ens, går det videre til den næste instruktion og forbyder systemkaldet; ellers tillader det systemkaldet med SECCOMP_RET_ALLOW.

— BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)) — afslutter programmet med BPF_RET og resulterer i at give fejlen SECCOMP_RET_ERRNO med nummeret fra variablen err.

— BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) — afslutter programmet med BPF_RET og tillader udførelsen af systemkaldet ved hjælp af SECCOMP_RET_ALLOW.

SECCOMP — DETTE ER CBPF
Måske undrer du dig over, hvorfor der i stedet for et kompileret ELF-objekt eller et program skrevet i C, kompilert med JIT, bruges en liste over instruktioner.

Der er to grunde til dette.

• For det første anvender Seccomp cBPF (klassisk BPF) og ikke eBPF, hvilket betyder: den har ikke registre, men kun en akkumulator til at opbevare det sidste resultat af beregningerne, som man kan se i eksemplet.

• For det andet accepterer Seccomp en peger til et array af BPF-instruktioner direkte og intet andet. De makroer, vi har brugt, hjælper blot med at angive disse instruktioner i en programmerervenlig form.

Hvis du har brug for yderligere hjælp til at forstå denne opbygning, så overvej pseudokoden, som gør det samme:

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

Efter at have defineret filterkoden i socket_filter-strukturen, skal du definere sock_fprog, som indeholder koden og den beregnede længde af filteret. Denne datakonstruktion er nødvendig som et argument til erklæringen om at fortsætte processen:

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

Der er kun én ting, der er tilbage at gøre i funktionen install_filter — at indlæse selve programmet! Til dette bruger vi prctl med PR_SET_SECCOMP som option for at gå ind i beskyttede beregninger. Vi angiver derefter tilstanden til at indlæse filteret ved hjælp af SECCOMP_MODE_FILTER, som er indeholdt i variablen prog af typen sock_fprog:

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

Endelig kan vi benytte vores funktion install_filter, men først skal prctl anvendes for at indstille PR_SET_NO_NEW_PRIVS for den aktuelle udførelse og dermed undgå, at børneprocesser får bredere rettigheder end forældrene. I den forbindelse kan vi foretage følgende prctl-opkald i funktionen install_filter uden root-rettigheder.

Nu kan vi kalde funktionen install_filter. Vi blokerer alle systemopkald, der vedrører skrivninger relateret til X86-64-arkitekturen, og giver blot tilladelse, der blokerer alle forsøg. Efter at have indstillet filteret fortsætter vi udførelsen ved at bruge det første 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]);
 }

Lad os komme i gang. Til at kompilere vores program kan vi bruge enten clang eller gcc; i begge tilfælde er det blot kompilering af filen main.c uden specielle indstillinger:

clang main.c -o filter-write

Som nævnt har vi blokeret alle skrivninger i programmet. For at teste dette har vi brug for et program, der outputter noget — ls ser ud til at være en god kandidat. Her er, hvordan det normalt opfører sig:

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

Fantastisk! Sådan ser det ud at bruge vores shell-program: vi sender blot programmet, vi ønsker at teste, som det første argument:

./filter-write "ls -la"

Efter udførelsen giver dette program helt tom output. Ikke desto mindre kan vi anvende strace for at se, hvad der sker:

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

Resultatet er betydeligt forkortet, men den relevante del viser, at optegnelserne blokeres med fejl EPERM — den samme, vi har konfigureret. Det betyder, at programmet ikke giver noget output, fordi det ikke kan få adgang til systemkaldet write:

[pid 25099] write(2, "ls: ", 4) = -1 EPERM (Operation ikke tilladt)
[pid 25099] write(2, "skrivningsfejl", 11) = -1 EPERM (Operation ikke tilladt)
[pid 25099] write(2, "n", 1) = -1 EPERM (Operation ikke tilladt)

Nu forstår du, hvordan Seccomp BPF fungerer, og du har en god idé om, hvad der kan gøres med det. Men ville det ikke være fantastisk at opnå det samme med eBPF i stedet for cBPF for at udnytte hele dens kraft?

Når man tænker på eBPF-programmer, tænker de fleste på, at de blot skriver dem og uploader dem med administratorrettigheder. Selvom denne påstand generelt er sand, implementerer kernen et sæt mekanismer til at beskytte eBPF-objekter på forskellige niveauer. Disse mekanismer kaldes BPF LSM fælter.

BPF LSM fælter

For at sikre en arkitektur-uafhængig kontrol af systembegivenheder implementerer LSM konceptet med fælter. Teknisk set ligner et felts kald et systemkald, men er uafhængigt af systemet og integreret med infrastrukturen. LSM præsenterer et nyt koncept, hvor abstraheringsniveauet er i stand til at hjælpe med at undgå problemer, der opstår ved håndtering af systemkald på forskellige arkitekturer.

På tidspunktet for bogens skrivning havde kernen syv fælter relateret til BPF-programmer og SELinux — den eneste indbyggede LSM, der implementerer dem.

Kildekoden til fælterne er placeret i kernel-træet i filen 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);

Hver af dem vil blive kaldt på forskellige tidspunkter i udførelsen:

— security_bpf — udfører en indledende kontrol af udførte systemopkald fra BPF;

— security_bpf_map — kontrollerer, når kernen returnerer en fildescriptor for en kortlægning;

— security_bpf_prog — kontrollerer, når kernen returnerer en fildescriptor for et eBPF-program;

— security_bpf_map_alloc — kontrollerer, om sikkerhedsfeltet er initialiseret inden for BPF-kortlægninger;

— security_bpf_map_free — kontrollerer, om sikkerhedsfeltet renses inden for BPF-kortlægninger;

— security_bpf_prog_alloc — kontrollerer, om sikkerhedsfeltet initialiseres inden for BPF-programmer;

— security_bpf_prog_free — kontrollerer, om sikkerhedsfeltet renses inden for BPF-programmer.

Nu, ved at se alt dette, forstår vi: Ideen med LSM BPF-holdere er, at de kan sikre hver eBPF-objekt, hvilket sikrer, at kun de med de nødvendige privilegier kan udføre operationer på kortlægninger og programmer.

CV

Sikkerhed er ikke noget, du kan implementere på en universel måde for alt, hvad du ønsker at beskytte. Det er vigtigt at have mulighed for at beskytte systemer på forskellige niveauer og på forskellige måder. Tro det eller ej, den bedste måde at sikre et system på er at organisere forskellige beskyttelseslag fra forskellige positioner, så reduktion af sikkerheden i et lag ikke åbner adgangen til hele systemet. Kerneludviklerne har gjort et stort stykke arbejde for at give os et sæt forskellige lag og interaktionspunkter. Vi håber, at vi har givet dig en god forståelse af, hvad lag er, og hvordan man bruger BPF-programmer til at arbejde med dem.

Om forfatterne

David Calavera er teknisk direktør hos Netlify. Han har arbejdet i Docker-support og har været involveret i udviklingen af værktøjer som Runc, Go og BCC samt andre open source-projekter. Han er kendt for sit arbejde med Docker-projekter og udvikling af Docker-plugin-økosystemet. David elsker flamegrafer og stræber altid efter at optimere ydeevnen.

Lorenzo Fontana arbejder i et team af softwareudviklere med open source i Sysdig, hvor han primært arbejder med Falco - et projekt under Cloud Native Computing Foundation, der sikrer sikkerheden i containerkørselsmiljøer og opdager anomalier gennem kernelmodul og eBPF. Han er passioneret omkring distribuerede systemer, softwaredefinerede netværk, Linux-kernen og ydeevneanalyse.

» Mere information om bogen kan findes på forlagets hjemmeside
» Indholdsfortegnelse
» Uddrag

For Habr-læsere er der 25% rabat med koden — Linux

Ved betaling af den fysiske version af bogen sendes e-bogen til e-mail.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster