Archebwch "BPF ar gyfer Monitro Linux"

Archebwch "BPF ar gyfer Monitro Linux"Helo, drigolion Khabro! Mae'r peiriant rhithwir BPF yn un o gydrannau pwysicaf y cnewyllyn Linux. Bydd ei ddefnydd priodol yn caniatáu i beirianwyr system ddod o hyd i ddiffygion a datrys hyd yn oed y problemau mwyaf cymhleth. Byddwch yn dysgu sut i ysgrifennu rhaglenni sy'n monitro ac yn addasu ymddygiad y cnewyllyn, sut i weithredu cod yn ddiogel i fonitro digwyddiadau yn y cnewyllyn, a llawer mwy. Bydd David Calavera a Lorenzo Fontana yn eich helpu i ddatgloi pŵer BPF. Ehangwch eich gwybodaeth am optimeiddio perfformiad, rhwydweithio, diogelwch. - Defnyddiwch BPF i fonitro ac addasu ymddygiad y cnewyllyn Linux. - Chwistrellu cod i fonitro digwyddiadau cnewyllyn yn ddiogel heb orfod ail-grynhoi'r cnewyllyn neu ailgychwyn y system. — Defnyddiwch enghreifftiau cod cyfleus yn C, Go neu Python. - Cymryd rheolaeth trwy fod yn berchen ar gylch oes rhaglen BPF.

Diogelwch Cnewyllyn Linux, Ei Nodweddion a Seccomp

Mae BPF yn darparu ffordd bwerus i ymestyn y cnewyllyn heb aberthu sefydlogrwydd, diogelwch na chyflymder. Am y rheswm hwn, roedd y datblygwyr cnewyllyn yn meddwl y byddai'n syniad da defnyddio ei amlbwrpasedd i wella ynysu prosesau yn Seccomp trwy weithredu hidlwyr Seccomp a gefnogir gan raglenni BPF, a elwir hefyd yn Seccomp BPF. Yn y bennod hon byddwn yn egluro beth yw Seccomp a sut y caiff ei ddefnyddio. Yna byddwch chi'n dysgu sut i ysgrifennu hidlwyr Seccomp gan ddefnyddio rhaglenni BPF. Ar ôl hynny, byddwn yn edrych ar y bachau BPF adeiledig sydd wedi'u cynnwys yn y cnewyllyn ar gyfer modiwlau diogelwch Linux.

Mae Modiwlau Diogelwch Linux (LSM) yn fframwaith sy'n darparu set o swyddogaethau y gellir eu defnyddio i weithredu modelau diogelwch amrywiol mewn modd safonol. Gellir defnyddio LSM yn uniongyrchol yn y goeden ffynhonnell cnewyllyn, fel Apparmor, SELinux a Tomoyo.

Gadewch i ni ddechrau trwy drafod galluoedd Linux.

Galluoedd

Hanfod galluoedd Linux yw bod angen i chi roi caniatâd proses ddi-freintiedig i gyflawni tasg benodol, ond heb ddefnyddio suid at y diben hwnnw, neu wneud y broses yn freintiedig fel arall, gan leihau'r posibilrwydd o ymosodiad a chaniatáu i'r broses gyflawni tasgau penodol. Er enghraifft, os oes angen i'ch cais agor porthladd breintiedig, dyweder 80, yn hytrach na rhedeg y broses fel gwraidd, gallwch chi roi'r gallu CAP_NET_BIND_SERVICE iddo.

Ystyriwch raglen Go o'r enw main.go:

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

Mae'r rhaglen hon yn gwasanaethu gweinydd HTTP ar borthladd 80 (mae hwn yn borthladd breintiedig). Fel arfer rydym yn ei redeg yn syth ar ôl ei lunio:

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

Fodd bynnag, gan nad ydym yn rhoi breintiau gwraidd, bydd y cod hwn yn taflu gwall wrth rwymo'r porthladd:

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

Mae capsh (rheolwr cragen) yn offeryn sy'n rhedeg cragen gyda set benodol o alluoedd.

Yn yr achos hwn, fel y crybwyllwyd eisoes, yn lle rhoi hawliau gwraidd llawn, gallwch chi alluogi rhwymiad porthladd breintiedig trwy ddarparu'r gallu cap_net_bind_service ynghyd â phopeth arall sydd eisoes yn y rhaglen. I wneud hyn, gallwn amgáu ein rhaglen mewn 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"

