
Escritura fuera de los límites en la caché de readdir de FUSE del kernel de Linux (CVE-2026-31694): un servidor FUSE malicioso desborda una página de la caché de páginas en 24 bytes. PoC más un exploit local-root sin privilegios mediante corrupción de la caché de páginas de /etc/passwd. Ejecutar solo dentro de una VM.
Una verificación de límites faltante en fs/fuse/readdir.c:fuse_add_dirent_to_cache(). Un servidor FUSE devuelve una entrada de directorio con namelen = 4095, que se serializa en un registro de 4120 bytes. El kernel lo copia en una sola página de caché de 4096 bytes y desborda en 24 bytes controlados por el servidor hacia la siguiente página física.
Este repositorio contiene un PoC de marcador para la primitiva de escritura y una escalada de privilegios local que posiciona el desbordamiento sobre la copia en caché de páginas de /etc/passwd y convierte a root en una cuenta sin contraseña.
FUSE_NAME_MAX a PATH_MAX - 1 hizo que la ruta de readdir fuera alcanzable)51a8de6c50bf9 "fuse: reject oversized dirents in page cache" (uno de cinco backports estables)El desbordamiento es una escritura del kernel en cualquier página física que esté justo después de la página de caché de FUSE. El posicionamiento apunta esa escritura a una página elegida, pero es probabilístico. En caso de fallo, los 24 bytes pueden alcanzar una página no relacionada:
Ejecútalo solo dentro de una VM desechable. Los scripts aquí siempre ejecutan el exploit dentro de QEMU/KVM, nunca en el anfitrión.
exploit.c el PoC y LPE (archivo único, compilación estática)
Makefile compila ./exploit (estático)
vm/config.sh todas las rutas y configuraciones (editar KERNEL_TREE)
vm/make_rootfs.sh construir la imagen invitada de Ubuntu 24.04 (ejecutar como root)
vm/build_vuln_kernel.sh construir un bzImage vulnerable desde tu árbol del kernel
vm/run_vm.sh arrancar el invitado sin interfaz gráfica
vm/provision_guest.sh configuración dentro del invitado (se ejecuta por ssh)
vm/run_in_vm.sh un solo comando: arrancar, configurar, ejecutar, verificar
Anfitrión: Linux con KVM (/dev/kvm presente, tu usuario en el grupo kvm), y:
qemu-system-x86_64, sshpass, gcc, makemake_rootfs.sh: debootstrap (y root)También necesitas un árbol de fuentes del kernel de Linux para compilar un kernel vulnerable.
Edita vm/config.sh. El único valor que debes establecer es KERNEL_TREE: la ruta a un checkout de las fuentes de Linux. Usa una revisión anterior a la corrección 51a8de6c50bf9 (cualquier checkout 6.15..7.0 tiene el error). Si el árbol ya tiene la corrección, build_vuln_kernel.sh elimina la protección para la compilación y restaura el archivo después. Todo lo demás (memoria, CPUs, puerto ssh, rutas de imágenes) tiene un valor predeterminado que puedes dejar como está. Cualquier valor también se puede establecer desde el entorno, por ejemplo KERNEL_TREE=/ruta/al/linux vm/run_in_vm.sh.
Construye la imagen invitada (Ubuntu 24.04, necesita root para debootstrap):
sudo vm/make_rootfs.sh
Esto crea un usuario sudo test:test, una consola serie, autenticación por contraseña ssh y fuse3.
Construye el kernel vulnerable:
vm/build_vuln_kernel.sh
De principio a fin (arrancar, configurar, PoC de marcador, LPE, verificar uid 0):
vm/run_in_vm.sh
Manual:
vm/run_vm.sh & # arrancar sin interfaz gráfica; la consola va a vm/serial.log
make # compilar el exploit estático
# copiar ./exploit al invitado, luego como usuario test:
./exploit --poc -n 20 # prueba de marcador
./exploit # calentamiento, luego LPE
Detener la VM:
pkill -f bzImage-fuse-vuln
--poc solo modo marcador, sin cambios en /etc/passwd
-n N número de rondas
(sin args) 5 rondas de calentamiento, luego hasta 200 intentos de LPE; en caso de éxito escribe
una línea de root sin contraseña en /etc/passwd y vacía los cachés
El modo marcador imprime aciertos por ronda y un total, por ejemplo 20/20 (100.0%).
El modo LPE imprime Warmup: 5/5, luego una línea LPE n/200 ... HIT!, cambia la primera línea de /etc/passwd de root:x:0:0:root:/root:/bin/bash a root::0:0:root:/root:/bin/sh, y un posterior su -s /bin/sh root con una contraseña vacía devuelve uid 0.
La ruta de caché de readdir copia cada entrada de directorio en una página de caché de páginas. La verificación de tamaño solo pregunta si la entrada cabe en el espacio restante de la página actual; nunca pregunta si la entrada cabe en una página en absoluto. Con namelen = 4095, el registro es de 4120 bytes, por lo que la copia se extiende 24 bytes más allá del final de una página nueva.
El exploit vacía las listas libres de PCP (por CPU) para que el asignador entregue páginas físicamente adyacentes a partir de divisiones de buddy, luego organiza que la página de caché de readdir y una página víctima sean vecinas. Para el LPE, la víctima es la copia en caché de páginas de /etc/passwd: el desbordamiento de 24 bytes reescribe la línea de root para que su campo de contraseña esté vacío, y con PAM nullok (predeterminado de Ubuntu), su root entonces tiene éxito con una contraseña vacía.
Escrito completo: https://cyberstan.co.uk/fuse-readdir-oob/
Reportado upstream por Qi Tang y Zijun Hu; la corrección fue escrita por Samuel Page. Yo lo encontré y reporté de forma independiente. El crédito upstream y CVE-2026-31694 son suyos. El error está corregido en mainline y en los árboles estables.
MIT, ver LICENSE. Solo para educación y pruebas autorizadas.