O autor da biblioteca padrão C Cosmopolitan e da plataforma Redbean anunciou a implementação do mecanismo de isolamento pledge() para Linux. Inicialmente, pledge foi desenvolvido pelo projeto OpenBSD e permite proibir seletivamente que aplicativos acessem chamadas de sistema não utilizadas (criando uma espécie de lista branca de chamadas de sistema para o aplicativo, enquanto as demais chamadas são proibidas). Diferente dos mecanismos disponíveis no Linux para restringir o acesso às chamadas de sistema, como o seccomp, o mecanismo pledge foi originalmente projetado com a intenção de simplificar ao máximo sua aplicação.
A iniciativa de isolamento de aplicativos do ambiente básico OpenBSD usando o mecanismo systrace, que terminou em fracasso, demonstrou que o isolamento em nível de chamadas de sistema individuais é muito complexo e trabalhoso. Como alternativa, foi proposto o pledge, que permite criar regras de isolamento sem se aprofundar nos detalhes e manipulando classes de acesso predefinidas. Por exemplo, são oferecidas classes como stdio (entrada/saída), rpath (somente leitura de arquivos), wpath (gravação de arquivos), cpath (criação de arquivos), tmppath (manipulação de arquivos temporários), inet (sockets de rede), unix (sockets unix), dns (resolução DNS), getpw (acesso de leitura ao banco de usuários), ioctl (chamada ioctl), proc (gerenciamento de processos), exec (execução de processos) e id (gerenciamento de permissões de acesso).
As regras para chamadas de sistema são definidas em forma de anotações, incluindo uma lista de classes de chamadas de sistema permitidas e um array de caminhos de arquivos aos quais o acesso é permitido. Após a compilação e execução do aplicativo modificado, o núcleo assume a tarefa de controlar o cumprimento das regras estabelecidas.
Uma implementação separada do pledge para FreeBSD está em desenvolvimento, a qual se diferencia pela possibilidade de isolar aplicativos sem precisar modificar seu código, enquanto no OpenBSD a chamada pledge visa uma integração íntima com o ambiente básico e a adição de anotações ao código de cada aplicativo.
Os desenvolvedores do port pledge para Linux tomaram como exemplo o FreeBSD e, em vez de modificar o código, prepararam uma ferramenta adicional chamada pledge.com, que permite aplicar restrições sem alterar o código do aplicativo. Por exemplo, para executar a ferramenta curl com acesso apenas às classes de chamadas de sistema stdio, rpath, inet e threadstdio, basta executar “./pledge.com -p 'stdio rpath inet thread' curl http://example.com”.
A ferramenta pledge funciona em todas as distribuições Linux, a partir do RHEL6, e não requer acesso root. Além disso, com base na biblioteca cosmopolitan, há uma API para gerenciar restrições no código de programas em C, permitindo também a criação de enclaves para restrição seletiva de acesso vinculada a determinadas funções do aplicativo.
A implementação não exige alterações no núcleo — as restrições de pledge são traduzidas em regras SECCOMP BPF e processadas por meio do mecanismo nativo de isolamento de chamadas de sistema do Linux. Por exemplo, a chamada pledge("stdio rpath", 0) será convertida em um 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*/ /* próximo filtro */ };
Fonte: opennet.ru
