
Cache readdir del kernel Linux FUSE scrittura fuori dai limiti (CVE-2026-31694): un server FUSE malintenzionato causa un overflow di una pagina della cache di pagina di 24 byte. PoC più un exploit locale non privilegiato per ottenere root tramite corruzione della cache di pagina di /etc/passwd. Eseguire solo all'interno di una VM.
Un controllo dei limiti mancante in fs/fuse/readdir.c:fuse_add_dirent_to_cache(). Un server FUSE restituisce un dirent con namelen = 4095, che viene serializzato in un record di 4120 byte. Il kernel lo copia in una singola pagina di cache di pagina da 4096 byte e supera di 24 byte controllati dal server nella pagina fisica successiva.
Questo repository contiene un PoC marker per la primitiva di scrittura e un escalation di privilegi locale che prepara l'overflow sulla copia in cache di /etc/passwd e trasforma root in un account senza password.
FUSE_NAME_MAX a PATH_MAX - 1 ha reso raggiungibile il percorso readdir)51a8de6c50bf9 "fuse: reject oversized dirents in page cache" (uno dei cinque backport stabili)L'overflow è una scrittura nel kernel in qualsiasi pagina fisica che si trovi subito dopo la pagina della cache FUSE. La preparazione mira a quella scrittura su una pagina scelta, ma è probabilistica. In caso di fallimento, i 24 byte possono colpire una pagina non correlata:
Eseguilo solo all'interno di una VM usa e getta. Gli script qui eseguono sempre l'exploit all'interno di QEMU/KVM, mai sull'host.
exploit.c il PoC e LPE (file singolo, build statica)
Makefile compila ./exploit (statica)
vm/config.sh tutti i percorsi e impostazioni (modifica KERNEL_TREE)
vm/make_rootfs.sh compila l'immagine guest Ubuntu 24.04 (esegui come root)
vm/build_vuln_kernel.sh compila un bzImage vulnerabile dal tuo albero del kernel
vm/run_vm.sh avvia la guest in modalità headless
vm/provision_guest.sh configurazione nella guest (eseguito via ssh)
vm/run_in_vm.sh un comando: avvia, configura, esegui, verifica
Host: Linux con KVM (/dev/kvm presente, il tuo utente nel gruppo kvm), e:
qemu-system-x86_64, sshpass, gcc, makemake_rootfs.sh: debootstrap (e root)È necessaria anche una directory dei sorgenti del kernel Linux da cui compilare un kernel vulnerabile.
Modifica vm/config.sh. L'unico valore che devi impostare è KERNEL_TREE: il percorso verso un checkout dei sorgenti Linux. Usa una revisione precedente alla correzione 51a8de6c50bf9 (qualsiasi checkout 6.15..7.0 ha il bug). Se l'albero ha già la correzione, build_vuln_kernel.sh rimuove la guardia per la build e ripristina il file successivamente. Tutto il resto (memoria, cpu, porta ssh, percorsi delle immagini) ha un valore predefinito che puoi lasciare invariato. Qualsiasi valore può anche essere impostato dall'ambiente, ad esempio KERNEL_TREE=/path/to/linux vm/run_in_vm.sh.
Compila l'immagine guest (Ubuntu 24.04, necessita di root per debootstrap):
sudo vm/make_rootfs.sh
Questo crea un utente sudo test:test, una console seriale, autenticazione ssh con password e fuse3.
Compila il kernel vulnerabile:
vm/build_vuln_kernel.sh
Dall'inizio alla fine (avvio, configurazione, PoC marker, LPE, verifica uid 0):
vm/run_in_vm.sh
Manuale:
vm/run_vm.sh & # avvia headless; la console va in vm/serial.log
make # compila l'exploit statico
# copia ./exploit nella guest, poi come utente test:
./exploit --poc -n 20 # test marker
./exploit # riscaldamento, poi LPE
Arresta la VM:
pkill -f bzImage-fuse-vuln
--poc solo modalità marker, nessuna modifica a /etc/passwd
-n N numero di round
(no args) 5 round di riscaldamento, poi fino a 200 tentativi LPE; in caso di successo scrive una riga root senza password in /etc/passwd e invalida le cache
La modalità marker stampa i successi per round e un totale, ad esempio 20/20 (100.0%).
La modalità LPE stampa Warmup: 5/5, poi una riga LPE n/200 ... HIT!, modifica la prima riga di /etc/passwd da root:x:0:0:root:/root:/bin/bash a root::0:0:root:/root:/bin/sh, e un successivo su -s /bin/sh root con password vuota restituisce uid 0.
Il percorso della cache readdir copia ogni dirent in una pagina della cache di pagina. Il controllo della dimensione chiede solo se il dirent si adatta allo spazio rimanente della pagina corrente; non chiede mai se il dirent si adatta in una pagina. Con namelen = 4095 il record è di 4120 byte, quindi la copia supera di 24 byte la fine di una pagina nuova.
L'exploit svuota le freelist per-CPU (PCP) in modo che l'allocatore fornisca pagine fisicamente adiacenti dalle suddivisioni buddy, quindi dispone la pagina della cache readdir e una pagina vittima come vicine. Per l'LPE la vittima è la copia in cache di /etc/passwd: l'overflow di 24 byte riscrive la riga di root in modo che il campo password sia vuoto, e con PAM nullok (impostazione predefinita di Ubuntu) su root ha successo con una password vuota.
Full writeup: https://cyberstan.co.uk/fuse-readdir-oob/
Segnalato a monte da Qi Tang e Zijun Hu; la correzione è stata scritta da Samuel Page. Ho scoperto e segnalato questo indipendentemente. Il credito a monte e CVE-2026-31694 sono loro. Il bug è stato risolto in mainline e nei rami stabili.
MIT, vedi LICENSE. Solo per istruzione e test autorizzati.