Boka "BPF för Linux-övervakning"

Boka "BPF för Linux-övervakning"Hej alla Khabrobor! Den virtuella BPF-maskinen är en av de viktigaste komponenterna i Linux-kärnan. Dess korrekta användning gör det möjligt för systemingenjörer att hitta fel och lösa även de mest komplexa problem. Du kommer att lära dig hur man skriver program som övervakar och modifierar kärnans beteende, hur man säkert implementerar kod för att övervaka händelser i kärnan och mycket mer. David Calavera och Lorenzo Fontana hjälper dig att låsa upp kraften hos BPF. Utöka din kunskap om prestandaoptimering, nätverk, säkerhet. - Använd BPF för att övervaka och ändra beteendet hos Linuxkärnan. - Injicera kod för att säkert övervaka kärnhändelser utan att behöva kompilera om kärnan eller starta om systemet. — Använd praktiska kodexempel i C, Go eller Python. - Ta kontroll genom att äga BPF-programmets livscykel.

Linux Kernel Security, dess funktioner och Secomp

BPF ger ett kraftfullt sätt att utöka kärnan utan att offra stabilitet, säkerhet eller hastighet. Av denna anledning tyckte kärnutvecklarna att det skulle vara en bra idé att använda dess mångsidighet för att förbättra processisoleringen i Seccomp genom att implementera Seccomp-filter som stöds av BPF-program, även kända som Seccomp BPF. I det här kapitlet kommer vi att förklara vad Secomp är och hur det används. Sedan kommer du att lära dig hur du skriver Secomp-filter med BPF-program. Efter det ska vi titta på de inbyggda BPF-krokarna som ingår i kärnan för Linux-säkerhetsmoduler.

Linux Security Modules (LSM) är ett ramverk som tillhandahåller en uppsättning funktioner som kan användas för att implementera olika säkerhetsmodeller på ett standardiserat sätt. LSM kan användas direkt i kärnans källträd, såsom Apparmor, SELinux och Tomoyo.

Låt oss börja med att diskutera funktionerna hos Linux.

Capabilities

Kärnan i Linuxs möjligheter är att du behöver ge en oprivilegierad processbehörighet för att utföra en viss uppgift, men utan att använda suid för det ändamålet, eller på annat sätt göra processen privilegierad, vilket minskar risken för attack och tillåter processen att utföra vissa uppgifter. Till exempel, om din applikation behöver öppna en privilegierad port, säg 80, istället för att köra processen som root, kan du helt enkelt ge den CAP_NET_BIND_SERVICE-kapaciteten.

Överväg ett Go-program som heter main.go:

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

Detta program betjänar en HTTP-server på port 80 (detta är en privilegierad port). Vanligtvis kör vi det direkt efter kompilering:

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

Men eftersom vi inte beviljar root-privilegier kommer den här koden att ge ett fel när porten binds:

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

capsh (skalhanterare) är ett verktyg som kör ett skal med en specifik uppsättning funktioner.

I det här fallet, som redan nämnts, istället för att ge fullständiga roträttigheter, kan du aktivera privilegierad portbindning genom att tillhandahålla cap_net_bind_service-kapaciteten tillsammans med allt annat som redan finns i programmet. För att göra detta kan vi bifoga vårt 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"

Låt oss förstå det här laget lite.

  • capsh - använd capsh som ett skal.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - eftersom vi behöver ändra användaren (vi vill inte köra som root), kommer vi att specificera cap_net_bind_service och möjligheten att faktiskt ändra användar-ID från rot till ingen, nämligen cap_setuid och cap_setgid.
  • —keep=1 — vi vill behålla de installerade funktionerna när vi byter från root-kontot.
  • —user=“ingen” — slutanvändaren som kör programmet kommer att vara ingen.
  • —addamb=cap_net_bind_service — ställ in rensningen av relaterade funktioner efter byte från rotläge.
  • - -c "./capabilities" - kör bara programmet.

Länkade funktioner är en speciell typ av funktioner som ärvs av underordnade program när det aktuella programmet kör dem med execve(). Endast förmågor som tillåts associeras, eller med andra ord, som miljöförmågor, kan ärvas.

