Liburua "BPF Linux Monitoring"

Liburua "BPF Linux Monitoring"Kaixo, Khabro bizilagunak! BPF makina birtuala Linux kernelaren osagai garrantzitsuenetako bat da. Bere erabilera egokiak sistema ingeniariei matxurak aurkitzeko eta arazo konplexuenak ere konpontzeko aukera emango die. Nukleoaren portaera kontrolatzen eta aldatzen duten programak nola idazten ikasiko duzu, nukleoko gertaerak kontrolatzeko kodea modu seguruan inplementatu eta askoz gehiago. David Calaverak eta Lorenzo Fontanak BPF-ren boterea desblokeatzen lagunduko dizute. Zabaldu zure ezagutza errendimenduaren optimizazioa, sareak, segurtasuna. - Erabili BPF Linux kernelaren portaera kontrolatzeko eta aldatzeko. - Sartu kodea nukleoaren gertaerak modu seguruan kontrolatzeko, nukleoa berriro konpilatu edo sistema berrabiarazi beharrik gabe. — Erabili kode adibide erosoak C, Go edo Python-en. - Kontrola hartu BPF programaren bizi-zikloaren jabe eginez.

Linux Kernel segurtasuna, bere ezaugarriak eta Seccomp

BPF-k nukleoa zabaltzeko modu indartsua eskaintzen du egonkortasuna, segurtasuna edo abiadura uko egin gabe. Hori dela eta, nukleoko garatzaileek ideia ona izango zela pentsatu zuten Seccomp-en prozesuen isolamendua hobetzeko bere aldakortasuna erabiltzea, BPF programek onartzen duten Seccomp iragazkiak ezarriz, Seccomp BPF izenez ere ezagutzen direnak. Kapitulu honetan Seccomp zer den eta nola erabiltzen den azalduko dugu. Ondoren, Seccop iragazkiak BPF programak erabiliz idazten ikasiko duzu. Horren ondoren, Linux segurtasun-moduluetarako nukleoan sartzen diren BPF kako integratuak ikusiko ditugu.

Linux Security Modules (LSM) hainbat segurtasun-eredu modu estandarizatuan ezartzeko erabil daitezkeen funtzio multzo bat eskaintzen duen esparrua da. LSM nukleoaren iturburuen zuhaitzean zuzenean erabil daiteke, hala nola Apparmor, SELinux eta Tomoyo.

Has gaitezen Linuxen gaitasunak eztabaidatzen.

Capabilities

Linux-en gaitasunen funtsa zera da: pribilegiorik gabeko prozesu bati baimena eman behar zaiola zeregin jakin bat burutzeko, baina horretarako suid erabili gabe, edo bestela prozesua pribilegiatu egin behar duzula, erasotzeko aukera murriztuz eta prozesuari zeregin jakin batzuk egiteko aukera emanez. Adibidez, zure aplikazioak ataka pribilegiatu bat ireki behar badu, demagun 80, prozesua root gisa exekutatu beharrean, CAP_NET_BIND_SERVICE gaitasuna eman diezaiokezu.

Demagun main.go izeneko Go programa bat:

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

Programa honek HTTP zerbitzari bat zerbitzatzen du 80 atakan (hau ataka pribilegiatua da). Normalean konpilatu ondoren berehala exekutatzen dugu:

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

Hala ere, root pribilegioak ematen ez ditugunez, kode honek errore bat emango du ataka lotzean:

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

capsh (shell manager) gaitasun multzo zehatz batekin shell bat exekutatzen duen tresna da.

Kasu honetan, lehen esan bezala, root eskubide osoak eman beharrean, pribilegiodun ataka lotzea gaitu dezakezu cap_net_bind_service gaitasuna programan dagoen beste guztiarekin batera emanez. Horretarako, gure programa capsh-n sartu dezakegu:

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

Uler dezagun talde hau pixka bat.

  • capsh - erabili capsh maskor gisa.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - erabiltzailea aldatu behar dugunez (ez dugu root gisa exekutatu nahi), cap_net_bind_service eta erabiltzaile IDa benetan aldatzeko gaitasuna zehaztuko dugu. root inori, hots, cap_setuid eta cap_setgid.
  • —keep=1 — instalatutako gaitasunak mantendu nahi ditugu root kontutik aldatzean.
  • —user=“nobody” — programa exekutatzen duen azken erabiltzailea inor izango da.
  • —addamb=cap_net_bind_service — ezarri erlazionatutako gaitasunen garbiketa erro modutik aldatu ondoren.
  • - -c "./capabilities" - exekutatu programa.

