Progetto per trasferire il meccanismo di isolamento del pegno su Linux

L'autore della libreria C standard Cosmopolitan e della piattaforma Redbean ha annunciato l'implementazione del meccanismo di isolamento pledge() per Linux. Pledge è stato originariamente sviluppato dal progetto OpenBSD e consente di vietare selettivamente alle applicazioni l'accesso alle chiamate di sistema inutilizzate (per l'applicazione viene formata una sorta di lista bianca di chiamate di sistema e altre chiamate sono vietate). A differenza dei meccanismi di restrizione dell'accesso alle chiamate di sistema disponibili in Linux, come seccomp, il meccanismo di impegno è stato originariamente progettato per essere il più semplice possibile da usare.

L'iniziativa fallita di isolare le applicazioni nell'ambiente di base OpenBSD utilizzando il meccanismo systrace ha dimostrato che l'isolamento a livello delle singole chiamate di sistema era troppo complesso e richiedeva molto tempo. In alternativa è stato proposto un impegno che permettesse di creare regole di isolamento senza entrare nei dettagli e senza manipolare classi di accesso già pronte. Ad esempio, le classi offerte sono stdio (input/output), rpath (file di sola lettura), wpath (scrivere file), cpath (creare file), tmppath (lavorare con file temporanei), inet (socket di rete), unix ( unix), dns (risoluzione DNS), getpw (accesso in lettura al database degli utenti), ioctl (chiamata ioctl), proc (gestione dei processi), exec (avvio del processo) e id (gestione dei diritti di accesso).

Le regole per lavorare con le chiamate di sistema sono specificate sotto forma di annotazioni, incluso un elenco di classi consentite di chiamate di sistema e una serie di percorsi di file a cui è consentito l'accesso. Dopo aver creato e avviato l'applicazione modificata, il kernel si assume il compito di monitorare il rispetto delle regole specificate.

Per FreeBSD è in fase di sviluppo un'implementazione separata del pledge, che si distingue per la capacità di isolare le applicazioni senza apportare modifiche al loro codice, mentre in OpenBSD il pledge call mira a una stretta integrazione con l'ambiente di base e all'aggiunta di annotazioni al codice di ciascuna applicazione.

Gli sviluppatori del port pledge per Linux hanno preso l'esempio di FreeBSD e, invece di apportare modifiche al codice, hanno preparato un'utilità aggiuntiva pledge.com che consente di applicare restrizioni senza modificare il codice dell'applicazione. Ad esempio, per eseguire l'utilità curl con accesso solo alle classi di chiamate di sistema stdio, rpath, inet e threadstdio, è sufficiente eseguire “./pledge.com -p 'stdio rpath inet thread' curl http://example.com”.

L'utilità pledge funziona su tutte le distribuzioni Linux a partire da RHEL6 e non richiede l'accesso root. Inoltre, sulla base della libreria cosmopolita, viene fornita un'API per la gestione delle restrizioni nel codice di programma in linguaggio C, che consente, tra l'altro, di creare enclavi per limitare selettivamente l'accesso in relazione a determinate funzioni dell'applicazione.

L'implementazione non richiede modifiche al kernel: le restrizioni di impegno vengono tradotte in regole SECCOMP BPF ed elaborate utilizzando il meccanismo di isolamento delle chiamate di sistema native di Linux. Ad esempio, la chiamata pledge("stdio rpath", 0) verrà convertita in un filtro 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_AND | 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_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), /*L13*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L14*/ /* filtro successivo */ };

Fonte: opennet.ru

Aggiungi un commento