Gadewch i ni ddeall y tîm hwn ychydig.

  • capsh - defnyddiwch capsh fel cragen.
  • —caps='cap_net_bind_service+eip cap_setpcap, cap_setuid, cap_setgid+ep' - gan fod angen i ni newid y defnyddiwr (nid ydym am redeg fel gwraidd), byddwn yn nodi cap_net_bind_service a'r gallu i newid yr ID defnyddiwr o gwraidd i neb, sef cap_setuid a cap_setgid.
  • —keep=1 — rydym am gadw'r galluoedd gosodedig wrth newid o'r cyfrif gwraidd.
  • —user="neb" — ni fydd y defnyddiwr terfynol sy'n rhedeg y rhaglen yn neb.
  • —addamb=cap_net_bind_service — gosodwch glirio galluoedd cysylltiedig ar ôl newid o'r modd gwraidd.
  • - -c "./capabilities" - rhedeg y rhaglen yn unig.

Mae galluoedd cysylltiedig yn fath arbennig o alluoedd sy'n cael eu hetifeddu gan raglenni plant pan fydd y rhaglen gyfredol yn eu gweithredu gan ddefnyddio execve (). Dim ond galluoedd y caniateir eu cysylltu, neu mewn geiriau eraill, fel galluoedd amgylchedd, a all gael eu hetifeddu.

Mae'n debyg eich bod yn pendroni beth mae +eip yn ei olygu ar ôl nodi'r gallu yn yr opsiwn --caps. Defnyddir y baneri hyn i benderfynu bod y gallu:

-rhaid ei actifadu (p);

-ar gael i'w ddefnyddio (e);

-gellir ei etifeddu gan brosesau plentyn (i).

Gan ein bod ni eisiau defnyddio cap_net_bind_service, mae angen i ni wneud hyn gyda'r e-faner. Yna byddwn yn cychwyn y gragen yn y gorchymyn. Bydd hyn yn rhedeg y galluoedd deuaidd ac mae angen i ni ei farcio gyda baner i. Yn olaf, rydym am i'r nodwedd gael ei galluogi (gwnaethom hyn heb newid yr UID) gyda t. Mae'n edrych fel cap_net_bind_service+eip.

Gallwch wirio'r canlyniad gan ddefnyddio ss. Gadewch i ni fyrhau'r allbwn ychydig i ffitio ar y dudalen, ond bydd yn dangos y porthladd cysylltiedig a'r ID defnyddiwr heblaw 0, yn yr achos hwn 65:

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

Yn yr enghraifft hon fe wnaethom ddefnyddio capsh, ond gallwch chi ysgrifennu cragen gan ddefnyddio libcap. Am ragor o wybodaeth, gweler dyn 3 libcap.

Wrth ysgrifennu rhaglenni, yn aml nid yw'r datblygwr yn gwybod ymlaen llaw yr holl nodweddion sydd eu hangen ar y rhaglen ar amser rhedeg; Ar ben hynny, gall y nodweddion hyn newid mewn fersiynau newydd.

Er mwyn deall galluoedd ein rhaglen yn well, gallwn gymryd yr offeryn gallu BCC, sy'n gosod y kprobe ar gyfer y swyddogaeth cnewyllyn 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 1

Gallwn gyflawni'r un peth trwy ddefnyddio bpftrace gyda kprobe un-leinin yn y swyddogaeth cnewyllyn 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

Bydd hyn yn allbynnu rhywbeth fel y canlynol os yw galluoedd ein rhaglen yn cael eu galluogi ar ôl 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

Y bumed golofn yw'r galluoedd sydd eu hangen ar y broses, a chan fod yr allbwn hwn yn cynnwys digwyddiadau nad ydynt yn rhai archwilio, gwelwn yr holl wiriadau nad ydynt yn rhai archwilio ac yn olaf y gallu gofynnol gyda'r faner archwilio (yn olaf yn yr allbwn) wedi'i gosod i 1. Gallu Y un y mae gennym ddiddordeb ynddo yw CAP_NET_BIND_SERVICE, fe'i diffinnir fel cysonyn yn y cod ffynhonnell cnewyllyn yn y ffeil cynnwys/uapi/linux/ability.h gyda dynodwr 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">