Du undrar förmodligen vad +eip betyder efter att ha angett förmågan i --caps-alternativet. Dessa flaggor används för att fastställa att kapaciteten:

-måste aktiveras (p);

-tillgänglig för användning (e);

-kan ärvas av underordnade processer (i).

Eftersom vi vill använda cap_net_bind_service måste vi göra detta med e-flaggan. Sedan startar vi skalet i kommandot. Detta kommer att köra funktionerna binär och vi måste markera den med flaggan i. Slutligen vill vi att funktionen ska vara aktiverad (vi gjorde detta utan att ändra UID) med p. Det ser ut som cap_net_bind_service+eip.

Du kan kontrollera resultatet med ss. Låt oss förkorta utgången lite för att passa på sidan, men den kommer att visa tillhörande port och användar-ID annat än 0, i det här fallet 65:

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

I det här exemplet använde vi capsh, men du kan skriva ett skal med libcap. För mer information, se man 3 libcap.

När man skriver program känner inte utvecklaren ofta till alla funktioner som programmet behöver vid körning; Dessutom kan dessa funktioner ändras i nya versioner.

För att bättre förstå funktionerna i vårt program kan vi ta BCC-kapabla verktyget, som ställer in kprobe för cap_capable-kärnfunktionen:

/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 uppnå samma sak genom att använda bpftrace med en one-liner kprobe i kärnfunktionen 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

Detta kommer att mata ut något i stil med följande om vårt programs funktioner är aktiverade 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 kolumnen är de möjligheter som processen behöver, och eftersom denna utdata inkluderar icke-revisionshändelser, ser vi alla icke-revisionskontroller och slutligen den erforderliga förmågan med revisionsflaggan (sist i utgången) inställd på 1. Capability. en vi är intresserade av är CAP_NET_BIND_SERVICE, den definieras som en konstant i kärnans källkod i filen include/uapi/linux/ability.h med identifierare 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 är ofta aktiverade under körning för behållare som runC eller Docker för att tillåta dem att köra i oprivilegierat läge, men de tillåts bara de funktioner som behövs för att köra de flesta applikationer. När en applikation kräver vissa funktioner kan Docker tillhandahålla dem med --cap-add:

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

Detta kommando ger behållaren CAP_NET_ADMIN-förmågan, vilket gör att den kan konfigurera en nätverkslänk för att lägga till dummy0-gränssnittet.

Nästa avsnitt visar hur man använder funktioner som filtrering, men med en annan teknik som gör att vi kan implementera våra egna filter programmatiskt.

Secomp

Secomp står för Secure Computing och är ett säkerhetslager implementerat i Linux-kärnan som låter utvecklare filtrera vissa systemanrop. Även om Secomp är jämförbar i kapacitet med Linux, gör dess förmåga att hantera vissa systemanrop det mycket mer flexibelt jämfört med dem.

Secomp- och Linux-funktioner utesluter inte varandra och används ofta tillsammans för att dra nytta av båda metoderna. Du kanske till exempel vill ge en process förmågan CAP_NET_ADMIN men inte tillåta den att acceptera socket-anslutningar, vilket blockerar acceptera och acceptera4 systemanrop.

Secomp-filtreringsmetoden är baserad på BPF-filter som arbetar i SECCOMP_MODE_FILTER-läget, och systemanropsfiltrering utförs på samma sätt som för paket.

Seccomp-filter laddas med prctl via PR_SET_SECCOMP-operationen. Dessa filter har formen av ett BPF-program som exekveras för varje Seccomp-paket som representeras av seccomp_data-strukturen. Denna struktur innehåller referensarkitekturen, en pekare till processorinstruktioner vid tidpunkten för systemanropet och maximalt sex systemanropsargument, uttryckta som uint64.

Så här ser strukturen secomp_data ut från kärnans källkod i filen linux/seccomp.h:

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

Som du kan se från den här strukturen kan vi filtrera efter systemanropet, dess argument eller en kombination av båda.

Efter att ha tagit emot varje Seccomp-paket måste filtret utföra bearbetning för att fatta ett slutgiltigt beslut och tala om för kärnan vad som ska göras härnäst. Det slutliga beslutet uttrycks av ett av returvärdena (statuskoder).

