Project to port the pledge isolation mechanism to Linux

The author of the Cosmopolitan C standard library and the Redbean platform announced the implementation of the pledge() isolation mechanism for Linux. The pledge was originally developed by the OpenBSD project and allows you to selectively prohibit applications from accessing unused system calls (a kind of white list of system calls is formed for the application, and other calls are prohibited). Unlike the syscall access control mechanisms available in Linux, such as seccomp, the pledge mechanism is designed from the ground up to be as easy to use as possible.

The failed initiative to isolate applications in the OpenBSD base environment using the systrace mechanism showed that isolation at the level of individual system calls is too complicated and time consuming. As an alternative, a pledge was proposed, which allowed creating isolation rules without going into details and manipulating ready-made access classes. For example, the classes offered are stdio (input / output), rpath (only reading files), wpath (writing files), cpath (creating files), tmppath (working with temporary files), inet (network sockets), unix (unix sockets) , dns (DNS resolution), getpw (read access to the user database), ioctl (call ioctl), proc (process control), exec (start processes), and id (permission control).

The rules for working with system calls are specified in the form of annotations that include a list of allowed system call classes and an array of file paths where access is allowed. After building and running the modified application, the kernel takes over the job of monitoring compliance with the specified rules.

Separately, the pledge implementation for FreeBSD is being developed, which is distinguished by the ability to isolate applications without making changes to their code, while in OpenBSD the pledge call is aimed at tight integration with the base environment and adding annotations to the code of each application.

The developers of the Linux port of pledge took the FreeBSD example and, instead of making changes to the code, prepared a pledge.com add-on utility that allows you to apply restrictions without changing the application code. For example, to run the curl utility with access only to the stdio, rpath, inet, and threadstdio system call classes, just run "./pledge.com -p 'stdio rpath inet thread' curl http://example.com".

The pledge utility works on all Linux distributions since RHEL6 and does not require root access. Additionally, based on the cosmopolitan library, an API is provided for managing restrictions in the code of programs in the C language, which allows, among other things, to create enclaves for selectively restricting access in relation to certain application functions.

The implementation does not require changes to the kernel - pledge restrictions are translated into SECCOMP BPF rules and processed using the native Linux system call isolation mechanism. For example, a call to pledge("stdio rpath", 0) will be converted to a BPF filter 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 */ };

Source: opennet.ru

Add a comment