
Detector en Rust y laboratorio local para CVE-2026-98432, un use-after-free de TCP IPv4 en Linux en inet_opt/ireq_opt: análisis estático de ELF, comprobaciones de alcanzabilidad mediante kprobe y un disparador de condición de carrera.
inet_opt / ireq_opt)PoC de investigación y laboratorio local para un use-after-free del kernel de Linux alcanzable desde un listener TCP IPv4 simple. Esto es un detector/disparador de bugs, no un exploit.
7.0.0-38-generic):
inet_sock_destruct() y tcp_v4_reqsk_destructor() liberan las opciones con
kfree() en lugar de kfree_rcu().kfree es alcanzable en tiempo de ejecución (kprobes).free -> use (via=reqsk) en una ejecución antigua, y no pudimos reproducirlos
de forma fiable.tcp2kaslr también se detiene en el disparo del bug; las etapas posteriores
no están publicadas.CONFIG_KASAN está desactivado y el muestreo de KFENCE está deshabilitado.tcp2kaslr)MPTCP no es necesario. La ruta probada es TCP IPv4 simple:
ireq_opt).accept() del hijo, establece SO_LINGER(0) y lo cierra.
inet_sock_destruct() libera las opciones con kfree().Nuestro disparador anterior era incorrecto en dos aspectos: la víctima nunca aceptaba/cerraba el
hijo (free_sock=0), y enviábamos un RST en lugar de confiar en el cierre del servidor.
El código actual añade las piezas correctas:
listen --accept-close — accept + SO_LINGER(0) + close.--sync — ACK + SYN duplicado de forma concurrente, sin RST, con opciones Record Route.La corrección upstream es exactamente:
- kfree(rcu_dereference_protected(inet->inet_opt, 1));
+ kfree_rcu(rcu_dereference_protected(inet->inet_opt, 1), rcu);
y el mismo cambio en tcp_v4_reqsk_destructor().
| Ruta | Qué |
|---|---|
rust-poc/ | la PoC nativa en Rust: análisis estático de ELF, kprobes, modos de activación |
lab/ | víctima de loopback con Alpine + PHP para las antiguas pruebas locales |
scripts/ | ayudantes de reproducción local, ayudantes de auditoría autorizada |
docs/FINDINGS.md | qué se probó, qué se confirmó, qué no |
docs/EXPLOITATION-NOTES.md | alcance: solo activación del fallo, sin RCE |
docs/evidence/ | evidencia de muestra saneada |
cd rust-poc
cargo build --release
# static analysis (no root)
./target/release/cve-2026-98432 static
# runtime reachability (root, tracefs)
sudo ./target/release/cve-2026-98432 runtime
# correct local vector: accept+close server + --sync trigger
cd ..
PASSES=1 ./scripts/repro-sync.sh 8083
repro-sync.sh inicia la víctima --accept-close en 127.0.0.1:8083, ejecuta el
disparador de sincronización con sudo e imprime free_sock, use_build y el
veredicto de UAF. Una ejecución limpia no es prueba de seguridad: la tasa es de aproximadamente 1e-7 por
intento y los eventos se agrupan.
Si falta artifacts/, static/runtime recurren a /boot; el
script heredado scripts/cve-2026-98432.sh --static puede generar los artefactos del kernel.
Con KASAN, el kernel reporta un slab-use-after-free en
inet_csk_route_req / ip_options_build con la pila de liberación en
inet_sock_destruct / inet_release. El arnés tcp2kaslr llega a eso en
unos 134k intentos con KASAN; en un kernel normal la misma carrera se observó solo
dos veces en ~48M intentos.
Prueba únicamente kernels y hosts que poseas o para los que tengas autorización explícita. El disparador es una carrera del kernel y puede provocar un fallo del host. Usa una VM desechable con una instantánea.
offline-ant/tcp2kaslr — disparador del bug, evidencia de KASAN, análisis:
https://github.com/offline-ant/tcp2kaslripv4: free inet_opt and ireq_opt after an RCU grace period
(Eric Dumazet), kfree → kfree_rcu en net/ipv4/af_inet.c y
net/ipv4/tcp_ipv4.c.MIT. Consulta LICENSE.