Bókin "BPF fyrir Linux eftirlit"

Bókin "BPF fyrir Linux eftirlit"Halló, Khabro íbúar! BPF sýndarvélin er einn mikilvægasti hluti Linux kjarnans. Rétt notkun þess mun gera kerfisverkfræðingum kleift að finna galla og leysa jafnvel flóknustu vandamálin. Þú munt læra hvernig á að skrifa forrit sem fylgjast með og breyta hegðun kjarnans, hvernig á að innleiða kóða á öruggan hátt til að fylgjast með atburðum í kjarnanum og margt fleira. David Calavera og Lorenzo Fontana munu hjálpa þér að opna kraft BPF. Auktu þekkingu þína á hagræðingu afkasta, netkerfi, öryggi. - Notaðu BPF til að fylgjast með og breyta hegðun Linux kjarnans. - Sprautaðu kóða til að fylgjast með atburðum kjarna á öruggan hátt án þess að þurfa að endursafna kjarnanum eða endurræsa kerfið. - Notaðu þægileg kóðadæmi í C, Go eða Python. - Taktu stjórn með því að eiga líftíma BPF forritsins.

Linux kjarnaöryggi, eiginleikar þess og Secomp

BPF veitir öfluga leið til að lengja kjarnann án þess að fórna stöðugleika, öryggi eða hraða. Af þessum sökum töldu kjarnahönnuðirnir að það væri góð hugmynd að nota fjölhæfni sína til að bæta ferli einangrun í Seccomp með því að innleiða Seccomp síur sem studdar eru af BPF forritum, einnig þekkt sem Seccomp BPF. Í þessum kafla munum við útskýra hvað Secomp er og hvernig það er notað. Þá munt þú læra hvernig á að skrifa Secomp síur með BPF forritum. Eftir það munum við skoða innbyggðu BPF krókana sem eru innifalin í kjarnanum fyrir Linux öryggiseiningar.

Linux öryggiseiningar (LSM) eru rammi sem býður upp á mengi aðgerða sem hægt er að nota til að útfæra ýmis öryggislíkön á staðlaðan hátt. LSM er hægt að nota beint í kjarnatrénu, eins og Apparmor, SELinux og Tomoyo.

Við skulum byrja á því að ræða möguleika Linux.

Hæfileiki

Kjarninn í getu Linux er sá að þú þarft að veita óforréttindum ferli leyfi til að framkvæma ákveðið verkefni, en án þess að nota suid í þeim tilgangi, eða á annan hátt gera ferlið forréttinda, sem minnkar möguleika á árás og leyfa ferlinu að framkvæma ákveðin verkefni. Til dæmis, ef forritið þitt þarf að opna forréttindagátt, segjum 80, í stað þess að keyra ferlið sem rót, geturðu einfaldlega gefið því CAP_NET_BIND_SERVICE getu.

Íhugaðu Go forrit sem heitir main.go:

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

Þetta forrit þjónar HTTP netþjóni á port 80 (þetta er forréttindahöfn). Venjulega keyrum við það strax eftir samantekt:

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

Hins vegar, þar sem við erum ekki að veita rótarréttindi, mun þessi kóða henda villu þegar tengið er bundið:

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

capsh (skeljastjóri) er tól sem keyrir skel með ákveðnum hæfileikum.

Í þessu tilviki, eins og áður hefur verið nefnt, í stað þess að veita fullan rótarrétt, geturðu virkjað forréttindagáttabindingu með því að bjóða upp á cap_net_bind_service getu ásamt öllu öðru sem er þegar í forritinu. Til að gera þetta getum við sett forritið okkar í 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"

Við skulum skilja þetta lið aðeins.

  • capsh - notaðu capsh sem skel.
  • —caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' - þar sem við þurfum að breyta notandanum (við viljum ekki keyra sem rót), munum við tilgreina cap_net_bind_service og getu til að breyta notandaauðkenni frá rót til enginn, nefnilega cap_setuid og cap_setgid.
  • —keep=1 — við viljum halda uppsettum möguleikum þegar skipt er úr rótarreikningnum.
  • —user=“enginn“ — endanotandinn sem keyrir forritið verður enginn.
  • —addamb=cap_net_bind_service — stilltu hreinsun tengdra getu eftir að skipt er úr rótarstillingu.
  • - -c "./capabilities" - keyrðu bara forritið.