- SECCOMP_RET_KILL_PROCESS - dödar hela processen omedelbart efter filtrering av ett systemanrop som inte exekveras på grund av detta.

- SECCOMP_RET_KILL_THREAD - avslutar den aktuella tråden omedelbart efter filtrering av ett systemanrop som inte exekveras på grund av detta.

— SECCOMP_RET_KILL — alias för SECCOMP_RET_KILL_THREAD, vänster för bakåtkompatibilitet.

- SECCOMP_RET_TRAP - systemanropet är förbjudet, och SIGSYS-signalen (Bad System Call) skickas till uppgiften som anropar den.

- SECCOMP_RET_ERRNO - Systemanropet exekveras inte, och en del av SECCOMP_RET_DATA-filtrets returvärde skickas till användarutrymmet som felvärdet. Beroende på orsaken till felet returneras olika felvärden. En lista över felnummer finns i nästa avsnitt.

- SECCOMP_RET_TRACE - Används för att meddela ptrace-spåraren med - PTRACE_O_TRACESECCOMP för att avlyssna när ett systemanrop exekveras för att se och kontrollera den processen. Om en spårare inte är ansluten returneras ett fel, errno sätts till -ENOSYS och systemanropet exekveras inte.

- SECCOMP_RET_LOG - systemanropet löses och loggas.

- SECCOMP_RET_ALLOW - systemanropet är helt enkelt tillåtet.

ptrace är ett systemanrop för att implementera spårningsmekanismer i en process som kallas tracee, med förmågan att övervaka och kontrollera exekveringen av processen. Spårningsprogrammet kan effektivt påverka exekveringen och modifiera spårningens minnesregister. I Secomp-sammanhang används ptrace när den triggas av SECCOMP_RET_TRACE-statuskoden, så spåraren kan förhindra systemanropet från att exekvera och implementera sin egen logik.

Secomp-fel

Då och då, när du arbetar med Seccomp, kommer du att stöta på olika fel, som identifieras av ett returvärde av typen SECCOMP_RET_ERRNO. För att rapportera ett fel kommer seccomp-systemanropet att returnera -1 istället för 0.

Följande fel är möjliga:

- EACCESS - Den som ringer får inte ringa ett systemsamtal. Detta händer vanligtvis eftersom det inte har CAP_SYS_ADMIN-privilegier eller att no_new_privs inte är inställt med prctl (vi ska prata om detta senare);

— EFAULT — de godkända argumenten (args i seccomp_data-strukturen) har inte en giltig adress;

— EINVAL — det kan finnas fyra anledningar här:

-den begärda operationen är okänd eller stöds inte av kärnan i den aktuella konfigurationen;

-de angivna flaggorna är inte giltiga för den begärda operationen;

-operation inkluderar BPF_ABS, men det finns problem med den specificerade offseten, som kan överstiga storleken på seccomp_data-strukturen;

-antalet instruktioner som skickas till filtret överstiger det maximala;

— ENOMEM — inte tillräckligt med minne för att köra programmet;

- EOPNOTSUPP - operationen indikerade att med SECCOMP_GET_ACTION_AVAIL var åtgärden tillgänglig, men kärnan stöder inte returer i argument;

— ESRCH — ett problem uppstod vid synkronisering av en annan ström;

- ENOSYS - Det finns ingen spårare kopplad till SECCOMP_RET_TRACE-åtgärden.

prctl är ett systemanrop som tillåter ett användarutrymmesprogram att manipulera (ställa in och hämta) specifika aspekter av en process, såsom byte endianness, trådnamn, säkert beräkningsläge (Seccomp), privilegier, Perf-händelser, etc.

Secomp kan verka som en sandlådeteknik för dig, men det är det inte. Secomp är ett verktyg som låter användare utveckla en sandlådemekanism. Låt oss nu titta på hur användarinteraktionsprogram skapas med ett filter som anropas direkt av Secommp-systemanropet.

BPF Secomp Filter Exempel

Här kommer vi att visa hur man kombinerar de två åtgärder som diskuterats tidigare, nämligen:

— vi kommer att skriva ett Seccomp BPF-program, som kommer att användas som ett filter med olika returkoder beroende på vilka beslut som fattas;

— ladda filtret med prctl.

Först behöver du rubriker från standardbiblioteket och Linux-kärnan:

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

