
Verificador de prueba de concepto para Aarch64 de CVE-2026-46242 'Bad Epoll', que desencadena la condición de carrera use-after-free close-vs-close del epoll del kernel de Linux para validar la escalada local de privilegios.
Este repositorio es un validador de Bad Epoll para kernels aarch64 basado en un exploit que ya existe para x86.
Escalada de privilegios local del kernel de Linux mediante condición de carrera de use-after-free en
epoll
| Campo | Detalle |
|---|---|
| CVE | CVE-2026-46242 |
| Apodo | Bad Epoll |
| Tipo | Use-After-Free (UAF) mediante condición de carrera |
| CVSS | 7.8 (High) |
| Impacto | Escalada local de privilegios → root |
| Kernels afectados | 5.10 – 6.11 (LTS y COS) |
| Subsistema | fs/eventpoll.c (ruta ep_remove() / cierre) |
Existe una condición de carrera en el subsistema epoll del kernel de Linux durante operaciones close() concurrentes sobre descriptores de archivo monitoreados y monitoreadores. Cuando dos rutas de cierre se ejecutan simultáneamente:
eventpoll mediante ep_remove().hlist_del_rcu() de la otra ruta aterriza en la memoria ya liberada.Esto produce un Use-After-Free que corrompe la lista refs del eventpoll reclamado, dejando un puntero epi->ffd.file colgante en el waiter de epoll sobreviviente — la base de la cadena de explotación completa.
┌─────────────────────────────────────────────────────────┐
│ 1. KASLR Leak (prefetch side-channel via libxdk) │
├─────────────────────────────────────────────────────────┤
│ 2. Race Trigger (close-vs-close UAF on eventpoll) │
│ ├─ Adaptive timer: stat/exec phases calibrate ahead │
│ ├─ False-sharing: dup()+close() widens race window │
│ └─ Oracle: EPOLL_CTL_ADD depth-3 → ELOOP? │
├─────────────────────────────────────────────────────────┤
│ 3. Reclaim (freed eventpoll → ep_uaf_target) │
│ └─ Dangling epi->ffd.file in ep_uaf_waiter │
├─────────────────────────────────────────────────────────┤
│ 4. Cross-Cache (filp slab → buddy → pipe_buffer) │
│ ├─ Drain per-CPU partial list │
│ ├─ Free enclosing objects → slab page freed │
│ └─ Reclaim as pipe pages (256 × 4 KiB) │
├─────────────────────────────────────────────────────────┤
│ 5. Constrained AAR (fdinfo ino:/sdev: as read oracle) │
│ ├─ Fake file spray tiles forged struct file in pipe │
│ ├─ 8B read: ino: ← i_ino at controlled offset │
│ ├─ 4B read: sdev: ← sigaltstack(sas_ss_sp) cursor │
│ └─ Walk: init_task → find exploit task → resolve │
│ files → fdt → fd[] → pipe_buffer → struct page │
├─────────────────────────────────────────────────────────┤
│ 6. RIP Control (f_op→poll hijack → JOP → ROP) │
│ ├─ Forge f_op = virt, f_count = virt - 1 │
│ ├─ JOP pivot chain lands rsp on controlled page │
│ └─ libxdk ROP: commit_creds(init_cred) + ns switch │
├─────────────────────────────────────────────────────────┤
│ 7. Ret2Usr execve("/bin/bash") as root │
└─────────────────────────────────────────────────────────┘
# aarch64 (cross-compile or native)
aarch64-linux-gnu-gcc -O2 -Wall -pthread -march=armv8-a \
race_check_aarch64.c -o race_check
./race_check [timeout_seconds] # default: 300s (5 min)
./race_check 120 # 2-minute timeout
| Código | Significado |
|---|---|
0 | Carrera ganada — el kernel es vulnerable |
1 | Tiempo de espera agotado — carrera no detectada (posible falso negativo, no demuestra que el kernel esté parcheado) |
⚠️ Aviso legal: Este repositorio se proporciona únicamente con fines educativos y de investigación de seguridad autorizada. El uso no autorizado de este exploit contra sistemas que no posees o para los que no tienes permiso explícito de prueba es ilegal.