Lotutako gaitasunak programa umeek heredatzen dituzten gaitasun mota berezi bat dira, uneko programak execve( erabiliz) exekutatzen dituenean. Elkartzeko baimena duten gaitasunak bakarrik, edo bestela esanda, inguruneko gaitasun gisa, hereda daitezke.

Ziurrenik +eip-ek zer esan nahi duen galdetzen ari zara --caps aukeran gaitasuna zehaztu ondoren. Bandera hauek gaitasun hori zehazteko erabiltzen dira:

-aktibatu behar da (p);

- erabiltzeko erabilgarri (e);

-haur-prozesuek heredatu dezakete (i).

cap_net_bind_service erabili nahi dugunez, e banderarekin egin behar dugu. Ondoren, shell-a abiaraziko dugu komandoan. Honek gaitasunen bitarra exekutatuko du eta i banderarekin markatu behar dugu. Azkenik, funtzioa gaituta egotea nahi dugu (UIDa aldatu gabe egin dugu) or. Cap_net_bind_service+eip itxura du.

Emaitza ss erabiliz egiaztatu dezakezu. Laburtu dezagun irteera apur bat orrialdera egokitzeko, baina 0 ez den 65 ez den beste portua eta erabiltzaile IDa erakutsiko ditu, kasu honetan 534:

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

Adibide honetan capsh erabili dugu, baina libcap erabiliz shell bat idatz dezakezu. Informazio gehiagorako, ikus man 3 libcap.

Programak idaztean, askotan garatzaileak ez ditu aldez aurretik ezagutzen programak exekuzio garaian behar dituen ezaugarri guztiak; Gainera, ezaugarri hauek alda daitezke bertsio berrietan.

Gure programaren gaitasunak hobeto ulertzeko, BCC gai den tresna har dezakegu, kprobe ezartzen duena cap_capable kernel funtziorako:

/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

Gauza bera lor dezakegu bpftrace lerro bakarreko kprobe batekin cap_capable kernel funtzioan:

bpftrace -e 
   'kprobe:cap_capable {
      time("%H:%M:%S ");
      printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
    }' 
    | grep -i capabilities

Honek honelako zerbait aterako du gure programaren gaitasunak kprobe ondoren gaituta badaude:

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

Bosgarren zutabea prozesuak behar dituen gaitasunak dira, eta irteera honek auditoretzakoak ez diren gertaerak barne hartzen dituenez, auditoretzakoak ez diren egiaztapen guztiak eta, azkenik, beharrezko gaitasuna ikusiko dugu auditoria-marka (irteeran azkena) 1. Gaitasuna ezarrita. interesatzen zaiguna CAP_NET_BIND_SERVICE da, include/uapi/linux/ability.h fitxategian nukleoaren iturburu-kodean konstante gisa definitzen da 10 identifikatzailearekin:

/* Allows binding to TCP/UDP sockets below 1024 */
/* Allows binding to ATM VCIs below 32 */
#define CAP_NET_BIND_SERVICE 10<source lang="go">

RunC edo Docker bezalako edukiontzietarako gaitasunak sarritan gaituta daude pribilegiorik gabeko moduan exekutatzeko, baina aplikazio gehienak exekutatzeko behar diren gaitasunak baino ez dituzte onartzen. Aplikazio batek gaitasun batzuk behar dituenean, Docker-ek --cap-add erabiliz eman ditzake:

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

Komando honek CAP_NET_ADMIN gaitasuna emango dio edukiontziari, dummy0 interfazea gehitzeko sareko esteka bat konfiguratzeko aukera emanez.

Hurrengo atalean iragazketa bezalako ezaugarriak nola erabili erakusten du, baina gure iragazkiak programatikoki ezartzeko aukera ematen digun beste teknika bat erabiliz.

Seccomp