Tengdir eiginleikar eru sérstök tegund af eiginleikum sem erfast af barnaforritum þegar núverandi forrit keyrir þá með execve(). Aðeins hæfileikar sem leyfilegt er að tengja, eða með öðrum orðum, sem umhverfisgetu, er hægt að erfa.

Þú ert líklega að velta fyrir þér hvað +eip þýðir eftir að hafa tilgreint hæfileikann í --caps valkostinum. Þessir fánar eru notaðir til að ákvarða að geta:

-verður að virkja (p);

- laus til notkunar (e);

-geta erft með barnaferlum (i).

Þar sem við viljum nota cap_net_bind_service þurfum við að gera þetta með e-fánanum. Þá byrjum við skelina í skipuninni. Þetta mun keyra getu tvöfaldan og við þurfum að merkja það með i fánanum. Að lokum viljum við að eiginleikinn sé virkur (við gerðum þetta án þess að breyta UID) með bls. Það lítur út eins og cap_net_bind_service+eip.

Þú getur athugað niðurstöðuna með því að nota ss. Við skulum stytta úttakið aðeins til að það passi á síðunni, en það mun sýna tilheyrandi tengi og notandakenni annað en 0, í þessu tilfelli 65:

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

Í þessu dæmi notuðum við capsh, en þú getur skrifað skel með libcap. Fyrir frekari upplýsingar, sjá mann 3 libcap.

Þegar forrit eru skrifuð veit verktaki ekki fyrirfram alla þá eiginleika sem forritið þarfnast á keyrslutíma; Þar að auki geta þessir eiginleikar breyst í nýjum útgáfum.

Til að skilja betur getu forritsins okkar getum við tekið BCC-hæft tólið, sem stillir kprobe fyrir cap_capable kjarnaaðgerðina:

/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ð getum náð því sama með því að nota bpftrace með einlínu kprobe í cap_capable kjarnafallinu:

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

Þetta mun gefa út eitthvað eins og eftirfarandi ef hæfileiki forritsins okkar er virkjaður eftir 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

Fimmti dálkurinn er hæfileikarnir sem ferlið þarfnast, og þar sem þessi framleiðsla inniheldur atburði sem ekki eru endurskoðaðir, sjáum við allar athuganir sem ekki eru endurskoðaðir og loks nauðsynlega getu með endurskoðunarfánann (síðast í úttakinu) stillt á 1. Hæfni. einn sem við höfum áhuga á er CAP_NET_BIND_SERVICE, hann er skilgreindur sem fasti í frumkóða kjarna í skránni include/uapi/linux/ability.h með auðkenni 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">

Möguleikar eru oft virkir á keyrslutíma fyrir gáma eins og runC eða Docker til að leyfa þeim að keyra í óforréttindum, en þeir eru aðeins leyfðir þeir eiginleikar sem þarf til að keyra flest forrit. Þegar forrit krefst ákveðinna getu getur Docker útvegað þeim með því að nota --cap-add:

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

Þessi skipun mun gefa ílátinu CAP_NET_ADMIN getu, sem gerir honum kleift að stilla nettengil til að bæta við dummy0 viðmótinu.

Næsti hluti sýnir hvernig á að nota eiginleika eins og síun, en með því að nota aðra tækni sem gerir okkur kleift að innleiða okkar eigin síur með áætlun.

Secomp

Seccomp stendur fyrir Secure Computing og er öryggislag útfært í Linux kjarnanum sem gerir forriturum kleift að sía ákveðin kerfissímtöl. Þrátt fyrir að Secomp sé sambærilegt við Linux að getu, gerir hæfileiki þess til að stjórna ákveðnum kerfissímtölum það mun sveigjanlegra miðað við þau.

