El autor de la biblioteca estándar C Cosmopolitan y de la plataforma Redbean ha anunciado la implementación del mecanismo de aislamiento pledge() para Linux. Originalmente, pledge fue desarrollado por el proyecto OpenBSD y permite restringir selectivamente a las aplicaciones el acceso a llamadas al sistema no utilizadas (se crea un tipo de lista blanca de llamadas al sistema para la aplicación, mientras que las demás llamadas están prohibidas). A diferencia de los mecanismos de restricciones de acceso a las llamadas al sistema disponibles en Linux, como seccomp, el mecanismo pledge fue diseñado desde el principio para simplificar al máximo su uso.
La fallida iniciativa de aislamiento de aplicaciones en el entorno base de OpenBSD utilizando el mecanismo systrace mostró que el aislamiento a nivel de llamadas al sistema individuales es demasiado complejo y laborioso. Como alternativa, se propuso pledge, que permitía crear reglas de aislamiento sin profundizar en los detalles y manipulando clases de acceso predefinidas. Por ejemplo, se ofrecen clases como stdio (entrada/salida), rpath (solo lectura de archivos), wpath (escritura de archivos), cpath (creación de archivos), tmppath (trabajo con archivos temporales), inet (sockets de red), unix (sockets unix), dns (resolución DNS), getpw (acceso de lectura a la base de usuarios), ioctl (llamada ioctl), proc (gestión de procesos), exec (ejecución de procesos) y id (gestión de permisos de acceso).
Las reglas de trabajo con las llamadas al sistema se establecen en forma de anotaciones, que incluyen una lista de clases de llamadas al sistema permitidas y un array de rutas de archivos a las que se permite el acceso. Después de compilar y ejecutar la aplicación modificada, el núcleo se encarga de controlar el cumplimiento de las reglas establecidas.
Se está desarrollando por separado una implementación de pledge para FreeBSD, que se diferencia por la posibilidad de aislar aplicaciones sin necesidad de modificar su código, mientras que en OpenBSD la llamada a pledge está destinada a una integración estrecha con el entorno base y a añadir anotaciones en el código de cada aplicación.
Los desarrolladores del puerto pledge para Linux se basaron en el ejemplo de FreeBSD y, en lugar de realizar cambios en el código, prepararon una utilidad de envoltura llamada pledge.com, que permite aplicar limitaciones sin modificar el código de la aplicación. Por ejemplo, para ejecutar la utilidad curl con acceso abierto solo a las clases de llamadas al sistema stdio, rpath, inet y threadstdio, basta con ejecutar “./pledge.com -p 'stdio rpath inet thread' curl http://example.com”.
La herramienta pledge funciona en todas las distribuciones de Linux a partir de RHEL6 y no requiere acceso root. Además, se proporciona una API basada en la biblioteca cosmopolitan para gestionar las restricciones en el código de programas en lenguaje C, lo que permite, entre otras cosas, crear enclaves para limitar selectivamente el acceso en función de ciertas funciones de la aplicación.
La implementación no requiere modificaciones en el núcleo: las restricciones de pledge se traducen en reglas SECCOMP BPF y se procesan mediante el mecanismo nativo de Linux para la aislamiento de llamadas al sistema. Por ejemplo, la llamada pledge("stdio rpath", 0) se convertirá en 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*/ /* siguiente filtro */ };
Fuente: opennet.ru
