Hej, Khabro-beboere! Den virtuelle BPF-maskine er en af de vigtigste komponenter i Linux-kernen. Dens korrekte brug vil give systemingeniører mulighed for at finde fejl og løse selv de mest komplekse problemer. Du lærer, hvordan du opretter programmer, der overvåger og ændrer kernens adfærd, sikkert injicerer kode for at overvåge kernelhændelser og meget mere. David Calavera og Lorenzo Fontana vil hjælpe dig med at frigøre kraften i BPF. Udvid din viden om performanceoptimering, netværk og sikkerhed. — Brug BPF til at overvåge og ændre Linux-kernens adfærd. — Injicer kode for sikkert at overvåge kernelhændelser uden at skulle rekompilere kernen eller genstarte systemet. — Brug praktiske kodeeksempler i C, Go eller Python. — Håndter situationen ved at tage ejerskab over BPF-programmets livscyklus.
Linux-kernesikkerhed, dens funktioner og Seccomp
BPF giver en effektiv måde at udvide kernen på uden at gå på kompromis med stabilitet, sikkerhed eller hastighed. Af denne grund mente kerneudviklerne, 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 bruges. Derefter lærer du, hvordan man skriver Seccomp-filtre ved hjælp af BPF-programmer. Lad os derefter se på de indbyggede BPF-hooks, der er i kernen til Linux-sikkerhedsmoduler.
Linux Security Modules (LSM) er et framework, der leverer et sæt funktioner, der kan bruges til at implementere forskellige sikkerhedsmodeller på en standardiseret måde. LSM kan bruges direkte i kernens kildekodetræ, såsom Apparmor, SELinux og Tomoyo.
Lad os starte med at diskutere Linux' muligheder.
Capabilities
Poenget med Linux-funktioner er, at du skal give en ikke-privilegeret proces tilladelse til at udføre en bestemt opgave, men uden at bruge `suid` til det formål, eller på anden måde gøre processen privilegeret, hvilket reducerer angrebsfladen og tillader processen at udføre bestemte opgaver. Hvis din applikation for eksempel skal åbne en privilegeret port, f.eks. 80, i stedet for at køre processen som root, kan du blot give den CAP_NET_BIND_SERVICE-funktionen.
Overvej et Go-program med navnet main.go:
package main
import (
"net/http"
"log"
)
func main() {
log.Fatalf("%v", http.ListenAndServe(":80", nil))
}Dette program betjener en HTTP-server på port 80 (dette er en privilegeret port). Vi kører det normalt lige efter kompilering:
$ go build -o capabilities main.go
$ ./capabilitiesMen da vi ikke giver root-rettigheder, vil denne kode give en fejl, når porten bindes:
2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1capsh (shell control tool) er et værktøj, der starter en shell med et specifikt sæt af funktioner.
I dette tilfælde, som allerede nævnt, kan du i stedet for at give fulde root-rettigheder tillade binding af privilegerede porte ved at give cap_net_bind_service-funktionen sammen med alle de andre, der allerede er i programmet. For at gøre dette kan vi omskrive vores program med 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å dette hold.
- capsh - brug capsh som en skal.
- —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' — da vi skal ændre brugeren (vi ønsker ikke at køre som root), angiver vi cap_net_bind_service og muligheden for rent faktisk at ændre bruger-ID'et fra root til nobody, nemlig cap_setuid og cap_setgid.
- --keep=1 - vi ønsker at beholde de installerede funktioner, når vi skifter fra root-kontoen.
- --bruger="ingen" — slutbrugeren, der kører programmet, vil være ingen.
- --addamb=cap_net_bind_service — vi indstiller rydning af bundne funktioner efter skift fra root-tilstand.
- — -c "./capabilities" — kør blot programmet.
Tilknyttede funktioner er en særlig type funktioner, der nedarves af underprogrammer, når det aktuelle program udfører dem ved hjælp af execve(). Kun evner, der opløses som relaterede, eller med andre ord, som miljøevner, kan arves.
Du undrer dig sikkert over, hvad +eip betyder efter at have angivet en funktion i --caps-indstillingen. Disse flag bruges til at afgøre, om funktionen er:
-skal aktiveres (p);
-tilgængelig til brug (e);
- kan nedarves af underprocesser (i).
Da vi vil bruge cap_net_bind_service, skal vi gøre det med e-flaget. Så kører vi skallen i kommandoen. Dette vil køre capabilities-binærfilen, og vi skal markere den med i-flaget. Endelig ønsker vi at funktionen aktiveres (vi gjorde dette uden at ændre UID'et) ved hjælp af p. Det ser ud som cap_net_bind_service+eip.
Du kan tjekke resultatet med ss. Vi forkorter outputtet en smule, så det passer på siden, men det vil vise den tilhørende port og bruger-ID, der er forskellig fra 0, i dette tilfælde 65:
# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0I dette eksempel brugte vi capsh, men du kan skrive en wrapper ved hjælp af libcap. For mere information, se man 3 libcap.
Når udvikleren skriver programmer, kender de ofte ikke på forhånd alle de funktioner, som programmet skal bruge under kørsel; Desuden kan disse funktioner ændres i nye versioner.
For bedre at forstå programmets muligheder kan vi bruge BCC-værktøjet, som sætter kprobe til kernefunktionen 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 1Vi kan opnå det samme ved at bruge bpftrace med en en-linjet kprobe i kernefunktionen cap_capable:
bpftrace -e
'kprobe:cap_capable {
time("%H:%M:%S ");
printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
}'
| grep -i capabilitiesDette vil vise noget i retning af følgende, hvis vores programs funktioner 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 1Den femte kolonne er de funktioner, som processen har brug for, og da dette output inkluderer ikke-revisionshændelser, ser vi alle ikke-revisionskontroller og endelig den nødvendige funktion med revisionsflaget (det sidste i outputtet) sat til 1. Den funktion, vi er interesserede i, er CAP_NET_BIND_SERVICE, den er defineret som en konstant i kernelkildekoden i include/uapi/linux/ability.h med ID'et 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">Funktioner aktiveres ofte under udførelsen af containere som runC eller Docker, så de kører i ikke-privilegeret tilstand, men kun har de funktioner, der er nødvendige for at køre de fleste applikationer. Når en applikation kræver bestemte funktioner, kan Docker levere dem ved hjælp af --cap-add:
docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummyDenne kommando giver containeren CAP_NET_ADMIN-funktionen, som gør det muligt for den at konfigurere et netværkslink for at tilføje dummy0-grænsefladen.
Det næste afsnit viser, hvordan man bruger funktioner som filtrering, men ved hjælp af en anden metode, der giver os mulighed for at implementere vores egne filtre programmatisk.
Secomp
Seccomp står for Secure Computing, som er et sikkerhedslag implementeret i Linux-kernen, der giver udviklere mulighed for at filtrere bestemte systemkald. Selvom Seccomp kan sammenlignes med Linux-funktioner, gør dens evne til at administrere specifikke systemkald den meget mere fleksibel end dem.
Seccomp- og Linux-funktioner udelukker ikke hinanden; de bruges ofte sammen for at få fordelen af begge tilgange. For eksempel kan du give en proces CAP_NET_ADMIN-funktionen, men forhindre den i at acceptere socket-forbindelser ved at blokere systemkaldene accept og accept4.
Seccomp-filtreringsmetoden er baseret på BPF-filtre, der opererer i SECCOMP_MODE_FILTER-tilstand, og filtrering af systemkald udføres på samme måde som for pakker.
Seccomp-filtre indlæses ved hjælp af prctl via PR_SET_SECCOMP-operationen. Disse filtre har form af et BPF-program, der udføres for hver Seccomp-pakke repræsenteret af seccomp_data-strukturen. Denne struktur indeholder referencearkitekturen, en pointer til processorinstruktionerne på tidspunktet for systemkaldet og op til seks systemkaldsargumenter udtrykt som uint64.
Sådan ser seccomp_data-strukturen ud fra kernelkildekoden i linux/seccomp.h:
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};Som du kan se af denne struktur, kan vi filtrere efter systemkaldet, dets argumenter eller en kombination af begge.
Efter at have modtaget hver Seccomp-pakke, skal filteret udføre behandling for at træffe en endelig beslutning og fortælle kernen, hvad den skal gøre nu. Den endelige beslutning udtrykkes ved en af returværdierne (statuskoder).
— SECCOMP_RET_KILL_PROCESS — afbryder hele processen umiddelbart efter filtrering af det systemkald, der ikke udføres på grund af dette.
— SECCOMP_RET_KILL_THREAD — afslut den aktuelle tråd umiddelbart efter filtrering af systemkaldet, der ikke udføres på grund af den.
— SECCOMP_RET_KILL — alias for SECCOMP_RET_KILL_THREAD, efterladt for bagudkompatibilitet.
— SECCOMP_RET_TRAP — systemkaldet er forbudt, og et SIGSYS-signal (Bad System Call) sendes til den opgave, der kalder det.
— SECCOMP_RET_ERRNO — systemkaldet udføres ikke, og en del af returværdien fra SECCOMP_RET_DATA-filteret sendes til brugerområdet som errno-værdien. Afhængigt af årsagen til fejlen returneres forskellige errno-værdier. En liste over fejlnumre findes i næste afsnit.
- SECCOMP_RET_TRACE - bruges til at underrette ptrace-sporeren med - PTRACE_O_TRACESECCOMP om at opfange, når et systemkald udføres, for at se og kontrollere processen. Hvis traceren ikke er tilknyttet, returneres en fejl, errno sættes til -ENOSYS, og systemkaldet udføres ikke.
— SECCOMP_RET_LOG — systemkaldet er tilladt og logget.
— SECCOMP_RET_ALLOW — systemkaldet er simpelthen tilladt.
ptrace er et systemkald til implementering af sporingsmekanismer i en proces kaldet tracee, med evnen til at observere og kontrollere processens udførelse. Sporingsprogrammet kan effektivt påvirke udførelsen og ændre sporingshukommelsesregistrene. I forbindelse med Seccomp bruges ptrace, når den udløses af statuskoden SECCOMP_RET_TRACE, så traceren kan forhindre systemkaldet i at blive udført og implementere sin egen logik.
Seccomp-fejl
Fra tid til anden, når du arbejder med Seccomp, vil du støde på forskellige fejl, der identificeres af en returværdi af typen SECCOMP_RET_ERRNO. For at indikere en fejl returnerer seccomp-systemkaldet -1 i stedet for 0.
Følgende fejl er mulige:
— EACCESS — den, der ringer op, har ikke tilladelse til at foretage et systemopkald. Dette skyldes normalt, at den ikke har CAP_SYS_ADMIN-rettigheder, eller at no_new_privs ikke er indstillet ved hjælp af prctl (vi taler om dette senere);
— EFAULT — de overførte argumenter (argumenter i seccomp_data-strukturen) har ikke en gyldig adresse;
— EINVAL — der kan være fire grunde til dette:
- den anmodede handling er ukendt eller understøttes ikke af kernen i den nuværende konfiguration;
- de angivne flag er ugyldige for den ønskede handling;
- operationen inkluderer BPF_ABS, men der er problemer med den angivne offset, som kan overstige størrelsen af seccomp_data-strukturen;
- antallet af instruktioner, der sendes til filteret, overstiger det maksimale antal;
— ENOMEM — ikke nok hukommelse til at køre programmet;
— EOPNOTSUPP — operationen indikerede, at en handling var tilgængelig med SECCOMP_GET_ACTION_AVAIL, men kernen understøtter ikke returnering af argumenter;
— ESRCH — der opstod et problem under synkronisering af en anden tråd;
— ENOSYS — der er ingen sporingsenhed knyttet til SECCOMP_RET_TRACE-handlingen.
prctl er et systemkald, der tillader et brugerområdeprogram at kontrollere (indstille og hente) specifikke aspekter af en proces, såsom byterækkefølge, trådnavne, sikker databehandlingstilstand (Seccomp), privilegier, Perf-hændelser osv.
Seccomp virker måske som en sandkasseteknologi for dig, men det er det ikke. Seccomp er et værktøj, der giver brugerne mulighed for at udvikle en sandkassemekanisme. Lad os nu se på, hvordan brugerinteraktionsprogrammer oprettes ved hjælp af et filter, der kaldes direkte af Seccomp-systemkaldet.
Eksempel på BPF Seccomp-filter
Her vil vi vise, hvordan man kombinerer de to handlinger, der er omtalt tidligere, nemlig:
— vi vil skrive et Seccomp BPF-program, der skal bruges som et filter med forskellige returkoder afhængigt af de trufne beslutninger;
— indlæs filteret ved hjælp af prctl.
Først skal du bruge headere 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 dette eksempel, skal vi sikre os, at kernen er kompileret med CONFIG_SECCOMP og CONFIG_SECCOMP_FILTER sat til y. På en fungerende maskine kan du tjekke dette således:
cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP
Resten af koden er install_filter-funktionen, som består af to dele. Den første del indeholder vores liste over BPF-filtreringsinstruktioner:
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 angives ved hjælp af makroerne BPF_STMT og BPF_JUMP, der er defineret i 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 fra BPF_LD i form af ordet BPF_W, pakkedataene er placeret med en fast offset BPF_ABS.
— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) — kontrollerer ved hjælp af BPF_JEQ, om arkitekturværdien i BPF_K akkumulatorkonstanten er lig med arch. Hvis det er tilfældet, så hop til offset 0 til den næste instruktion, ellers, for at give en fejl, hop til offset 3 (i dette tilfælde), fordi arch ikke matcher.
— BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) — indlæser og akkumulerer fra BPF_LD i form af ordet BPF_W, som er systemkaldsnummeret indeholdt ved den faste offset BPF_ABS.
— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — sammenligner systemopkaldsnummeret med værdien af variablen nr. Hvis de er ens, fortsæt til den næste instruktion og afvis systemkaldet, ellers tillad systemkaldet med SECCOMP_RET_ALLOW.
— BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (fejl & SECCOMP_RET_DATA)) — afslutter programmet med BPF_RET og returnerer som følge heraf fejlen SECCOMP_RET_ERRNO med tallet fra err-variablen.
— BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) — afslutter programmet med BPF_RET og tillader, at systemkaldet udføres med SECCOMP_RET_ALLOW.
SECCOMP ER CBPF
Du undrer dig måske over, hvorfor en liste med instruktioner bruges i stedet for et kompileret ELF-objekt eller et JIT-kompileret C-program.Det er der to grunde til.
• For det første bruger Seccomp cBPF (klassisk BPF) i stedet for eBPF, hvilket betyder, at den ikke har nogen registre, kun en akkumulator til at gemme det sidste resultat af beregningen, som du kan se i eksemplet.
• For det andet tager Seccomp en pointer direkte til et array af BPF-instruktioner og intet andet. De makroer, vi brugte, hjælper os simpelthen med at specificere disse instruktioner i en form, der er bekvem for programmører.
Hvis du har brug for mere hjælp til at forstå denne assembly, så overvej denne pseudokode, der 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 filterlængde. Denne datastruktur er nødvendig som et argument for at deklarere processens arbejde senere:
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};Der er kun én ting tilbage at gøre i install_filter-funktionen: indlæse selve programmet! For at gøre dette bruger vi prctl, hvor vi tager PR_SET_SECCOMP som en mulighed for at gå i sikker databehandlingstilstand. Så beder vi tilstanden om at indlæse filteret ved hjælp af SECCOMP_MODE_FILTER, som er indeholdt i prog-variablen 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 bruge vores install_filter-funktion, men inden da skal vi bruge prctl til at indstille PR_SET_NO_NEW_PRIVS for den aktuelle udførelse og dermed undgå den situation, hvor underprocesser får højere rettigheder end deres forældre. I dette tilfælde kan vi foretage følgende prctl-kald i install_filter-funktionen uden at have root-rettigheder.
Nu kan vi kalde funktionen install_filter. Lad os blokere alle skrivesystemkald relateret til X86-64-arkitekturen og blot give tilladelse, der blokerer alle forsøg. Efter installation af filteret fortsætter vi udførelsen ved hjælp af 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. For at kompilere vores program kan vi bruge enten clang eller gcc. I begge tilfælde er det blot en kompilering af main.c-filen uden nogen særlige indstillinger:
clang main.c -o filter-writeSom nævnt har vi blokeret alle poster i programmet. For at teste dette, skal du bruge et program, der outputter noget - ls virker som en god kandidat. Sådan opfører hun sig normalt:
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
Vidunderlig! Sådan ser det ud, når vi bruger vores wrapper-program: Vi bruger blot det program, vi vil teste, som det første argument:
./filter-write "ls -la"Efter udførelse producerer dette program et helt tomt output. Vi kan dog bruge strace til at se, hvad der sker:
strace -f ./filter-write "ls -la"Outputtet er kraftigt forkortet, men den relevante del af det viser, at posterne er blokeret med EPERM-fejlen - den samme som vi konfigurerede. Det betyder, at programmet ikke udskriver noget, fordi det ikke kan få adgang til skrivesystemkaldet:
[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)Nu forstår du, hvordan Seccomp BPF fungerer, og har en god idé om, hvad du kan gøre med det. Men ville det ikke være rart at opnå det samme ved at bruge eBPF i stedet for cBPF for at udnytte dens fulde kraft?
Når de tænker på eBPF-programmer, tænker de fleste blot på at skrive dem og uploade 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ælder.
BPF LSM-fælder
For at kunne overvåge systemhændelser uafhængigt af arkitekturen implementerer LSM konceptet med fælder. Teknisk set ligner et hook-opkald et systemopkald, men er systemuafhængigt og integreret med infrastrukturen. LSM tilbyder et nyt koncept, hvor et abstraktionslag kan hjælpe med at undgå problemer, der opstår, når man håndterer systemkald på forskellige arkitekturer.
I skrivende stund har kernen syv hooks relateret til BPF-programmer, og SELinux er den eneste indbyggede LSM, der implementerer dem.
Kildekoden til hooksene findes i kernetræ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 stadier af udførelsen:
— security_bpf — udfører en indledende kontrol af udførte BPF-systemkald;
— security_bpf_map — tjekker, hvornår kernen returnerer en filbeskrivelse for kortet;
— security_bpf_prog — kontrollerer, hvornår kernen returnerer en filbeskrivelse for et eBPF-program;
— security_bpf_map_alloc — kontrollerer om sikkerhedsfeltet i BPF-kort er initialiseret;
— security_bpf_map_free — kontrollerer om sikkerhedsfeltet er ryddet i BPF-kort;
— security_bpf_prog_alloc — kontrollerer om sikkerhedsfeltet er initialiseret i BPF-programmer;
— security_bpf_prog_free — kontrollerer om sikkerhedsfeltet er ryddet i BPF-programmer.
Nu, når vi ser alt dette, forstår vi: ideen bag LSM BPF-interceptorer er, at de kan beskytte hvert eBPF-objekt og sikre, at kun dem med de relevante rettigheder kan udføre operationer på kort og programmer.
Resumé
Sikkerhed er ikke noget, man kan implementere på en one-size-fits-all-måde til alt, hvad man vil beskytte. Det er vigtigt at kunne beskytte systemer på forskellige niveauer og på forskellige måder. Tro det eller ej, men den bedste måde at sikre et system på er at organisere forskellige niveauer af beskyttelse fra forskellige vinkler, så et sikkerhedsbrud på ét niveau ikke giver adgang til hele systemet. Kerneudviklerne har gjort et fantastisk stykke arbejde med at give os et sæt forskellige lag og berøringspunkter. Vi håber, at vi har givet dig en god idé om, hvad lag er, og hvordan du bruger BPF-programmer til at arbejde med dem.
Om forfattere
David Calavera er teknisk direktør hos Netlify. Han har arbejdet med Docker-support og bidraget til udviklingen af Runc-, Go- og BCC-værktøjer samt andre open source-projekter. Kendt for sit arbejde med Docker-projekter og udviklingen af Docker-plugin-økosystemet. David er stor fan af flammegrafer og søger altid at optimere ydeevnen.
Lorenzo Fontana arbejder i open source-teamet hos Sysdig, hvor han primært fokuserer på Falco, et Cloud Native Computing Foundation-projekt, der leverer container runtime-sikkerhed og anomaliedetektion via et kernemodul og eBPF. Han brænder for distribuerede systemer, softwaredefinerede netværk, Linux-kernen og performanceanalyse.
» Flere detaljer om bogen kan findes på
»
»
For Khabrozhiteley 25% rabat ved brug af kupon - Linux
Ved betaling af papirversionen af bogen fremsendes en elektronisk bog på e-mail.
Kilde: www.habr.com