Innan vi försöker det här exemplet måste vi se till att kärnan är kompilerad med CONFIG_SECCOMP och CONFIG_SECCOMP_FILTER satt till y. På en fungerande maskin kan du kontrollera detta så här:

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

Resten av koden är en tvådelad install_filter-funktion. Den första delen innehåller vår lista med 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),
  };

Instruktionerna ställs in med hjälp av makrona BPF_STMT och BPF_JUMP som definieras i filen linux/filter.h.
Låt oss gå igenom instruktionerna.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - systemet laddar och ackumuleras från BPF_LD i form av ordet BPF_W, paketdata är lokaliserad vid en fast offset BPF_ABS.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, båge, 0, 3) - kontrollerar med hjälp av BPF_JEQ om arkitekturvärdet i ackumulatorkonstanten BPF_K är lika med båge. Om så är fallet, hoppar vid offset 0 till nästa instruktion, annars hoppar vid offset 3 (i detta fall) för att kasta ett fel eftersom bågen inte matchar.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Laddar och ackumuleras från BPF_LD i form av ordet BPF_W, vilket är systemanropsnumret som ingår i den fasta offseten av BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — jämför systemanropsnumret med värdet på variabeln nr. Om de är lika, går du vidare till nästa instruktion och inaktiverar systemanropet, annars tillåter systemanropet med SECCOMP_RET_ALLOW.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)) - avslutar programmet med BPF_RET och ger som ett resultat ett fel SECCOMP_RET_ERRNO med numret från felvariabeln.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - avslutar programmet med BPF_RET och tillåter att systemanropet exekveras med SECCOMP_RET_ALLOW.

SECCOMP ÄR CBPF
Du kanske undrar varför en lista med instruktioner används istället för ett kompilerat ELF-objekt eller ett JIT-kompilerat C-program.

Det finns två skäl till detta.

• För det första använder Seccomp cBPF (klassisk BPF) och inte eBPF, vilket betyder: den har inga register, utan bara en ackumulator för att lagra det senaste beräkningsresultatet, som kan ses i exemplet.

• För det andra accepterar Secomp en pekare till en uppsättning BPF-instruktioner direkt och inget annat. Makron vi har använt hjälper helt enkelt till att specificera dessa instruktioner på ett programmerarvänligt sätt.

Om du behöver mer hjälp med att förstå denna sammansättning, överväg pseudokoden som gör samma sak:

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

Efter att ha definierat filterkoden i socket_filter-strukturen måste du definiera en sock_fprog som innehåller koden och den beräknade längden på filtret. Denna datastruktur behövs som ett argument för att förklara att processen ska köras senare:

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

Det finns bara en sak kvar att göra i install_filter-funktionen - ladda själva programmet! För att göra detta använder vi prctl, med PR_SET_SECCOMP som ett alternativ för att gå in i säkert datorläge. Sedan säger vi till läget att ladda filtret med SECCOMP_MODE_FILTER, som finns i progvariabeln av typen sock_fprog:

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

Slutligen kan vi använda vår install_filter-funktion, men innan dess måste vi använda prctl för att ställa in PR_SET_NO_NEW_PRIVS för den aktuella exekveringen och därmed undvika situationen där underordnade processer får fler privilegier än sina föräldrar. Med detta kan vi göra följande prctl-anrop i install_filter-funktionen utan att ha root-rättigheter.

Nu kan vi anropa funktionen install_filter. Låt oss blockera alla skrivsystemanrop relaterade till X86-64-arkitekturen och helt enkelt ge en behörighet som blockerar alla försök. Efter att ha installerat filtret fortsätter vi körningen med det första argumentet:

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

Låt oss börja. För att kompilera vårt program kan vi använda antingen clang eller gcc, hur som helst är det bara att kompilera filen main.c utan speciella alternativ:

clang main.c -o filter-write

Som nämnts har vi blockerat alla poster i programmet. För att testa detta behöver du ett program som matar ut något - det verkar vara en bra kandidat. Så här beter hon sig vanligtvis:

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

Underbar! Så här ser det ut att använda vårt omslagsprogram: Vi klarar helt enkelt programmet vi vill testa som första argument:

./filter-write "ls -la"