Mae galluoedd yn aml yn cael eu galluogi ar amser rhedeg ar gyfer cynwysyddion fel runC neu Docker i'w galluogi i redeg mewn modd di-freintiedig, ond dim ond y galluoedd sydd eu hangen i redeg y mwyafrif o gymwysiadau y caniateir iddynt. Pan fydd angen galluoedd penodol ar raglen, gall Docker eu darparu gan ddefnyddio --cap-add:

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

Bydd y gorchymyn hwn yn rhoi'r gallu CAP_NET_ADMIN i'r cynhwysydd, gan ganiatáu iddo ffurfweddu cyswllt rhwydwaith i ychwanegu'r rhyngwyneb dymmy0.

Mae'r adran nesaf yn dangos sut i ddefnyddio nodweddion fel hidlo, ond gan ddefnyddio techneg wahanol sy'n ein galluogi i weithredu ein hidlwyr ein hunain yn rhaglennol.

Seccomp

Ystyr Seccomp yw Cyfrifiadura Diogel ac mae'n haen ddiogelwch a weithredir yn y cnewyllyn Linux sy'n caniatáu i ddatblygwyr hidlo rhai galwadau system. Er bod Seccomp yn debyg o ran galluoedd i Linux, mae ei allu i reoli rhai galwadau system yn ei gwneud yn llawer mwy hyblyg o'i gymharu â nhw.

Nid yw nodweddion Seccomp a Linux yn annibynnol ar ei gilydd ac fe'u defnyddir yn aml gyda'i gilydd i elwa o'r ddau ddull. Er enghraifft, efallai y byddwch am roi'r gallu CAP_NET_ADMIN i broses ond peidio â chaniatáu iddi dderbyn cysylltiadau soced, gan rwystro'r derbyn a derbyn4 galwadau system.

Mae'r dull hidlo Seccomp yn seiliedig ar hidlwyr BPF sy'n gweithredu yn y modd SECCOMP_MODE_FILTER, ac mae hidlo galwadau system yn cael ei berfformio yn yr un modd ag ar gyfer pecynnau.

Mae hidlwyr Seccomp yn cael eu llwytho gan ddefnyddio prctl trwy'r gweithrediad PR_SET_SECCOMP. Mae'r hidlwyr hyn ar ffurf rhaglen BPF a weithredir ar gyfer pob pecyn Seccomp a gynrychiolir gan y strwythur seccomp_data. Mae'r strwythur hwn yn cynnwys y saernïaeth gyfeirio, pwyntydd i gyfarwyddiadau prosesydd ar adeg yr alwad system, ac uchafswm o chwe dadl galwad system, wedi'u mynegi fel uint64.

Dyma sut olwg sydd ar y strwythur seccomp_data o'r cod ffynhonnell cnewyllyn yn y ffeil linux/seccomp.h:

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

Fel y gwelwch o'r strwythur hwn, gallwn hidlo yn ôl galwad y system, ei ddadleuon, neu gyfuniad o'r ddau.

Ar ôl derbyn pob pecyn Seccomp, rhaid i'r hidlydd berfformio prosesu i wneud penderfyniad terfynol a dweud wrth y cnewyllyn beth i'w wneud nesaf. Mynegir y penderfyniad terfynol gan un o'r gwerthoedd dychwelyd (codau statws).

- SECCOMP_RET_KILL_PROCESS - yn lladd y broses gyfan yn syth ar ôl hidlo galwad system nad yw'n cael ei weithredu oherwydd hyn.

- SECCOMP_RET_KILL_THREAD - yn terfynu'r edefyn cyfredol yn syth ar ôl hidlo galwad system nad yw'n cael ei weithredu oherwydd hyn.

— SECCOMP_RET_KILL — alias ar gyfer SECCOMP_RET_KILL_THREAD, wedi'i adael ar gyfer cydweddoldeb yn ôl.

- SECCOMP_RET_TRAP - gwaherddir galwad system, ac anfonir signal SIGSYS (Galwad System Drwg) i'r dasg sy'n ei alw.