Seccomp Secure Computing esan nahi du eta Linux nukleoan inplementatutako segurtasun-geruza bat da, garatzaileek sistema-dei batzuk iragazteko aukera ematen diena. Seccomp Linux-ekin konparagarria den arren, sistema-dei jakin batzuk kudeatzeko gaitasunak askoz malguagoa egiten du haiekin alderatuta.

Seccomp eta Linux ezaugarriak ez dira elkarren artean esklusiboak eta askotan elkarrekin erabiltzen dira bi ikuspegietatik etekina ateratzeko. Esate baterako, baliteke prozesu bati CAP_NET_ADMIN gaitasuna eman nahi izatea, baina socket konexioak onartzen ez dituena, onartu eta onartu4 sistema-deiak blokeatuz.

Seccomp iragazteko metodoa SECCOMP_MODE_FILTER moduan funtzionatzen duten BPF iragazkietan oinarritzen da, eta sistema-deien iragazketa paketeen modu berean egiten da.

Seccomp iragazkiak prctl erabiliz kargatzen dira PR_SET_SECCOMP eragiketaren bidez. Iragazki hauek seccomp_data egiturak adierazten duen Seccomp pakete bakoitzeko exekutatzen den BPF programa baten forma hartzen dute. Egitura honek erreferentzia-arkitektura, sistema-deiaren unean prozesadorearen instrukzioen erakuslea eta sistema-deiaren argumentu gehienez sei, uint64 gisa adierazita.

Hau da seccomp_data egitura linux/seccomp.h fitxategiko nukleoaren iturburu-kodearen itxura:

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

Egitura honetatik ikus dezakezunez, sistema-deiaren, bere argumentuen edo bien konbinazioaren arabera iragaz dezakegu.

Seccomp pakete bakoitza jaso ondoren, iragazkiak prozesatzea egin behar du azken erabakia hartzeko eta nukleoari jarraian zer egin behar duen esateko. Azken erabakia itzultzeko balioetako batek adierazten du (egoera kodeak).

- SECCOMP_RET_KILL_PROCESS - prozesu osoa hiltzen du horregatik exekutatzen ez den sistema-deia iragazi ondoren.

- SECCOMP_RET_KILL_THREAD - uneko haria amaitzen du horregatik exekutatzen ez den sistema-deia iragazi ondoren.

— SECCOMP_RET_KILL — SECCOMP_RET_KILL_THREAD ezizena, atzerako bateragarritasunerako utzi da.

- SECCOMP_RET_TRAP - sistema-deia debekatuta dago, eta SIGSYS (Bad System Call) seinalea bidaltzen zaio deitzen duen zereginari.

- SECCOMP_RET_ERRNO - Sistema-deia ez da exekutatzen, eta SECCOMP_RET_DATA iragazkiaren itzulera-balioaren zati bat erabiltzailearen espaziora pasatzen da errno balio gisa. Errorearen kausaren arabera, errno balio desberdinak itzultzen dira. Errore-zenbakien zerrenda hurrengo atalean eskaintzen da.

- SECCOMP_RET_TRACE - Ptrace trazatzaileari jakinarazteko erabiltzen da - PTRACE_O_TRACESECCOMP erabiliz prozesu hori ikusteko eta kontrolatzeko sistema dei bat exekutatzen denean atzemateko. Trazatzaile bat konektatzen ez bada, errore bat itzultzen da, errno -ENOSYS gisa ezartzen da eta sistema-deia ez da exekutatzen.

- SECCOMP_RET_LOG - sistema-deia konpondu eta erregistratuta dago.

- SECCOMP_RET_ALLOW - sistema deia besterik gabe onartzen da.

ptrace tracee izeneko prozesu batean trazamendu-mekanismoak ezartzeko sistema-dei bat da, prozesuaren exekuzioa kontrolatzeko eta kontrolatzeko gaitasuna duena. Trace programak eraginkortasunez eragin dezake exekuzioan eta tracee-ren memoria-erregistroak alda ditzake. Seccomp testuinguruan, ptrace erabiltzen da SECCOMP_RET_TRACE egoera-kodeak abiarazten duenean, beraz, trazatzaileak sistema-deia exekutatzea eta bere logika ezartzea eragotzi dezake.

Seccomp akatsak

Noizean behin, Seccomp-ekin lan egiten duzun bitartean, hainbat errore topatuko dituzu, SECCOMP_RET_ERRNO motako itzulera-balioarekin identifikatzen direnak. Errore baten berri emateko, seccomp sistema deiak -1 itzuliko du 0 beharrean.