När det körs producerar det här programmet helt tomt utdata. Men vi kan använda strace för att se vad som händer:

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

Resultatet av arbetet förkortas avsevärt, men motsvarande del av det visar att poster är blockerade med EPERM-felet - samma som vi konfigurerade. Detta betyder att programmet inte matar ut något eftersom det inte kan komma åt skrivsystemanropet:

[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 förstår du hur Secomp BPF fungerar och har en god uppfattning om vad du kan göra med det. Men skulle du inte vilja uppnå samma sak med eBPF istället för cBPF för att utnyttja dess fulla kraft?

När man tänker på eBPF-program tror de flesta att de helt enkelt skriver dem och laddar dem med administratörsrättigheter. Även om detta påstående generellt är sant, implementerar kärnan en uppsättning mekanismer för att skydda eBPF-objekt på olika nivåer. Dessa mekanismer kallas BPF LSM-fällor.

BPF LSM-fällor

För att tillhandahålla arkitekturoberoende övervakning av systemhändelser implementerar LSM konceptet med fällor. Ett hook call liknar tekniskt sett ett systemsamtal, men är systemoberoende och integrerat med infrastrukturen. LSM tillhandahåller ett nytt koncept där ett abstraktionsskikt kan hjälpa till att undvika problem som uppstår vid hantering av systemanrop på olika arkitekturer.

I skrivande stund har kärnan sju krokar associerade med BPF-program, och SELinux är den enda inbyggda LSM som implementerar dem.

Källkoden för fällorna finns i kärnträdet 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);

Var och en av dem kommer att anropas i olika skeden av utförande:

— security_bpf — utför en första kontroll av exekverade BPF-systemanrop;

- security_bpf_map - kontrollerar när kärnan returnerar en filbeskrivning för kartan;

- security_bpf_prog - kontrollerar när kärnan returnerar en filbeskrivning för eBPF-programmet;

— security_bpf_map_alloc — kontrollerar om säkerhetsfältet inuti BPF-kartor är initierat;

- security_bpf_map_free - kontrollerar om säkerhetsfältet är rensat inuti BPF-kartor;

— security_bpf_prog_alloc — kontrollerar om säkerhetsfältet är initialiserat i BPF-program;

- security_bpf_prog_free - kontrollerar om säkerhetsfältet är rensat i BPF-program.

Nu när vi ser allt detta förstår vi: tanken bakom LSM BPF-interceptorer är att de kan ge skydd till varje eBPF-objekt, vilket säkerställer att endast de med lämpliga privilegier kan utföra operationer på kort och program.

Sammanfattning

Säkerhet är inget du kan implementera på ett enhetligt sätt för allt du vill skydda. Det är viktigt att kunna skydda system på olika nivåer och på olika sätt. Tro det eller ej, det bästa sättet att säkra ett system är att organisera olika skyddsnivåer från olika positioner, så att en minskning av säkerheten på en nivå inte tillåter åtkomst till hela systemet. Kärnutvecklarna har gjort ett bra jobb med att ge oss en uppsättning olika lager och beröringspunkter. Vi hoppas att vi har gett dig en bra förståelse för vad lager är och hur du använder BPF-program för att arbeta med dem.

Om författare

David Calavera är CTO på Netlify. Han arbetade i Docker-support och bidrog till utvecklingen av Runc-, Go- och BCC-verktyg, samt andra projekt med öppen källkod. Känd för sitt arbete med Docker-projekt och utveckling av Docker-plugin-ekosystemet. David är mycket passionerad när det gäller flamgrafer och är alltid ute efter att optimera prestanda.

Lorenzo Fontana arbetar i open source-teamet på Sysdig, där han främst är fokuserad på Falco, ett Cloud Native Computing Foundation-projekt som tillhandahåller containerruntime-säkerhet och avvikelsedetektering genom en kärnmodul och eBPF. Han brinner för distribuerade system, mjukvarudefinierat nätverk, Linux-kärnan och prestandaanalys.

» Mer information om boken finns på förlagets webbplats
» innehållsförteckning
» Utdrag

För Khabrozhiteley 25% rabatt med kupong - Linux

Vid betalning av pappersversionen av boken skickas en elektronisk bok via e-post.

Källa: will.com

Lägg en kommentar