- SECCOMP_RET_ERRNO - Nid yw'r alwad system yn cael ei gweithredu, ac mae rhan o werth dychwelyd hidlydd SECCOMP_RET_DATA yn cael ei drosglwyddo i ofod defnyddiwr fel y gwerth errno. Yn dibynnu ar achos y gwall, dychwelir gwahanol werthoedd errno. Darperir rhestr o rifau gwall yn yr adran nesaf.

- SECCOMP_RET_TRACE - Fe'i defnyddir i hysbysu'r olrhain ptrace gan ddefnyddio - PTRACE_O_TRACESECCOMP i ryng-gipio pan weithredir galwad system i weld a rheoli'r broses honno. Os nad yw olrheiniwr wedi'i gysylltu, dychwelir gwall, gosodir errno i -ENOSYS, ac ni weithredir galwad y system.

- SECCOMP_RET_LOG - mae'r alwad system wedi'i datrys a'i chofnodi.

- SECCOMP_RET_ALLOW - yn syml, caniateir galwad system.

Mae ptrace yn alwad system i weithredu mecanweithiau olrhain mewn proses o'r enw tracee, gyda'r gallu i fonitro a rheoli gweithrediad y broses. Gall y rhaglen olrhain ddylanwadu'n effeithiol ar weithrediad ac addasu cofrestrau cof tracee. Yng nghyd-destun Seccomp, defnyddir ptrace pan gaiff ei sbarduno gan god statws SECCOMP_RET_TRACE, felly gall yr olrheiniwr atal galwad y system rhag gweithredu a gweithredu ei resymeg ei hun.

Gwallau Seccomp

O bryd i'w gilydd, wrth weithio gyda Seccomp, byddwch yn dod ar draws gwallau amrywiol, sy'n cael eu nodi gan werth dychwelyd o'r math SECCOMP_RET_ERRNO. I riportio gwall, bydd galwad y system seccomp yn dychwelyd -1 yn lle 0.

Mae'r gwallau canlynol yn bosibl:

- HYFFORDDIANT - Ni chaniateir i'r galwr wneud galwad system. Mae hyn fel arfer yn digwydd oherwydd nad oes ganddo breintiau CAP_SYS_ADMIN neu nid yw no_new_privs wedi'i osod gan ddefnyddio prctl (byddwn yn siarad am hyn yn nes ymlaen);

— EFAULT — nid oes gan y dadleuon a basiwyd (args yn y strwythur seccomp_data) gyfeiriad dilys;

- EINVAL - gall fod pedwar rheswm yma:

-mae'r gweithrediad y gofynnwyd amdano yn anhysbys neu heb ei gefnogi gan y cnewyllyn yn y ffurfweddiad cyfredol;

- nid yw'r baneri penodedig yn ddilys ar gyfer y gweithrediad y gofynnwyd amdano;

-operation yn cynnwys BPF_ABS, ond mae problemau gyda'r gwrthbwyso penodedig, a all fod yn fwy na maint y strwythur seccomp_data;

- mae nifer y cyfarwyddiadau a drosglwyddir i'r hidlydd yn fwy na'r uchafswm;

— ENOMEM - dim digon o gof i weithredu'r rhaglen;

- EOPNOTSUPP - dangosodd y gweithrediad fod y weithred ar gael gyda SECCOMP_GET_ACTION_AVAIL, ond nid yw'r cnewyllyn yn cefnogi dychweliadau mewn dadleuon;

— ESRCH — digwyddodd problem wrth gydamseru ffrwd arall;

- ENOSYS - Nid oes unrhyw olrheiniwr ynghlwm wrth y weithred SECCOMP_RET_TRACE.

Mae prctl yn alwad system sy'n caniatáu i raglen gofod defnyddiwr drin (gosod a chael) agweddau penodol ar broses, megis dycnwch beit, enwau edau, modd cyfrifiannu diogel (Seccomp), breintiau, digwyddiadau Perf, ac ati.

Efallai y bydd Seccomp yn ymddangos fel technoleg blwch tywod i chi, ond nid yw. Cyfleustodau yw Seccomp sy'n galluogi defnyddwyr i ddatblygu mecanwaith blwch tywod. Nawr, gadewch i ni edrych ar sut mae rhaglenni rhyngweithio defnyddwyr yn cael eu creu gan ddefnyddio hidlydd a elwir yn uniongyrchol gan alwad system Seccomp.