Akats hauek posible dira:

- ACCESS - Deitzaileak ezin du sistema deirik egin. Hau gertatzen da normalean CAP_SYS_ADMIN pribilegiorik ez duelako edo no_new_privs ez dagoelako prctl erabiliz (aurrerago hitz egingo dugu honetaz);

— EFAULT — pasatu diren argumentuek (args seccomp_data egituran) ez dute baliozko helbiderik;

— EINVAL — lau arrazoi egon daitezke hemen:

- eskatutako eragiketa ezezaguna da edo nukleoak ez du onartzen oraingo konfigurazioan;

-Zehaztutako banderak ez dute balio eskatutako eragiketarako;

-operazioak BPF_ABS barne hartzen du, baina zehaztutako desplazamenduarekin arazoak daude, eta horrek seccomp_data egituraren tamaina gaindi dezake;

-iragazkira pasatzen diren argibide kopuruak gehienezkoa gainditzen du;

— ENOMEM — ez dago memoria nahikoa programa exekutatzeko;

- EOPNOTSUPP - eragiketak SECCOMP_GET_ACTION_AVAIL-ekin ekintza erabilgarri zegoela adierazi zuen, baina nukleoak ez ditu argumentuetan itzultzen onartzen;

— ESRCH — arazo bat gertatu da beste korronte bat sinkronizatzean;

- ENOSYS - Ez dago SECCOMP_RET_TRACE ekintzari aztarnatzailerik erantsita.

prctl sistema-dei bat da, erabiltzaile-espazioko programa bati prozesu baten alderdi zehatzak manipulatzeko (ezarri eta lortzeko) aukera ematen diona, hala nola byte-endiantasuna, harien izenak, kalkulu modu segurua (Seccomp), pribilegioak, Perf gertaerak, etab.

Seccomp sandbox teknologia bat irudituko zaizu, baina ez da. Seccomp erabiltzaileei sandbox mekanismo bat garatzeko aukera ematen dien utilitate bat da. Ikus dezagun orain Seccomp sistema-deiak zuzenean deitutako iragazkia erabiliz erabiltzaileen interakzio-programak nola sortzen diren.

BPF Seccomp iragazkiaren adibidea

Hemen erakutsiko dugu nola uztartu lehen aipatu ditugun bi ekintzak, hots:

— Seccop BPF programa bat idatziko dugu, hartutako erabakien arabera itzulera-kode ezberdinekin iragazki gisa erabiliko dena;

— Kargatu iragazkia prctl erabiliz.

Lehenik eta behin liburutegi estandarreko eta Linux nukleoko goiburuak behar dituzu:

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

Adibide honekin saiatu baino lehen, ziurtatu behar dugu nukleoa CONFIG_SECCOMP eta CONFIG_SECCOMP_FILTER ezarrita duela konpilatuta dagoela. Laneko makina batean hau egiazta dezakezu honela:

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

Gainerako kodea install_filter bi zatiko funtzioa da. Lehenengo zatiak BPF iragazteko argibideen zerrenda dauka:

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

Argibideak linux/filter.h fitxategian definitutako BPF_STMT eta BPF_JUMP makroak erabiliz ezartzen dira.
Jarrai ditzagun argibideak.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - sistema BPF_LD-tik kargatzen eta metatzen da BPF_W hitzaren forman, pakete datuak desplazamendu finko batean kokatzen dira BPF_ABS.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) - BPF_JEQ erabiliz egiaztatzen du ea BPF_K metagailuaren konstantearen arkitektura-balioa arkuaren berdina den. Hala bada, 0 desplazamenduan jauzi egiten da hurrengo instrukziora, bestela 3. desplazamenduan jauzi egiten da (kasu honetan) errore bat botatzeko, arkua ez datorrelako bat.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - BPF_LD-tik kargatzen eta metatzen da BPF_W hitzaren forman, hau da, BPF_ABSren desplazamendu finkoan dagoen sistema-deiaren zenbakia.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — sistemaren dei-zenbakia nr aldagaiaren balioarekin alderatzen du. Berdinak badira, hurrengo instrukziora pasatzen da eta sistema-deia desgaitzen du, bestela SECCOMP_RET_ALLOW-rekin sistema-deia baimentzen du.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)) - programa BPF_RET-ekin amaitzen du eta ondorioz SECCOMP_RET_ERRNO errore bat sortzen du err aldagaiaren zenbakiarekin.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - BPF_RET-ekin programa amaitzen du eta sistema-deia SECCOMP_RET_ALLOW erabiliz exekutatzeko aukera ematen du.

