Proiect de portare a mecanismului de izolare a gajului la Linux

Autorul bibliotecii standard C Cosmopolitan și al platformei Redbean a anunțat implementarea mecanismului de izolare pledge() pentru Linux. Pledge a fost dezvoltat inițial de proiectul OpenBSD și vă permite să interziceți selectiv aplicațiilor să acceseze apelurile de sistem neutilizate (un fel de listă albă de apeluri de sistem este format pentru aplicație, iar alte apeluri sunt interzise). Spre deosebire de mecanismele de restricție a accesului la apeluri de sistem disponibile în Linux, cum ar fi seccomp, mecanismul de gaj a fost conceput inițial pentru a fi cât mai simplu posibil.

Inițiativa eșuată de a izola aplicațiile în mediul de bază OpenBSD folosind mecanismul systrace a arătat că izolarea la nivelul apelurilor individuale de sistem a fost prea complexă și consumatoare de timp. Ca alternativă, a fost propus un angajament, care a făcut posibilă crearea unor reguli de izolare fără a intra în detalii și a manipula clase de acces gata făcute. De exemplu, clasele oferite sunt stdio (intrare/ieșire), rpath (fișiere doar pentru citire), wpath (fișiere de scriere), cpath (creare fișiere), tmppath (lucrare cu fișiere temporare), inet (prize de rețea), unix ( socket-uri unix), dns (rezoluție DNS), getpw (acces de citire la baza de date a utilizatorilor), ioctl (apel ioctl), proc (gestionarea procesului), exec (lansarea procesului) și id (gestionarea drepturilor de acces).

Regulile pentru lucrul cu apelurile de sistem sunt specificate sub formă de adnotări, inclusiv o listă de clase permise de apeluri de sistem și o serie de căi de fișiere unde este permis accesul. După construirea și lansarea aplicației modificate, nucleul preia munca de monitorizare a respectării regulilor specificate.

O implementare separată a promisiunii este în curs de dezvoltare pentru FreeBSD, care se distinge prin capacitatea de a izola aplicațiile fără a aduce modificări codului lor, în timp ce în OpenBSD apelul de gaj are ca scop integrarea strânsă cu mediul de bază și adăugarea de adnotări la codul fiecăruia. aplicarea.

Dezvoltatorii portului pledge pentru Linux au luat exemplul FreeBSD și, în loc să facă modificări codului, au pregătit un utilitar de completare pledge.com care vă permite să aplicați restricții fără a modifica codul aplicației. De exemplu, pentru a rula utilitarul curl cu acces numai la clasele de apel de sistem stdio, rpath, inet și threadstdio, trebuie doar să rulați „./pledge.com -p 'stdio rpath inet thread' curl http://example.com”.

Utilitarul de gaj funcționează pe toate distribuțiile Linux care încep cu RHEL6 și nu necesită acces root. În plus, pe baza bibliotecii cosmopolite, este prevăzut un API pentru gestionarea restricțiilor în codul programului în limbajul C, care permite, printre altele, crearea de enclave pentru restricționarea selectivă a accesului în legătură cu anumite funcții ale aplicației.

Implementarea nu necesită modificări ale nucleului - restricțiile de gaj sunt traduse în reguli SECCOMP BPF și procesate folosind mecanismul nativ de izolare a apelurilor de sistem Linux. De exemplu, apelul pledge("stdio rpath", 0) va fi convertit într-un filtru BPF static const struct sock_filter kFilter[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall, 0, 14 - 1 ), / * L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), /* L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 4 - 3, 0), /* L3* / BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 10, 0, 13 - 4), /* L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), /* L5*/ BPF_STMT(BPF_ALU | BPF_ALU | BPF_ALU | | BPF_K, ~0x80800), /* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 8 - 7, 0), /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 0, 13 - 8) , /* L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), /* L9*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 12 - 10, 0), /*L10*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 12 - 11, 0), /*L11*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 17, 0, 13 - 11), /*L12*/ BPF_RET_STMT |(BPF_JMP | BPF_JEQ | BPF_K, 13, 14, XNUMX - XNUMX), /*LXNUMX*/ BPF_RET | SECCOMP_RET_ALLOW), /*LXNUMX*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*LXNUMX*/ /* următorul filtru */ };

Sursa: opennet.ru

Adauga un comentariu