Enghraifft Hidlo Seccomp BPF

Yma byddwn yn dangos sut i gyfuno'r ddau gam gweithredu a drafodwyd yn gynharach, sef:

— byddwn yn ysgrifennu rhaglen Seccomp BPF, a fydd yn cael ei defnyddio fel hidlydd gyda chodau dychwelyd gwahanol yn dibynnu ar y penderfyniadau a wneir;

— llwythwch yr hidlydd gan ddefnyddio prctl.

Yn gyntaf mae angen penawdau arnoch o'r llyfrgell safonol a'r cnewyllyn Linux:

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

Cyn rhoi cynnig ar yr enghraifft hon, rhaid i ni sicrhau bod y cnewyllyn yn cael ei lunio gyda CONFIG_SECCOMP a CONFIG_SECCOMP_FILTER set i y. Ar beiriant gweithio gallwch wirio hyn fel hyn:

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

Mae gweddill y cod yn swyddogaeth install_filter dwy ran. Mae'r rhan gyntaf yn cynnwys ein rhestr o gyfarwyddiadau hidlo BPF:

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

Gosodir y cyfarwyddiadau gan ddefnyddio'r macros BPF_STMT a BPF_JUMP a ddiffinnir yn y ffeil linux/filter.h.
Gadewch i ni fynd drwy'r cyfarwyddiadau.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, bwa)))) - mae'r system yn llwytho ac yn cronni o BPF_LD ar ffurf y gair BPF_W, mae data pecyn wedi'i leoli ar wrthbwyso sefydlog BPF_ABS.

- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, bwa, 0, 3) - gwirio gan ddefnyddio BPF_JEQ a yw gwerth pensaernïaeth yn y cysonyn cronadur BPF_K yn hafal i bwa. Os felly, mae'n neidio ar wrthbwyso 0 i'r cyfarwyddyd nesaf, fel arall yn neidio ar wrthbwyso 3 (yn yr achos hwn) i daflu gwall oherwydd nad yw bwa yn cyfateb.

- BPF_STMT(BPF_LD + BPF_W + BPF_ABS (offsetof(struct seccomp_data, nr))) - Yn llwytho ac yn cronni o BPF_LD ar ffurf y gair BPF_W, sef rhif galwad y system sydd wedi'i gynnwys yn y gwrthbwyso sefydlog o BPF_ABS.

— BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1) — yn cymharu rhif galwad y system â gwerth y newidyn nr. Os ydynt yn gyfartal, yn symud ymlaen i'r cyfarwyddyd nesaf ac yn analluogi'r alwad system, fel arall yn caniatáu galwad system gyda SECCOMP_RET_ALLOW.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (gwall & SECCOMP_RET_DATA)) - yn terfynu'r rhaglen gyda BPF_RET ac o ganlyniad yn cynhyrchu gwall SECCOMP_RET_ERRNO gyda'r rhif o'r newidyn gwall.

- BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) - yn terfynu'r rhaglen gyda BPF_RET ac yn caniatáu i'r alwad system gael ei gweithredu gan ddefnyddio SECCOMP_RET_ALLOW.

SECCOMP YN CBPF
Efallai eich bod yn pendroni pam y defnyddir rhestr o gyfarwyddiadau yn lle gwrthrych ELF wedi'i lunio neu raglen C a luniwyd gan JIT.

Mae dau reswm am hyn.

• Yn gyntaf, mae Seccomp yn defnyddio cBPF (BPF clasurol) ac nid eBPF, sy'n golygu: nid oes ganddo gofrestrau, ond dim ond cronadur i storio canlyniad y cyfrifiad olaf, fel y gwelir yn yr enghraifft.

• Yn ail, mae Seccomp yn derbyn pwyntydd i amrywiaeth o gyfarwyddiadau BPF yn uniongyrchol a dim byd arall. Mae'r macros rydyn ni wedi'u defnyddio yn helpu i nodi'r cyfarwyddiadau hyn mewn ffordd sy'n gyfeillgar i raglenwyr.

Os oes angen mwy o help arnoch i ddeall y gwasanaeth hwn, ystyriwch y ffuggod sy'n gwneud yr un peth:

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