SECCOMP CBPF DA
Galdetzen ari zara zergatik erabiltzen den argibideen zerrenda konpilatutako ELF objektu baten ordez edo JIT konpilatutako C programa baten ordez.

Bi arrazoi daude horretarako.

• Lehenik eta behin, Seccopek cBPF (BPF klasikoa) erabiltzen du eta ez eBPF, hau da: ez du erregistrorik, azken kalkuluaren emaitza gordetzeko metagailu bat baizik, adibidean ikus daitekeen bezala.

• Bigarrenik, Seccomp-ek BPF instrukzioen array baten erakuslea onartzen du zuzenean eta kito. Erabili ditugun makroek argibide hauek programatzaileen modu egokian zehazten laguntzen dute.

Muntaia hau ulertzeko laguntza gehiago behar baduzu, kontuan hartu gauza bera egiten duen pseudokodea:

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

Iragazkiaren kodea socket_filter egituran definitu ondoren, kodea eta kalkulatutako iragazkiaren luzera dituen sock_fprog bat definitu behar duzu. Datu-egitura hau argumentu gisa behar da prozesua gero exekutatzeko deklaratzeko:

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

Install_filter funtzioan gauza bakarra dago egiteko - kargatu programa bera! Horretarako, prctl erabiltzen dugu, PR_SET_SECCOMP aukera gisa hartuz informatika modu seguruan sartzeko. Ondoren, moduari esaten diogu iragazkia kargatzeko SECCOMP_MODE_FILTER erabiliz, hau sock_fprog motako prog aldagaian dagoena:

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

Azkenik, gure install_filter funtzioa erabil dezakegu, baina aurretik prctl erabili behar dugu PR_SET_NO_NEW_PRIVS uneko exekuziorako ezartzeko eta, horrela, haur prozesuek gurasoek baino pribilegio gehiago jasotzen duten egoera saihesteko. Honekin, prctl dei hauek egin ditzakegu install_filter funtzioan root eskubiderik izan gabe.

Orain install_filter funtzioa deitu dezakegu. Blokeatu ditzagun X86-64 arkitekturarekin lotutako sistema-dei guztiak eta eman ditzagun saiakera guztiak blokeatzen dituen baimena. Iragazkia instalatu ondoren, lehen argumentua erabiliz exekutatzen jarraituko dugu:

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

Has gaitezen. Gure programa konpilatzeko clang edo gcc erabil ditzakegu, edozein modutan main.c fitxategia konpilatzen besterik ez da aukera berezirik gabe:

clang main.c -o filter-write

Esan bezala, programako sarrera guztiak blokeatu ditugu. Hau probatzeko zerbait ateratzen duen programa behar duzu - ls hautagai ona dirudi. Honela jokatzen du normalean:

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

Zoragarria! Hona hemen gure wrapper programa erabiltzearen itxura: Probatu nahi dugun programa lehen argumentu gisa pasatzen dugu:

./filter-write "ls -la"

Exekutatzen denean, programa honek irteera guztiz hutsa sortzen du. Hala ere, strace erabil dezakegu zer gertatzen ari den ikusteko:

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

Lanaren emaitza asko laburtzen da, baina dagokion zatiak erakusten du erregistroak blokeatuta daudela EPERM errorearekin -konfiguratu genuen bera-. Horrek esan nahi du programak ez duela ezer ateratzen, ezin duelako idazteko sistema-deian sartu:

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

Orain ulertzen duzu Seccop BPF-k nola funtzionatzen duen eta ideia ona duzu horrekin zer egin dezakezun. Baina ez al zenuke gauza bera lortzea gustatuko eBPF-rekin cBPF-ren ordez bere botere osoa aprobetxatzeko?

