Una vulnerabilidad en io_uring permitía que un usuario sin permisos se convierta en root incluso en contenedores

agosto 08, 2022 , 0 Comments

Hace poco se dio a conocer información de la vulnerabilidad (CVE-2022-29582) en la implementación de la interfaz de E/S asíncrona io_uring, incluida en el kernel de Linux desde la versión 5.1, que permite que un usuario sin privilegios se convierta en root en el sistema, incluso cuando ejecuta un exploit de un contenedor.

Cabe mencionar que dicha vulnerabilidad se informó hace poco más de 3 meses (aproximadamente a principios de mayo de este año), pero la información completa y divulgación se dio a conocer recientemente.

Sobre la vulnerabilidad se menciona que esta se produce al acceder a un bloque de memoria ya liberado, se manifiesta en los kernels de Linux a partir de la rama 5.10.

Sobre la vulnerabilidad CVE-2022-29582

Esta vulnerabilidad permite poder accede a la memoria liberada como resultado de una condición de carrera cuando se manejan tiempos de espera en la función io_flush_timeouts(), que elimina la entrada de tiempo de espera de la lista y la cancela, sin verificar la creación y eliminación del tiempo de espera en ese punto.

Una descripción general y actualizada de io_uring ya ha sido proporcionada por otros. Lo explican mil veces mejor que nosotros, por lo que solo cubriremos el subsistema de manera más amplia (consulte este artículo de Grapl Security y este artículo de Flatt Security para obtener una excelente introducción).

Lo que es más importante, el campo opcode determina qué tipo de operación realizar. Para que cada que»opcode» lo requiera, el campo fd especifica el descriptor de archivo en el que realizar la E/S solicitada. Casi todas las llamadas al sistema de E/S normales ( read, sendto, etc.) tienen un código de operación asíncrono equivalente. Cada campo puede asumir diferentes roles dependiendo de la operación.

Una vez recuperado del SQ, un SQE se convierte en una representación interna descrita por struct io_kiocb( kernel input/output call back). Estos objetos se conocen comúnmente como solicitudes.

struct io_kiocb utiliza como un equivalente a «ready-for-launch» del SQE en el que se basa, con lo que cualquier descriptor de archivo se resuelve en struct file*s, se adjuntan las credenciales del usuario, se adjunta la personalidad (en qué núcleos se ejecutará), etc.

Una vez finalizada la operación solicitada, se escribe en la cola de finalización (CQ) una entrada que corresponde al SQE. Dicha entrada se denomina entrada de cola de finalización (CQE) y contiene campos como un código de error y un valor de resultado. La aplicación del espacio de usuario puede sondear el CQ en busca de nuevas entradas para determinar si los SQE enviados han terminado de procesarse y cuál fue su resultado.

Se mencionan que existen algunos escenarios sobre los cuales es fácil reemplazar un objeto sobre la marcha. Pero existen dos limitantes :

  • LT’ tiene que ser asignado e inicializado en una ventana de carrera. Es decir, después de que el LT se libera pero antes de llegar a un punto en el LT que ya no se accede.
  • LT’ sólo puede ser otro objeto objeto struct io_kiocb. Debido al aislamiento del montón, donde los objetos del montón se separan según su tipo, es demasiado difícil reasignarlos como un tipo diferente de objeto dentro de la ventana de carrera.

Los investigadores han preparado un exploit funcional que no requiere la inclusión de espacios de nombres de identificadores de usuario (espacios de nombres de usuario) para su funcionamiento y puede proporcionar acceso de raíz al sistema principal cuando un usuario sin privilegios inicia el exploit en un contenedor aislado.

Nuestro exploit apunta a la versión del kernel 5.10.90, la versión que Google estaba ejecutando de forma remota en ese momento. Tuvimos que ajustar nuestro exploit a las especificaciones particulares del servidor (4 núcleos Skylake Xeon @ 2.80Ghz, 16GiB RAM), pero con algunos ajustes, cualquier máquina que ejecute un kernel vulnerable debería ser explotable

El exploit también funciona en el entorno nsjail aislado en la distribución Google COS (Container Optimized OS) basada en Chromium OS y utilizada en Google Cloud Platform en máquinas virtuales Compute Engine. El exploit está diseñado para funcionar con ramas del kernel de 5.10 a 5.12. Por ultimo vale mencionar que el problema solucionó en abril en las actualizaciones 5.10.111, 5.15.34 y 5.17.3.

Finalmente si estás interesado en poder conocer más al respecto sobre la vulnerabilidad, puedes consultar la publicación realizada en el siguiente enlace.


Some say he’s half man half fish, others say he’s more of a seventy/thirty split. Either way he’s a fishy bastard.