Seccomp og Linux eiginleikar útiloka ekki gagnkvæmt og eru oft notaðir saman til að njóta góðs af báðum aðferðum. Til dæmis gætirðu viljað gefa ferli CAP_NET_ADMIN getu en ekki leyfa því að samþykkja innstungutengingar, sem hindrar samþykki og samþykki4 kerfissímtöl.

Secomp síunaraðferðin byggir á BPF síum sem starfa í SECCOMP_MODE_FILTER ham og síun kerfiskalla er framkvæmd á sama hátt og fyrir pakka.

Seccomp síur eru hlaðnar með prctl í gegnum PR_SET_SECCOMP aðgerðina. Þessar síur eru í formi BPF forrits sem er keyrt fyrir hvern Seccomp pakka sem er táknaður með seccomp_data uppbyggingunni. Þessi uppbygging inniheldur tilvísunararkitektúrinn, vísbendingu um leiðbeiningar örgjörva þegar kerfiskallið var hringt og að hámarki sex kerfiskallarrök, gefin upp sem uint64.

Svona lítur uppbygging secomp_data út úr frumkóða kjarna í linux/seccomp.h skránni:

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

Eins og þú sérð af þessari uppbyggingu getum við síað eftir kerfiskallinu, rökum þess eða samsetningu af hvoru tveggja.

Eftir að hafa fengið hvern Seccomp pakka verður sían að framkvæma vinnslu til að taka endanlega ákvörðun og segja kjarnanum hvað á að gera næst. Endanleg ákvörðun er gefin upp með einu af skilagildunum (stöðukóðum).

- SECCOMP_RET_KILL_PROCESS - drepur allt ferlið strax eftir síun á kerfiskalli sem er ekki keyrt vegna þessa.

- SECCOMP_RET_KILL_THREAD - slítur núverandi þræði strax eftir síun á kerfiskalli sem er ekki keyrt vegna þessa.

— SECCOMP_RET_KILL — samnefni fyrir SECCOMP_RET_KILL_THREAD, vinstri fyrir afturábak eindrægni.

- SECCOMP_RET_TRAP - kerfiskallið er bannað og SIGSYS (Bad System Call) merki er sent til verkefnisins sem kallar það.

- SECCOMP_RET_ERRNO - Kerfiskallið er ekki keyrt og hluti af SECCOMP_RET_DATA síuskilgildinu er sendur til notendarýmis sem errno gildi. Það fer eftir orsök villunnar, mismunandi villugildum er skilað. Listi yfir villunúmer er að finna í næsta kafla.

- SECCOMP_RET_TRACE - Notað til að láta ptrace rekjandann vita með því að nota - PTRACE_O_TRACESECCOMP til að stöðva þegar kerfiskall er keyrt til að sjá og stjórna því ferli. Ef rekjaefni er ekki tengt er villa skilað, errno er stillt á -ENOSYS og kerfiskallið er ekki keyrt.

- SECCOMP_RET_LOG - kerfiskallið er leyst og skráð.

- SECCOMP_RET_ALLOW - kerfiskallið er einfaldlega leyfilegt.

ptrace er kerfiskall til að innleiða rakningarkerfi í ferli sem kallast tracee, með getu til að fylgjast með og stjórna framkvæmd ferlisins. Rekjaforritið getur í raun haft áhrif á framkvæmdina og breytt minnisskrám rekjandans. Í Secomp samhenginu er ptrace notað þegar það er kveikt af SECCOMP_RET_TRACE stöðukóðanum, svo rekjandann getur komið í veg fyrir að kerfiskallið keyrir og innleiðir sína eigin rökfræði.

Seccomp villur

Af og til, meðan þú vinnur með Seccomp, muntu lenda í ýmsum villum, sem auðkenndar eru með skilgildi af gerðinni SECCOMP_RET_ERRNO. Til að tilkynna villu mun seccomp kerfiskallið skila -1 í stað 0.

Eftirfarandi villur eru mögulegar:

- AÐGANGUR - Sá sem hringir má ekki hringja kerfissímtal. Þetta gerist venjulega vegna þess að það hefur ekki CAP_SYS_ADMIN réttindi eða no_new_privs er ekki stillt með prctl (við munum tala um þetta síðar);