eBPF programetan pentsatzen denean, gehienek pentsatzen dute idazten dutela eta administratzaile-pribilegioekin kargatzen dituztela. Adierazpen hau, oro har, egia den arren, nukleoak eBPF objektuak hainbat mailatan babesteko mekanismo multzo bat inplementatzen du. Mekanismo horiei BPF LSM tranpak deitzen zaie.

BPF LSM tranpak

Sistemaren gertaeren arkitekturatik independentea den monitorizazioa eskaintzeko, LSMk tranpa kontzeptua ezartzen du. Hook dei bat sistema dei baten antzekoa da teknikoki, baina sistema independentea da eta azpiegiturarekin integratuta dago. LSM-k kontzeptu berri bat eskaintzen du, non abstrakzio-geruza batek arkitektura ezberdinetan sistema-deiak tratatzerakoan sortzen diren arazoak saihesten lagun dezake.

Idazteko unean, nukleoak BPF programekin lotutako zazpi kako ditu, eta SELinux da horiek inplementatzen dituen LSM barneratu bakarra.

Trapetarako iturburu kodea include/linux/security.h fitxategiko nukleoaren zuhaitzean dago:

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

Horietako bakoitza exekuzio fase desberdinetan deituko da:

— security_bpf — exekutatutako BPF sistema-deien hasierako egiaztapena egiten du;

- security_bpf_map - nukleoak maparako fitxategi deskribatzailea noiz itzultzen duen egiaztatzen du;

- security_bpf_prog - nukleoak eBPF programarako fitxategi deskribatzailea noiz itzultzen duen egiaztatzen du;

— security_bpf_map_alloc — BPF mapen barruko segurtasun eremua hasieratuta dagoen egiaztatzen du;

- security_bpf_map_free - egiaztatzen du segurtasun-eremua BPF mapen barruan garbitu den;

— security_bpf_prog_alloc — egiaztatzen du segurtasun-eremua BPF programen barruan hasieratuta dagoen;

- security_bpf_prog_free - BPF programen barruan segurtasun-eremua garbitu den egiaztatzen du.

Orain, hori guztia ikusita, ulertzen dugu: LSM BPF atzemateen atzean dagoen ideia eBPF objektu guztiei babesa eman diezaieketela da, pribilegio egokiak dituztenek bakarrik txarteletan eta programetan eragiketak egin ditzaketela ziurtatuz.

Laburpena

Segurtasuna ez da babestu nahi duzun guztiarako neurri bakarrean ezar dezakezun zerbait. Garrantzitsua da sistemak maila ezberdinetan eta modu ezberdinetan babestu ahal izatea. Sinetsi ala ez, sistema bat ziurtatzeko modurik onena posizio desberdinetatik babes-maila desberdinak antolatzea da, maila bateko segurtasuna murrizteak sistema osorako sartzea ahalbidetzen ez dezan. Oinarrizko garatzaileek lan bikaina egin dute geruza eta ukipen-puntu ezberdinen multzoa eskainiz. Geruzak zer diren eta haiekin lan egiteko BPF programak nola erabili behar diren ondo ulertu izana espero dugu.

Egileei buruz

David Calavera Netlifyko CTO da. Docker laguntzan lan egin zuen eta Runc, Go eta BCC tresnen garapenean lagundu zuen, baita kode irekiko beste proiektu batzuetan ere. Docker proiektuetan egindako lanagatik eta Docker plugin ekosistemaren garapenagatik ezaguna. David oso sutsua da flame grafikoekin eta beti dabil errendimendua optimizatzea.

Lorenzo Fontana Sysdig-eko kode irekiko taldean lan egiten du, non, batez ere, Falco-n zentratuta dagoen, Cloud Native Computing Foundation proiektuan, edukiontzien exekuzio-denboran segurtasuna eta anomaliak detektatzeko kernel-modulu baten eta eBPF bidez. Banatutako sistemak, software definitutako sareak, Linux kernelak eta errendimenduaren analisiak ditu gogotsu.

» Liburuari buruzko xehetasun gehiago hemen aurki daitezke argitaletxearen webgunea
» Edukien taula
» Laburpena

Khabrozhiteleyrentzat % 25eko deskontua kupoia erabiliz - Linux

Liburuaren paperezko bertsioa ordaintzean, liburu elektroniko bat bidaliko da posta elektronikoz.

Iturria: www.habr.com

Gehitu iruzkin berria