Tere, Habrikad! Virtuaalne masin BPF on ĂŒks tĂ€htsamaid komponente Linuxi tuumas. Selle nĂ”uetekohane rakendamine vĂ”imaldab sĂŒsteemiinseneridel leida vigu ja lahendada isegi kĂ”ige keerulisemaid probleeme. Te Ă”pite looma programme, mis jĂ€lgivad ja muudavad tuuma kĂ€itumist, saate ohutult sisestada koodi sĂŒndmuste jĂ€lgimiseks tuumas ja palju muud. David Calavera ja Lorenzo Fontana aitavad teil avada BPF vĂ”imalused. TĂ€iendage oma teadmisi jĂ”udluse optimeerimise, vĂ”rkude ja turvalisuse kohta. â Kasutage BPF-d Linuxi tuuma kĂ€itumise jĂ€lgimiseks ja muutmiseks. â Sisestage kood ohutuks sĂŒndmuste jĂ€lgimiseks tuumas â ilma tuuma uuesti kompileerimata vĂ”i sĂŒsteemi taaskĂ€ivitamata. â Kasutage mugavaid koodinĂ€iteid C, Go vĂ”i Pythonis. â Hallake olukorda, valdades BPF programmi elutsĂŒklit.
Linuxi tuuma turvalisus, selle vÔimalused ja Seccomp
BPF pakub vĂ”imsat viisi tuuma laiendamiseks ilma stabiilsuse, turvalisuse ja kiiruseta. Just sellepĂ€rast mĂ”tlesid tuuma arendajad, et oleks suurepĂ€rane kasutada selle mitmekesisust protsesside isoleerimise parandamiseks Seccompis, rakendades BPF poolt toetatud Seccomp filtreid, tuntud ka kui Seccomp BPF. Selles peatĂŒkis rÀÀgime, mis on Seccomp ja kuidas seda rakendatakse. SeejĂ€rel Ă”pite, kuidas kirjutada Seccomp filtreid BPF programmide abil. PĂ€rast seda vaatame sisse ehitatud BPF lĂ”kse, mis on olemas Linuxi turvamuudatustes.
Linuxi turvamuudatused (LSM) on platvorm, mis pakub komplekti funktsioone, mida saab rakendada erinevate turvamudelite standardiseeritud rakendamiseks. LSM-i saab kasutada otse tuuma lÀhtekoodide puus, nÀiteks Apparmor, SELinux ja Tomoyo.
Alustame arutelu Linuxi vĂ”imaluste ĂŒle.
VÔimalused
Linuxi vĂ”imekuse tuum seisneb selles, et peate andma tavalisele protsessile Ă”iguse teatud ĂŒlesande tĂ€itmiseks, kuid ilma et peaksite selleks kasutama suidi, vĂ”i muul viisil muutma protsessi privileegide taset, vĂ€hendades seelĂ€bi rĂŒnnaku vĂ”imalusi ja andes protsessile vĂ”imaluse teatud ĂŒlesannete tĂ€itmiseks. NĂ€iteks, kui teie rakendus vajab privileegitud portaali avamist, nĂ€iteks 80, saate selle asemel, et kĂ€ivitada protsess root'i alt, anda sellele lihtsalt CAP_NET_BIND_SERVICE Ă”iguse.
Vaadakem Go programmi nimega main.go:
package main
import (
"net/http"
"log"
)
func main() {
log.Fatalf("%v", http.ListenAndServe(":80", nil))
}See programm teenindab HTTP-serverit pordil 80 (see on privileegitud port). TĂŒĂŒpiliselt kĂ€ivitame selle kohe pĂ€rast kompileerimist:
$ go build -o capabilities main.go
$ ./capabilitiesKuna me ei anna root Ôigusi, annab see kood pordi sidumisel tÔrke:
2019/04/25 23:17:06 listen tcp :80: bind: permission denied
exit status 1capsh (vÔimaluste haldamise shell) on tööriist, mis kÀivitab shelli teatud Ôiguste komplektiga.
Selles olukorras, nagu juba mainitud, ei pea me andma tÀielikku root Ôiguste komplekti, vaid saame lubada privileegitud portide sidumise, andes Ôiguse cap_net_bind_service, koos kÔigi muude Ôigustega, mis programmil juba on. Selleks vÔime oma programmi paigutada capsh-i:
# 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"Vaatame seda kÀsklust veidi lÀhemalt.
- capsh â kasutame capshi shellina.
- âcaps=âcap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+epâ â kuna me peame muutma kasutajat (me ei soovi kĂ€ivitada root Ă”igustega), mÀÀrame cap_net_bind_service ja Ă”iguse sisuliselt muuta kasutaja ID-d root'ilt nobody'le, nimelt cap_setuid ja cap_setgid.
- âkeep=1 â soovime sĂ€ilitada mÀÀratud Ă”igused, kui oleme vahetanud konto root'ilt.
- âuser=«nobody» â programmi kĂ€ivitavaks lĂ”ppkasutajaks on nobody.
- âaddamb=cap_net_bind_service â mÀÀrame seotud Ă”iguste puhastamise pĂ€rast vahetamist root reĆŸiimist.
- â -c ". /capabilities" â lihtsalt kĂ€ivitame programmi.
Seotud Ôigused on erilised Ôigused, mis pÀrandatakse allprogrammidele, kui praegune programm tÀidab neid execve() abil. PÀranduda vÔivad ainult Ôigused, mis on mÀÀratud kui seotud, vÔi teisisÔnu, kui keskkonna Ôigused.
TĂ”enĂ€oliselt olete huvitatud, mida tĂ€hendab +eip vĂ”imaluse nĂ€itamisel valikus âcaps. Need lipud mÀÀravad, et vĂ”imalus:
- peab olema aktiveeritud (p);
- on rakendamiseks saadaval (e);
- vÔib olla pÀrandatud alamprotsesside poolt (i).
Kuna tahame kasutada cap_net_bind_service'i, peame seda tegema lipuga e. SeejÀrel kÀivitame kÀsurealt shelli. Tulemuseks on, et kÀivitatakse capabilities binaarfail ja peame selle mÀrkima lipuga i. LÔpuks tahame, et vÔimalus oleks aktiveeritud (oleme selle teinud, muutes UID-d) p abil. See nÀeb vÀlja nagu cap_net_bind_service+eip.
Saate tulemuse kontrollida ss abil. LĂŒhendame vĂ€ljundit, et see mahuks lehele, kuid see nĂ€itab seotud porti ja kasutaja ID-d, mis ei ole 0, antud juhul 65 534:
# ss -tulpn -e -H | cut -d' ' -f17-
128 *:80 *:*
users:(("capabilities",pid=30040,fd=3)) uid:65534 ino:11311579 sk:2c v6only:0Sel juhul kasutasime capsh, kuid saate shelli kirjutada ka libcap'i abil. Lisainformatsiooni saamiseks vaadake man 3 libcap.
Programmi kirjutamisel ei tea arendaja ĂŒsna sageli ette, millised Ă”igused on programmil kĂ€itamise ajal vajalikud; veelgi enam, uutes versioonides vĂ”ivad need Ă”igused muutuda.
Meie programmi Ôiguste paremaks mÔistmiseks vÔime vÔtta tööriista BCC capable, mis seadistab kprobe funktsiooni kernelis 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 1Sama saab saavutada, kasutades bpftrace'i ĂŒhe reaga kprobe funktsiooni kernelis cap_capable:
bpftrace -e
'kprobe:cap_capable {
time("%H:%M:%S ");
printf("%-6d %-6d %-16s %-4d %dn", uid, pid, comm, arg2, arg3);
}'
| grep -i capabilitiesSee kuvab midagi sellist, kui meie programmi Ôigused on aktiveeritud pÀrast 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 1Viies veerg on Ă”igused, mida protsess vajab, ja kuna need vĂ€ljavĂ”tted sisaldavad ka mitteauditeeritud sĂŒndmusi, nĂ€eme kĂ”iki mitteauditeeritud kontrolle ja lĂ”puks nĂ”utud Ă”igust, mille auditi lipp (viimane vĂ€ljundis) on seadistatud 1. Meid huvitav vĂ”imalus on CAP_NET_BIND_SERVICE, mis on mÀÀratletud konstandina kernelis allikas koodis failis include/uapi/linux/ability.h identifikaatoriga 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">VĂ”imalusi kasutatakse sageli konteinerite, nagu runC vĂ”i Docker, töö ajal, et need töötaksid privileegita reĆŸiimis, kuid neile lubatakse ainult need vĂ”imalused, mis on vajalikud enamiku rakenduste kĂ€ivitamiseks. Kui rakendusele on vajalikud teatud vĂ”imalused, saab Dockeris need lubada, kasutades --cap-add:
docker run -it --rm --cap-add=NET_ADMIN ubuntu ip link add dummy0 type dummySee kÀsk annab konteinerile vÔimaluse CAP_NET_ADMIN, mis vÔimaldab tal seadistada vÔrgu linki, et lisada dummy0 liides.
JÀrgmises osas on nÀidatud, kuidas kasutada selliseid vÔimalusi nagu filtreerimine, kuid teise meetodi abil, mis vÔimaldab meil oma filtreid programmeerimislikult rakendada.
Seccomp
Seccomp tĂ€hendab Secure Computing, see on turbetase, mis on rakendatud Linuxi tuumas ja vĂ”imaldab arendajatel filtreerida teatud sĂŒsteemikĂ”nesid. Kuigi Seccomp on vĂ”rreldav Linuxi vĂ”imalustega, muudab selle vĂ”ime hallata teatud sĂŒsteemikĂ”nesid selle palju paindlikumaks.
Seccomp ja Linuxi vĂ”imalused ei vĂ€lista ĂŒksteist, neid kasutatakse sageli koos, et saada kasu mĂ”lemast lĂ€henemisviisist. NĂ€iteks vĂ”idakse soovi korral anda protsessile vĂ”imalus CAP_NET_ADMIN, kuid mitte lubada tal vastu vĂ”tta ĂŒhendusi socketi kaudu, blokeerides sĂŒsteemikĂ”ned accept ja accept4.
Seccomp filtreerimise meetod pĂ”hineb BPF filteritel, mis töötavad reĆŸiimis SECCOMP_MODE_FILTER, ning sĂŒsteemikĂ”nede filtreerimine toimub samamoodi nagu pakettide puhul.
Seccomp filtrid laaditakse prctl kasutades operatsiooniga PR_SET_SECCOMP. Need filtrid on BPF programmide kujul, mis kĂ€ivitatakse iga Seccomp paketi jaoks, mis esitatakse seccomp_data struktuuri abil. See struktuur sisaldab arhitektuuri, protsessori kĂ€skluse suunajat sĂŒsteemikĂ”ne ajal ja maksimaalselt kuut sĂŒsteemikĂ”ne argumenti, vĂ€ljendatud kui uint64.
Nii nÀeb vÀlja seccomp_data struktuur Linuxi tuuma allikakoodis failis linux/seccomp.h:
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};Nagu nĂ€ha sellest struktuurist, saame filtreerida sĂŒsteemikĂ”ne, selle argumentide vĂ”i nende kombinatsiooni jĂ€rgi.
PĂ€rast iga paketi vastuvĂ”tmist peab Seccomp filter teostama töötlemise, et teha lĂ”plik otsus ja teavitada tuuma, mida edasi teha. LĂ”plik otsus vĂ€ljendatakse ĂŒhe tagastatud vÀÀrtuse (olekukoodi) kaudu.
â SECCOMP_RET_KILL_PROCESS â kogu protsessi lĂ”petamine vahetult pĂ€rast sĂŒsteemi kĂ”ne filtreerimist, mis seetĂ”ttu ei toimu.
â SECCOMP_RET_KILL_THREAD â praeguse niidi lĂ”petamine vahetult pĂ€rast sĂŒsteemi kĂ”ne filtreerimist, mis seetĂ”ttu ei toimu.
â SECCOMP_RET_KILL â alias SECCOMP_RET_KILL_THREAD, jĂ€etud tagurpidi ĂŒhilduvuse sĂ€ilitamiseks.
â SECCOMP_RET_TRAP â sĂŒsteemi kĂ”ne on keelatud ja signaal SIGSYS (Vale sĂŒsteemi kĂ”ne) saadetakse selle kĂ”ne teinud protsessile.
â SECCOMP_RET_ERRNO â sĂŒsteemi kĂ”ne ei toimu ja osa tagastatavast vÀÀrtusest filtrist SECCOMP_RET_DATA edastatakse kasutajaruumi vÀÀrtusena errno. Olenevalt veast tagastatakse erinevad errno vÀÀrtused. Veanumbrite loetelu on jĂ€rgmises osas.
â SECCOMP_RET_TRACE â kasutatakse ptrace jĂ€lgijale teavitamiseks â PTRACE_O_TRACESECCOMP sĂŒsteemi kĂ”nede pĂŒĂŒdmiseks, et nĂ€ha ja juhtida seda protsessi. Kui jĂ€lgijat ei ole ĂŒhendatud, tagastatakse viga, errno seadistatakse -ENOSYS ja sĂŒsteemi kĂ”ne ei toimu.
â SECCOMP_RET_LOG â sĂŒsteemi kĂ”ne on lubatud ja registreeritud logisse.
â SECCOMP_RET_ALLOW â sĂŒsteemi kĂ”ne on lihtsalt lubatud.
ptrace on sĂŒsteemi kĂ”ne jĂ€lgimismehhanismide rakendamiseks protsessis, mida nimetatakse tracee, vĂ”imaldades jĂ€lgida ja kontrollida protsessi tĂ€itmist. JĂ€lgimisprogramm saab tĂ”husalt mĂ”jutada tĂ€itmist ja muuta tracee mĂ€lu registreid. Seccomp kontekstis kasutatakse ptrace'i, kui kĂ€ivitatakse SECCOMP_RET_TRACE oleku kood, seega vĂ”ib jĂ€lgija takistada sĂŒsteemi kĂ”ne tĂ€itmist ja rakendada oma loogikat.
Seccomp vead
Aeg-ajalt töötades Seccompiga vĂ”ite kokku puutuda erinevate vigadega, mida identifitseeritakse tagastatud vÀÀrtuse SECCOMP_RET_ERRNO tĂŒĂŒbi jĂ€rgi. Vea teatamiseks tagastab sĂŒsteemi kĂ”ne seccomp -1 asemel 0.
JÀrgmised vead on vÔimalikud:
â EACCESS â kutsuvĂ€listel ei ole lubatud sĂŒsteemikĂ”net teha. See toimub tavaliselt seetĂ”ttu, et tal puuduvad CAP_SYS_ADMIN Ă”igused vĂ”i ei ole prctl abil seatud no_new_privs (sellest rÀÀgime hiljem);
â EFAULT â edastatud argumentidel (args struktuuris seccomp_data) ei ole kehtivat aadressi;
â EINVAL â siin vĂ”ib olla neli pĂ”hjust:
- taotletav operatsioon on teadmata vÔi ei toeta tuuma praeguses konfigureerimises;
- mÀÀratud lipud on taotletud operatsiooni jaoks kehtetud;
- operatsioon hĂ”lmab BPF_ABS, kuid mÀÀratletud nihkega on probleeme, mis vĂ”ivad ĂŒletada seccomp_data struktuuri suuruse;
- filtrisse edastatud kĂ€skude arv ĂŒletab maksimaalse;
â ENOMEM â programmiks piisavalt mĂ€lu pole;
â EOPNOTSUPP â operatsioon nĂ€itas, et SECCOMP_GET_ACTION_AVAIL toiming oli saadaval, kuid tuum ei toeta argumentides tagastamist;
â ESRCH â teise niidi sĂŒnkroonimisega tekkis probleem;
â ENOSYS â ei ole jĂ€lgijat, mis oleks seotud SECCOMP_RET_TRACE toiminguga.
prctl on sĂŒsteemikĂ”ne, mis vĂ”imaldab kasutajataseme programmil hallata (seada ja saada) konkreetseid protsessi aspekte, nagu baitide jĂ€rjestus, niitide nimed, kaitstud arvutuskeskkonna reĆŸiim (Seccomp), Ă”igused, Perf sĂŒndmused jne.
Seccomp vĂ”ib tunduda nagu liivakasti tehnoloogia, kuid see ei ole nii. Seccomp on utiliit, mis vĂ”imaldab kasutajatel arendada liivakasti mehhanismi. NĂŒĂŒd vaatame, kuidas luua kasutaja suhtlemisprogramme, kasutades filtreid, mida kutsutakse otse sĂŒsteemikĂ”ne Seccomp kaudu.
BPF Seccomp filtrite nÀide
Siin nĂ€itame, kuidas ĂŒhendada kaks varem arutatud toimingut, nimelt:
â kirjutame Seccomp BPF programmi, mis rakendatakse filtrina erinevate tagastuskoodidega sĂ”ltuvalt vastuvĂ”etud otsustest;
â laadime filtri, kasutades prctl.
Esmalt on vajalikud pealkirjad standardraamatukogust ja Linuxi tuumast:
#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>Enne kui ĂŒritame seda nĂ€idet tĂ€ita, peame veenduma, et tuum on kompileeritud CONFIG_SECCOMP ja CONFIG_SECCOMP_FILTER seadistustega, mis on seadistatud y. Töömasinas saab seda kontrollida jĂ€rgmiselt:
cat /proc/config.gz | zcat | grep -i CONFIG_SECCOMP
Koodi ĂŒlejÀÀnud osa koosneb install_filter funktsioonist, mis jaguneb kaheks osaks. Esimene osa sisaldab meie BPF filtreerimisjuhiseid:
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),
}; Juhiseid seadistatakse BPF_STMT ja BPF_JUMP makrode abil, mis on mÀÀratud failis linux/filter.h.
Vaatame juhiseid ĂŒle.
â BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) â sĂŒsteem laadib ja kogub BPF_LD abil sĂ”naformaadis BPF_W, paketid asuvad fikseeritud nihkega BPF_ABS.
â BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3) â kontrollib BPF_JEQ abil, kas arhitektuuri vÀÀrtus BPF_K akumulaatoris on vĂ”rdselt arch-iga. Kui jah, siis liigub nihkega 0 jĂ€rgmise juhiseni, vastasel juhul, et genereerida viga, hĂŒppab nihkega 3 (antud juhul), kuna arch ei ĂŒhti.
â BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) â laadib ja kogub BPF_LD abil sĂ”naformaadis BPF_W, mis on sĂŒsteemikutsumise number, sisaldudes fikseeritud nihkega BPF_ABS.
â BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) â vĂ”rdleb sĂŒsteemikutsumise numbrit muutuja nr vÀÀrtusega. Kui need on vĂ”rdsed, liigub see jĂ€rgmise juhiseni ja keelab sĂŒsteemikutsumise, vastasel juhul lubab sĂŒsteemikutsumise SECCOMP_RET_ALLOW abil.
â BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)) â lĂ”petab programmi BPF_RET abil ja tekitab viga SECCOMP_RET_ERRNO koos numbriga muutuja err.
â BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) â lĂ”petab programmi BPF_RET abil ja lubab sĂŒsteemikutsumise tĂ€itmise SECCOMP_RET_ALLOW abil.
SECCOMP ON CBPF
VÔib-olla curiositeedist, miks kasutatakse kÀsujuhendi nimekirja, mitte ELF objektkomplekti vÔi C programmid, mis on JIT-ga kompileeritud.Sellel on kaks pÔhjust.
⹠Esiteks rakendab Seccomp cBPF-i (klassikaline BPF), mitte eBPF-i, mis tÀhendab: tal pole registreid, vaid ainult akumulaator viimase arvutustulemuse hoidmiseks, nagu vÔib nÀha nÀites.
⹠Teiseks, Seccomp vÔtab otse BPF-i kÀsu massiivi nÀitaja ja mitte midagi muud. Makrod, mida me kasutasime, aitavad lihtsalt neid kÀske programmeerijatel mugavas vormis nÀidata.
Kui vajate lisabi selle kogumiga arusaamiseks, kaaluge pseudokoodi, mis teeb sama:
if (arch != AUDIT_ARCH_X86_64) {
return SECCOMP_RET_ALLOW;
}
if (nr == __NR_write) {
return SECCOMP_RET_ERRNO;
}
return SECCOMP_RET_ALLOW;PÀrast filtri koodi mÀÀramist socket_filteri struktuuris tuleb mÀÀrata sock_fprog, mis sisaldab koodi ja arvutatud filtri pikkust. See andmestruktuur on vajalik edasiste protsesside kuulutamise argumendina:
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};JĂ€tkub vaid ĂŒks asi, mida teha install_filter funktsioonis â laadida programm ise! Selleks kasutame prctl, vĂ”ttes valikuks PR_SET_SECCOMP, et siseneda kaitstud arvutuste reĆŸiimi. SeejĂ€rel mÀÀrame reĆŸiimile, et laadida filter SECCOMP_MODE_FILTER, mis sisaldub sock_fprog tĂŒĂŒpi muutuja prog sees:
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
perror("prctl(PR_SET_SECCOMP)");
return 1;
}
return 0;
}LÔpuks saame kasutada meie install_filter funktsiooni, kuid enne seda peame kasutama prctl lause PR_SET_NO_NEW_PRIVS seadmiseks jooksva protsessiga, vÀltides seega olukorda, kus alamprotsessidel on rohkem Ôigusi kui vanematel. Samal ajal saame teha jÀrgmisi prctl kutsungeid install_filter funktsioonis, ilma et oleks vaja root Ôigusi.
NĂŒĂŒd saame kutsuda install_filter funktsiooni. Blokeerime kĂ”ik sĂŒsteemi kutsungid write, mis puudutavad X86-64 arhitektuuri, ja anname lihtsalt loa, mis blokeerib kĂ”ik katsed. Filtri seadistamise jĂ€rel jĂ€tkame tĂ€itmist, kasutades esimest argumenti:
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]);
}Alustame. Meie programmi kompileerimiseks vÔime kasutada kas clang vÔi gcc, igal juhul on see lihtsalt main.c faili kompileerimine ilma eriliste valikuteta:
clang main.c -o filter-writeKuidas juba mainitud, oleme blokeerinud kĂ”ik kirjutamised programmis. Selle kontrollimiseks on vajalik programm, mis midagi vĂ€ljundab â ls tundub hea kandidaadina. Niimoodi kĂ€itub ta tavaliselt:
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
SuurepÀrane! Nii nÀeb vÀlja meie kestaprogrammi kasutamine: me edastame lihtsalt programmi, mida soovime testida, esimese argumendina:
.\/filter-write "ls -la"PĂ€rast tĂ€itmist annab see programm tĂ€iesti tĂŒhja vĂ€ljundi. Siiski saame rakendada strace'i, et nĂ€ha, mis juhtub:
strace -f .\/filter-write "ls -la"Tulemused on oluliselt lĂŒhendatud, kuid vastav osa nĂ€itab, et kirjed blokeeritakse EPERM veaga â just see, mille me seadistasime. See tĂ€hendab, et programm ei vĂ€ljasta midagi, kuna ei pÀÀse juurde sĂŒsteemikutsest write:
[pid 25099] write(2, "ls: ", 4) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "write error", 11) = -1 EPERM (Operation not permitted)
[pid 25099] write(2, "n", 1) = -1 EPERM (Operation not permitted)NĂŒĂŒd mĂ”istate, kuidas Seccomp BPF töötab, ja teil on hea ettekujutus sellest, mida selle abil saavutada saab. Kuid kas poleks tore saavutada sama ka eBPF abil, et kasutada selle kogu vĂ”imet?
MĂ”eldes eBPF programmidele, arvavad enamik inimesi, et nad kirjutavad need lihtsalt ja laadivad administraatori Ă”igustega ĂŒles. Kuigi see vĂ€ide on ĂŒldiselt tĂ”si, rakendab kernel erinevatel tasanditel eBPF objektide kaitseks mehanisme. Need mehhanismid on tuntud kui BPF LSM lĂ”ksud.
BPF LSM lÔksud
SĂŒsteemsete sĂŒndmuste arhitektuurist sĂ”ltumatu kontrolli seadmiseks rakendab LSM lĂ”ksude kontseptsiooni. Tehniliselt on lĂ”ksukutse sarnane sĂŒsteemikutsumisega, kuid sĂ”ltumatu sĂŒsteemist ja integreeritud infrastruktuuri. LSM pakub uut kontseptsiooni, mille abstraktsioonitase aitab vĂ€ltida probleeme, mis vĂ”ivad tekkida sĂŒsteemikutsete kĂ€sitlemisel erinevates arhitektuurides.
Raamatute kirjutamise ajal oli kernelil seitse BPF programmidega seotud lĂ”ksu ning SELinux â ainus sisseehitatud LSM, mis neid rakendab.
LÔksude allikakood on paigutatud kernelipuu faili 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);Iga neist kutsutakse vÀlja erinevates tÀitmise etappides:
â security_bpf â teostab esialgse kontrolli tehtud sĂŒsteemikĂ”nede BPF;
â security_bpf_map â kontrollib, kui sĂŒdamik tagastab failideskripti kaardi jaoks;
â security_bpf_prog â kontrollib, kui sĂŒdamik tagastab failideskripti eBPF programmi jaoks;
â security_bpf_map_alloc â kontrollib, kas turvavĂ€li on kaardid BPF sees algatatud;
â security_bpf_map_free â kontrollib, kas turvavĂ€li kaardid BPF sees puhastatakse;
â security_bpf_prog_alloc â kontrollib, kas turvavĂ€li on BPF programmides algatatud;
â security_bpf_prog_free â kontrollib, kas turvavĂ€li BPF programmides puhastatakse.
NĂŒĂŒd, nĂ€hes seda kĂ”ike, mĂ”istame: LSM BPF pĂŒĂŒdmiste idee on see, et need saavad kaitsta igat eBPF objekti, tagades, et ainult need, kellel on vastavad privileegid, saavad kaardid ja programmide ĂŒle teostada toiminguid.
Elulookirjeldus
Turvalisus ei ole midagi, mida saad universaalse viisina rakendada kĂ”igile, mida soovid kaitsta. Oluline on suutlikkus kaitsta sĂŒsteeme erinevatel tasanditel ja erinevate viisidega. Usugu vĂ”i mitte, parim viis sĂŒsteemi turvamiseks on organiseerida erinevad kaitsetasemed erinevatest positsioonidest, et ĂŒhe taseme turvade vĂ€henemine ei lubaks pÀÀseda kogu sĂŒsteemile. SĂŒdamike arendajad on teinud suurepĂ€rast tööd, pakkudes meile erinevaid kihte ja suhtlemispunkte. Me loodame, et oleme andnud teile hea ĂŒlevaate sellest, mis need kihid on ja kuidas kasutada BPF programme nende kĂ€sitlemiseks.
Autoritest
David Calavera on Netlify tehniline direktor. Ta on töötanud Dockeris tugiteenustes ja osalenud Runci, Go ja BCC tööriistade arendamises, samuti muudes avatud lĂ€htekoodiga projektides. Ta on tuntud oma töö eest Dockerite ja Docker-pluginte ökosĂŒsteemi arendamisel. David armastab vĂ€ga flame graph'e ja pĂŒĂŒab alati optimeerida jĂ”udlust.
Lorenzo Fontana töötab Sysdigi tarkvaraarendajate meeskonnas, kus ta tegeleb peamiselt Falco projektiga â Cloud Native Computing Foundation'i algatusega, mis tagab konteinerite kĂ€itamise keskkonna turvalisuse ja anomaaliate tuvastamise lĂ€bi kerneli mooduli ja eBPF-i. Tema huvi on jaotatud sĂŒsteemid, tarkvaraga mÀÀratud vĂ”rgud, Linuxi kerneli ja jĂ”udluse analĂŒĂŒs.
» Raamatuga saab lÀhemalt tutvuda
»
»
Habr kasutajatele on 25% allahindlus kupongi abil â Linux
Paberkoopia eest maksmise korral saadetakse elektrooniline raamat e-posti teel.
Allikas: habr.com
