L'autore della standard C library Cosmopolitan e della piattaforma Redbean ha annunciato l'implementazione del meccanismo di isolamento pledge() per Linux. Originariamente sviluppato dal progetto OpenBSD, pledge consente di vietare selettivamente alle applicazioni l'accesso a chiamate di sistema non utilizzate (per l'applicazione viene creato un qualcosa di simile a una lista bianca di chiamate di sistema, mentre le altre vengono bloccate). A differenza dei meccanismi di limitazione dell'accesso alle chiamate di sistema disponibili in Linux, come seccomp, il meccanismo pledge è stato progettato con l'obiettivo di semplificare al massimo l'applicazione.
L'iniziativa di isolamento delle applicazioni del sistema di base OpenBSD utilizzando il meccanismo systrace, che si è conclusa con un fallimento, ha dimostrato che l'isolamento a livello di singole chiamate di sistema è troppo complesso e laborioso. Come alternativa è stato proposto pledge, che consentiva di creare regole di isolamento senza approfondire i dettagli e manipolando classi di accesso predefinite. Ad esempio, vengono proposte classi come stdio (input/output), rpath (solo lettura dei file), wpath (scrittura dei file), cpath (creazione di file), tmppath (lavoro con file temporanei), inet (socket di rete), unix (socket unix), dns (risoluzione DNS), getpw (accesso in lettura al database degli utenti), ioctl (chiamata ioctl), proc (gestione dei processi), exec (esecuzione di processi) e id (gestione dei permessi di accesso).
Le regole per le chiamate di sistema sono definite sotto forma di annotazioni, che includono un elenco di classi di chiamate di sistema consentite e un array di percorsi di file cui è consentito l'accesso. Dopo la compilazione e l'esecuzione dell'applicazione modificata, il kernel si occupa del controllo dell'osservanza delle regole stabilite.
Si sta sviluppando separatamente un'implementazione di pledge per FreeBSD, che si distingue per la possibilità di isolare le applicazioni senza modificare il loro codice, mentre in OpenBSD la chiamata pledge mira a una stretta integrazione con il sistema di base e ad aggiungere annotazioni nel codice di ogni applicazione.
Gli sviluppatori del porting di pledge per Linux hanno seguito l'esempio di FreeBSD e, invece di modificare il codice, hanno preparato un'utilità wrapper pledge.com, che consente di applicare restrizioni senza modificare il codice dell'applicazione. Ad esempio, per eseguire l'utilità curl con accesso consentito 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 accesso root. Inoltre, sulla base della libreria cosmopolitan, viene fornito un API per gestire le restrizioni nel codice dei programmi in C, che consente anche di creare enclavi per limitare selettivamente l'accesso in relazione a funzioni specifiche dell'applicazione.
L'implementazione non richiede modifiche al kernel: le restrizioni di pledge vengono tradotte in regole SECCOMP BPF e gestite tramite il meccanismo di isolamento delle chiamate di sistema nativo per Linux. Ad esempio, la chiamata pledge("stdio rpath", 0) verrà trasformata in un filtro BPF statico: 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*/ /* next filter */ };
Fonte: opennet.ru