Ar ôl diffinio'r cod hidlo yn y strwythur socket_filter, mae angen i chi ddiffinio sock_fprog sy'n cynnwys y cod a hyd yr hidlydd a gyfrifwyd. Mae angen y strwythur data hwn fel dadl dros ddatgan bod y broses yn rhedeg yn ddiweddarach:

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

Dim ond un peth sydd ar ôl i'w wneud yn y swyddogaeth install_filter - llwythwch y rhaglen ei hun! I wneud hyn, rydym yn defnyddio prctl, gan gymryd PR_SET_SECOMP fel opsiwn i fynd i mewn i fodd cyfrifiadura diogel. Yna rydyn ni'n dweud wrth y modd i lwytho'r hidlydd gan ddefnyddio SECCOMP_MODE_FILTER, sydd wedi'i gynnwys yn y newidyn prog math sock_fprog:

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

Yn olaf, gallwn ddefnyddio ein swyddogaeth install_filter, ond cyn hynny mae angen i ni ddefnyddio prctl i osod PR_SET_NO_NEW_PRIVS ar gyfer y gweithrediad cyfredol a thrwy hynny osgoi'r sefyllfa lle mae prosesau plentyn yn derbyn mwy o freintiau na'u rhieni. Gyda hyn, gallwn wneud y galwadau prctl canlynol yn y swyddogaeth install_filter heb gael hawliau gwraidd.

Nawr gallwn alw'r swyddogaeth install_filter. Gadewch i ni rwystro pob galwad system ysgrifennu sy'n ymwneud â phensaernïaeth X86-64 a rhoi caniatâd yn unig sy'n rhwystro pob ymgais. Ar ôl gosod yr hidlydd, rydym yn parhau i weithredu gan ddefnyddio'r ddadl gyntaf:

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

Gadewch i ni ddechrau. I lunio ein rhaglen gallwn ddefnyddio naill ai clang neu gcc, y naill ffordd neu'r llall, dim ond llunio'r ffeil main.c heb opsiynau arbennig:

clang main.c -o filter-write

Fel y nodwyd, rydym wedi rhwystro pob cofnod yn y rhaglen. I brofi hyn mae angen rhaglen sy'n allbynnu rhywbeth - mae'n ymddangos fel ymgeisydd da. Dyma sut mae hi fel arfer yn ymddwyn:

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

Gwych! Dyma sut olwg sydd ar ddefnyddio ein rhaglen lapio: Yn syml, rydyn ni'n pasio'r rhaglen rydyn ni am ei phrofi fel y ddadl gyntaf:

./filter-write "ls -la"

Pan gaiff ei gweithredu, mae'r rhaglen hon yn cynhyrchu allbwn hollol wag. Fodd bynnag, gallwn ddefnyddio strace i weld beth sy'n digwydd:

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

Mae canlyniad y gwaith yn cael ei fyrhau'n fawr, ond mae'r rhan gyfatebol ohono yn dangos bod cofnodion wedi'u rhwystro â'r gwall EPERM - yr un un ag y gwnaethom ei ffurfweddu. Mae hyn yn golygu nad yw'r rhaglen yn allbynnu dim oherwydd na all gael mynediad i'r alwad system ysgrifennu:

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

Nawr rydych chi'n deall sut mae Seccomp BPF yn gweithio ac mae gennych chi syniad da o'r hyn y gallwch chi ei wneud ag ef. Ond oni fyddech chi'n hoffi cyflawni'r un peth gydag eBPF yn lle cBPF i harneisio ei bŵer llawn?

Wrth feddwl am raglenni eBPF, mae'r rhan fwyaf o bobl yn meddwl eu bod yn eu hysgrifennu ac yn eu llwytho â breintiau gweinyddwr. Er bod y datganiad hwn yn gyffredinol wir, mae'r cnewyllyn yn gweithredu set o fecanweithiau i amddiffyn gwrthrychau eBPF ar wahanol lefelau. Gelwir y mecanweithiau hyn yn drapiau LSM BPF.

Trapiau LSM BPF

Er mwyn darparu monitro pensaernïaeth-annibynnol o ddigwyddiadau system, mae LSM yn gweithredu'r cysyniad o drapiau. Mae galwad bachyn yn dechnegol debyg i alwad system, ond mae'n annibynnol ar y system ac wedi'i hintegreiddio â'r seilwaith. Mae LSM yn darparu cysyniad newydd lle gall haen tynnu dŵr helpu i osgoi problemau a wynebir wrth ddelio â galwadau system ar wahanol bensaernïaeth.