— EFAULT — færðu rökin (args í seccomp_data uppbyggingunni) hafa ekki gilt heimilisfang;

— EINVAL — það geta verið fjórar ástæður hér:

-umbeðin aðgerð er óþekkt eða ekki studd af kjarnanum í núverandi uppsetningu;

-tilgreindir fánar eru ekki gildir fyrir umbeðna aðgerð;

-aðgerð felur í sér BPF_ABS, en það eru vandamál með tilgreint offset, sem getur farið yfir stærð seccomp_data uppbyggingu;

-fjöldi leiðbeininga sem sendar eru til síunnar fer yfir hámarkið;

— ENOMEM — ekki nóg minni til að keyra forritið;

- EOPNOTSUPP - aðgerðin gaf til kynna að með SECCOMP_GET_ACTION_AVAIL væri aðgerðin tiltæk, en kjarninn styður ekki skil í rökum;

— ESRCH — vandamál kom upp við samstillingu annars straums;

- ENOSYS - Það er engin rekjamerki tengd við SECCOMP_RET_TRACE aðgerðina.

prctl er kerfiskall sem gerir notendarýmisforriti kleift að vinna (stilla og fá) tiltekna þætti ferlis, svo sem endian bæti, þráðanöfn, örugga útreikningsham (Seccomp), forréttindi, Perf atburði osfrv.

Secomp kann að virðast eins og sandkassatækni fyrir þig, en það er það ekki. Secomp er tól sem gerir notendum kleift að þróa sandkassakerfi. Nú skulum við skoða hvernig notendasamskiptaforrit eru búin til með því að nota síu sem kallað er beint af Secommp kerfiskallinu.

BPF Secomp síudæmi

Hér munum við sýna hvernig á að sameina þessar tvær aðgerðir sem ræddar voru áðan, þ.e.

— við munum skrifa Seccomp BPF forrit, sem verður notað sem sía með mismunandi skilakóðum eftir ákvörðunum sem teknar eru;

— hlaðið síunni með prctl.

Fyrst þarftu hausa frá venjulegu bókasafninu og Linux kjarnanum:

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

Áður en við reynum þetta dæmi verðum við að tryggja að kjarninn sé settur saman með CONFIG_SECCOMP og CONFIG_SECCOMP_FILTER stillt á y. Á vinnandi vél geturðu athugað þetta svona:

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

Restin af kóðanum er tveggja hluta install_filter aðgerð. Fyrsti hlutinn inniheldur lista okkar yfir BPF síunarleiðbeiningar:

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

Leiðbeiningarnar eru stilltar með BPF_STMT og BPF_JUMP fjölva sem eru skilgreind í linux/filter.h skránni.
Við skulum fara í gegnum leiðbeiningarnar.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, arch))) - kerfið hleður og safnast upp frá BPF_LD í formi orðsins BPF_W, pakkagögn eru staðsett á föstum offset BPF_ABS.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, bogi, 0, 3) - athugar með því að nota BPF_JEQ hvort arkitektúrgildið í safnfastanum BPF_K sé jafnt boga. Ef svo er, hoppar við offset 0 í næstu leiðbeiningar, annars hoppar við offset 3 (í þessu tilfelli) til að kasta villu vegna þess að boginn passar ekki.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Hleður og safnast upp úr BPF_LD í formi orðsins BPF_W, sem er kerfissímtalsnúmerið sem er í fasta offsetinu á BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — ber saman kerfissímtalsnúmerið við gildi nr breytunnar. Ef þeir eru jafnir, heldur áfram í næstu leiðbeiningar og gerir kerfiskallið óvirkt, annars leyfir kerfiskallið með SECCOMP_RET_ALLOW.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (villa & SECCOMP_RET_DATA)) - lýkur forritinu með BPF_RET og veldur þar af leiðandi villu SECCOMP_RET_ERRNO með tölunni frá villubreytunni.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - lýkur forritinu með BPF_RET og gerir kleift að keyra kerfiskallið með því að nota SECCOMP_RET_ALLOW.