Ar adeg ysgrifennu, mae gan y cnewyllyn saith bachau sy'n gysylltiedig â rhaglenni BPF, a SELinux yw'r unig LSM adeiledig sy'n eu gweithredu.

Mae'r cod ffynhonnell ar gyfer y trapiau wedi'i leoli yn y goeden cnewyllyn yn y ffeil cynnwys/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);

Bydd pob un ohonynt yn cael eu galw ar wahanol gamau gweithredu:

— security_bpf — yn cynnal gwiriad cychwynnol o alwadau system BPF a weithredwyd;

- security_bpf_map - yn gwirio pan fydd y cnewyllyn yn dychwelyd disgrifydd ffeil ar gyfer y map;

- security_bpf_prog - yn gwirio pan fydd y cnewyllyn yn dychwelyd disgrifydd ffeil ar gyfer y rhaglen eBPF;

— security_bpf_map_alloc — yn gwirio a yw'r maes diogelwch y tu mewn i fapiau BPF wedi'i gychwyn;

- security_bpf_map_free - yn gwirio a yw'r maes diogelwch wedi'i glirio y tu mewn i fapiau BPF;

— security_bpf_prog_alloc — yn gwirio a yw'r maes diogelwch wedi'i gychwyn y tu mewn i raglenni BPF;

- security_bpf_prog_free - yn gwirio a yw'r maes diogelwch wedi'i glirio y tu mewn i raglenni BPF.

Nawr, o weld hyn i gyd, rydym yn deall: y syniad y tu ôl i atalwyr LSM BPF yw y gallant ddarparu amddiffyniad i bob gwrthrych eBPF, gan sicrhau mai dim ond y rhai sydd â'r breintiau priodol sy'n gallu cyflawni gweithrediadau ar gardiau a rhaglenni.

Crynodeb

Nid yw diogelwch yn rhywbeth y gallwch chi ei roi ar waith mewn ffordd sy'n addas i bawb ar gyfer popeth rydych chi am ei amddiffyn. Mae'n bwysig gallu diogelu systemau ar wahanol lefelau ac mewn gwahanol ffyrdd. Credwch neu beidio, y ffordd orau o sicrhau system yw trefnu gwahanol lefelau o amddiffyniad o wahanol swyddi, fel nad yw lleihau diogelwch un lefel yn caniatáu mynediad i'r system gyfan. Mae'r datblygwyr craidd wedi gwneud gwaith gwych o roi set o wahanol haenau a phwyntiau cyffwrdd i ni. Gobeithiwn ein bod wedi rhoi dealltwriaeth dda i chi o beth yw haenau a sut i ddefnyddio rhaglenni BPF i weithio gyda nhw.

Am awduron

David Calavera yw'r GTG yn Netlify. Bu’n gweithio ym maes cymorth Docker a chyfrannodd at ddatblygu offer Runc, Go a BCC, yn ogystal â phrosiectau ffynhonnell agored eraill. Yn adnabyddus am ei waith ar brosiectau Docker a datblygiad ecosystem ategyn Docker. Mae David yn angerddol iawn am graffiau fflam ac mae bob amser yn ceisio optimeiddio perfformiad.

Lorenzo Fontana yn gweithio ar y tîm ffynhonnell agored yn Sysdig, lle mae'n canolbwyntio'n bennaf ar Falco, prosiect Cloud Native Computing Foundation sy'n darparu diogelwch amser rhedeg cynhwysydd a chanfod anghysondebau trwy fodiwl cnewyllyn ac eBPF. Mae'n angerddol am systemau gwasgaredig, rhwydweithio wedi'i ddiffinio gan feddalwedd, y cnewyllyn Linux, a dadansoddi perfformiad.

» Ceir rhagor o fanylion am y llyfr yn gwefan y cyhoeddwr
» Tabl cynnwys
» Detholiad

Ar gyfer Khabrozhiteley gostyngiad o 25% gan ddefnyddio cwpon - Linux

Ar ôl talu'r fersiwn papur o'r llyfr, anfonir llyfr electronig trwy e-bost.

Ffynhonnell: hab.com

Ychwanegu sylw