SECCOMP ER CBPF
Þú gætir verið að velta fyrir þér hvers vegna listi yfir leiðbeiningar er notaður í stað samsetts ELF-hluts eða JIT-samsetts C-forrits.

Það eru tvær ástæður fyrir þessu.

• Í fyrsta lagi notar Seccomp cBPF (klassískt BPF) en ekki eBPF, sem þýðir: það hefur enga skrá, heldur aðeins safn til að geyma síðustu útreikningsniðurstöðu, eins og sést á dæminu.

• Í öðru lagi samþykkir Secomp bendilinn á fjölda BPF leiðbeininga beint og ekkert annað. Fjölvi sem við höfum notað hjálpa einfaldlega að tilgreina þessar leiðbeiningar á forritaravænan hátt.

Ef þú þarft meiri hjálp við að skilja þessa samsetningu skaltu íhuga gervikóðann sem gerir það sama:

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

Eftir að hafa skilgreint síukóðann í socket_filter uppbyggingunni þarftu að skilgreina sock_fprog sem inniheldur kóðann og reiknaða lengd síunnar. Þessi gagnauppbygging er nauðsynleg sem rök fyrir því að lýsa því yfir að ferlið gangi síðar:

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

Það er aðeins eitt eftir að gera í install_filter aðgerðinni - hlaða forritinu sjálfu! Til að gera þetta notum við prctl og tökum PR_SET_SECCOMP sem valmöguleika til að fara í örugga tölvuham. Síðan segjum við stillingunni að hlaða síunni með SECCOMP_MODE_FILTER, sem er að finna í prog breytunni af gerðinni sock_fprog:

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

Að lokum getum við notað install_filter aðgerðina okkar, en áður en það gerist þurfum við að nota prctl til að stilla PR_SET_NO_NEW_PRIVS fyrir núverandi framkvæmd og forðast þannig aðstæður þar sem barnaferli fá meiri réttindi en foreldrar þeirra. Með þessu getum við gert eftirfarandi prctl símtöl í install_filter aðgerðinni án þess að hafa rótarréttindi.

Nú getum við kallað install_filter aðgerðina. Við skulum loka á öll skrifkerfissímtöl sem tengjast X86-64 arkitektúrnum og gefa einfaldlega leyfi sem lokar fyrir allar tilraunir. Eftir að sían hefur verið sett upp höldum við áfram að keyra með því að nota fyrstu rökin:

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

Byrjum. Til að setja saman forritið okkar getum við notað annað hvort clang eða gcc, hvort sem er er það bara að setja saman main.c skrána án sérstakra valkosta:

clang main.c -o filter-write

Eins og fram hefur komið höfum við lokað á allar færslur í forritinu. Til að prófa þetta þarftu forrit sem gefur frá sér eitthvað - það virðist vera góður frambjóðandi. Svona hagar hún sér venjulega:

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

Dásamlegt! Svona lítur það út að nota umbúðaforritið okkar: Við sendum einfaldlega forritið sem við viljum prófa sem fyrstu rök:

./filter-write "ls -la"

Þegar það er keyrt framleiðir þetta forrit alveg tómt úttak. Hins vegar getum við notað strace til að sjá hvað er að gerast:

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

Niðurstaða vinnunnar styttist mjög, en samsvarandi hluti hennar sýnir að færslur eru læstar með EPERM villunni - sömu og við stilltum. Þetta þýðir að forritið gefur ekki út neitt vegna þess að það hefur ekki aðgang að skrifakerfiskallinu:

[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ú skilurðu hvernig Secomp BPF virkar og hefur góða hugmynd um hvað þú getur gert við það. En myndirðu ekki vilja ná því sama með eBPF í stað cBPF til að nýta fullan kraft sinn?

Þegar þeir hugsa um eBPF forrit, halda flestir að þeir einfaldlega skrifi þau og hleðji þeim stjórnandaréttindum. Þó að þessi fullyrðing sé almennt sönn, innleiðir kjarninn safn aðferða til að vernda eBPF hluti á ýmsum stigum. Þessir aðferðir eru kallaðar BPF LSM gildrur.

BPF LSM gildrur

Til að veita arkitektúr-óháða eftirlit með kerfisatburðum, innleiðir LSM hugmyndina um gildrur. Hook call er tæknilega svipað kerfissímtali, en er kerfisóháð og samþætt innviðum. LSM býður upp á nýtt hugtak þar sem abstraktlag getur hjálpað til við að forðast vandamál sem upp koma þegar tekist er á við kerfiskall á mismunandi arkitektúr.

Þegar þetta er skrifað hefur kjarninn sjö króka sem tengjast BPF forritum og SELinux er eini innbyggði LSM sem útfærir þá.

Kóðinn fyrir gildrurnar er staðsettur í kjarnatrénu í skránni 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 þeirra verður kölluð á mismunandi stigum aftöku:

— security_bpf — framkvæmir fyrstu athugun á keyrðum BPF kerfissímtölum;

- security_bpf_map - athugar hvenær kjarninn skilar skráarlýsingu fyrir kortið;

- security_bpf_prog - athugar hvenær kjarninn skilar skráarlýsingu fyrir eBPF forritið;

— security_bpf_map_alloc — athugar hvort öryggisreiturinn inni í BPF kortum sé frumstilltur;

- security_bpf_map_free - athugar hvort öryggisreiturinn sé hreinsaður inni í BPF kortum;

— security_bpf_prog_alloc — athugar hvort öryggisreiturinn sé frumstilltur inni í BPF forritum;

- security_bpf_prog_free - athugar hvort öryggisreiturinn sé hreinsaður inni í BPF forritum.

Núna, þegar við sjáum þetta allt, skiljum við: Hugmyndin á bak við LSM BPF hlerana er að þeir geti veitt vernd fyrir hvern eBPF hlut og tryggt að aðeins þeir sem hafa viðeigandi réttindi geti framkvæmt aðgerðir á kortum og forritum.

Yfirlit

Öryggi er ekki eitthvað sem þú getur innleitt í einu lagi fyrir allt sem þú vilt vernda. Mikilvægt er að geta verndað kerfi á mismunandi stigum og á mismunandi hátt. Trúðu það eða ekki, besta leiðin til að tryggja kerfi er að skipuleggja mismunandi verndarstig frá mismunandi stöðum, þannig að það að draga úr öryggi eins stigs leyfir ekki aðgang að öllu kerfinu. Kjarnahönnuðirnir hafa unnið frábært starf við að gefa okkur sett af mismunandi lögum og snertipunktum. Við vonum að við höfum gefið þér góðan skilning á því hvað lög eru og hvernig á að nota BPF forrit til að vinna með þau.

Um höfunda

David Calavera er tæknistjóri hjá Netlify. Hann vann í Docker stuðningi og lagði sitt af mörkum til þróunar á Runc, Go og BCC verkfærum, auk annarra opinna verkefna. Þekktur fyrir vinnu sína við Docker verkefni og þróun á Docker viðbót vistkerfisins. David er mjög ástríðufullur um logagrafík og er alltaf að leitast við að hámarka frammistöðu.

Lorenzo Fontana vinnur í opna uppspretta teyminu hjá Sysdig, þar sem hann einbeitir sér fyrst og fremst að Falco, Cloud Native Computing Foundation verkefni sem veitir gámakeyrsluöryggi og fráviksgreiningu í gegnum kjarnaeiningu og eBPF. Hann hefur brennandi áhuga á dreifðum kerfum, hugbúnaðarskilgreindum netkerfum, Linux kjarnanum og frammistöðugreiningu.

» Nánari upplýsingar um bókina má finna á heimasíðu útgefanda
» efnisyfirlit
» Útdráttur

Fyrir Khabrozhiteley 25% afslátt með afsláttarmiða - Linux

Við greiðslu á pappírsútgáfu bókarinnar er rafbók send með tölvupósti.

Heimild: www.habr.com

Bæta við athugasemd