Vghost: dos kernels en mi Ubuntu y ninguno lo arregla
Ver imagen del artículo

El jueves 15, a las 06:06 UTC, unattended-upgrades instaló en el servidor web el kernel 6.8.0-147. Esta mañana he buscado en su registro de cambios el arreglo de Vghost, el fallo de vhost que Tencent publicó el lunes. No está. Tampoco en el 6.8.0-138, que es el que sigue arrancado.
Vghost es CVE-2026-74580. Según el informe de Tencent, quien pueda abrir /dev/vhost-net o /dev/vhost-vsock puede hacerse root, y con cierta configuración una máquina virtual llega a escribir en la memoria del QEMU que la ejecuta. Red Hat y Amazon lo corrigieron en agosto. Ubuntu 24.04, a 16 de octubre, todavía no.

/dev/vhost-net aquí y dónde lo corta la propuesta. Esquema propio.Qué he medido y en qué máquina
No puedo reiniciar en un kernel que no existe, pero sí saber quién puede abrir esos dos ficheros y cómo impedir que el módulo se cargue. Lo Probado lo ejecuté el 16 de octubre de 2026, entre las 04:27 y las 04:40 UTC, en el servidor web: Ubuntu 24.04.5 LTS, kernel 6.8.0-138.
Todo ha sido lectura, más modprobe -n, que enseña lo que haría sin cargar nada. Lo que sale del informe de Tencent, del commit o de los avisos de cada distribución va como Revisado (lo explico en cómo pruebo y reviso las guías).
[WARN] Hay una prueba de concepto pública en GitHub, enlazada por The Hacker News; su primer commit es del día 13. No la he ejecutado: en un servidor con webs de verdad, no. Quien quiera verla, en una máquina virtual de usar y tirar.
Qué es Vghost, en corto
vhost es la parte del kernel que acelera la red, el almacenamiento y el vsock de las máquinas virtuales. QEMU le dice dónde están los anillos de cada cola virtio, y vhost guarda en caché la traducción de esas direcciones para no repetirla en cada acceso.
El commit del arreglo lo explica: la caché se vacía en varios casos, pero no cuando VHOST_SET_VRING_ADDR cambia los anillos ni cuando VHOST_SET_VRING_NUM cambia su tamaño. vhost sigue usando la traducción vieja y accede a memoria fuera de la región que de verdad está mapeada.
No privilege is required beyond opening a device node: several distributions ship /dev/vhost-vsock and /dev/vhost-net mode 0666 (the systemd default udev rules), while others use 0660 root:kvm.
Tencent Zhuque Lab, informe de Vghost (12/10/2026)
Viene de lejos: la caché entró en Linux 4.11 (2017) y un cambio de la 5.9 (2020) aplazó la comprobación de direcciones. Según Tencent, su sistema Corvus AI lo encontró en dos horas. El parche, de Jun Yang, lleva la línea Assisted-by: tencentos-corvus-ai:kimi-k3.
- Root en el anfitrión. Basta con abrir uno de los dos nodos. Tencent lo reprodujo en Ubuntu 26.04, RHEL 9.8, Amazon Linux 2023, Azure Linux 3.0 y Oracle Linux 10.2. En Ubuntu necesitó un usuario del grupo
kvm; en los otros cuatro, cualquiera. - Salir de la máquina virtual. Exige un IOMMU virtual con
iommu_platformy vhost en modo device-IOTLB. Para ese camino no hay arreglo provisional, según The Hacker News: solo el kernel corregido.
Dónde está el parche y dónde no
El registro del CVE da el arreglo en siete ramas estables, de la 5.10.265 a la 7.1.9. La 6.8 de Ubuntu no está entre ellas ni entre las ramas longterm de kernel.org: no hay una 6.8.x corregida que tomar. Depende de que Canonical lo meta en la suya.
Del commit a mi servidor · avisos y dpkg.log
2026-08-04
Arreglo en la rama principal
Commit de845981, de Jun Yang (fechado el día 3), firmado también por Michael S. Tsirkin, mantenedor de vhost.
2026-08-21 y 31
CVE publicado; Amazon Linux corregido
El 31, los kernels de Amazon Linux 2 y 2023, según su ficha del CVE.
2026-10-12 y 13
Informe de Tencent; Ubuntu, pendiente
El rastreador de Ubuntu marca la 24.04 «Vulnerable, work in progress»; sus datos dejan el arreglo pendiente para 6.8.0-148.148. La 22.04 ya lo tiene.
2026-10-15 06:06 UTC
Instalado aquí el 147
Lo trae unattended-upgrades. No lleva el arreglo.
Las notas no cuadran: 8,8 sobre 10 para el equipo de CVE del kernel, 8,7 para Red Hat, 7,8 para Amazon; Ubuntu le da prioridad media. Para el registro del CVE, el atacante típico es la cuenta del grupo kvm con la que libvirt arranca QEMU, o un huésped malicioso.
Mi kernel: el que corre y el que espera
Busqué el arreglo en los dos registros de cambios, por el CVE y por el asunto del commit, por si Ubuntu lo hubiera metido sin nombrarlo:
# El que corre y los que estan instalados (ii), no los que dejaron config
uname -r
dpkg -l 'linux-image-6.8.0-*' | awk '/^ii/{print $2, $3}'
# El arreglo, por CVE o por el asunto del commit
for v in 138 147; do
f=/usr/share/doc/linux-modules-6.8.0-$v-generic/changelog.Debian.gz
echo "$v: $(zgrep -c -e CVE-2026-74580 -e 'vring metadata cache' $f)"
done
# 6.8.0-138-generic
# linux-image-6.8.0-138-generic 6.8.0-138.138
# linux-image-6.8.0-147-generic 6.8.0-147.147
# 138: 0
# 147: 0
Cero en los dos. Ubuntu lo espera en el 148, y la API de Launchpad no devuelve todavía ningún paquete con ese número en el archivo. Reiniciar hoy me llevaría al 147: un kernel más nuevo con el mismo fallo.
Y una corrección. En la entrada de curl dije que esperaba reinicio el kernel 146. Ya ni existe: unattended-upgrades lo desinstaló el día 15 al meter el 147. Instalado sigue sin ser lo mismo que en uso, como en la de algif_aead.
Quién puede abrir /dev/vhost-net aquí
Lo que pide la prueba de concepto es abrir el nodo. Así que miré quién puede, y lo intenté con un usuario sin privilegios:
# Permisos, dueno y grupo de los dos nodos
stat -c '%n %a %U:%G' /dev/vhost-net /dev/vhost-vsock
# Quien esta en kvm: miembros y usuarios con kvm de grupo principal (993)
getent group kvm
awk -F: '$4==993' /etc/passwd
# Un usuario sin privilegios intenta abrirlo
sudo -u nobody python3 -c 'import os; os.open("/dev/vhost-net", os.O_RDWR)'
# Modulos vhost cargados despues del intento
lsmod | grep -c '^vhost'
# /dev/vhost-net 660 root:kvm
# /dev/vhost-vsock 660 root:kvm
# kvm:x:993:
# PermissionError: [Errno 13] Permission denied: '/dev/vhost-net'
# 0
Solo root. El grupo kvm está vacío, y el usuario normal se lleva un EACCES antes de que se cargue nada. Aquí, hoy, Vghost no le sirve a nadie para subir a root. Pero el módulo está a un open() de root de cargarse.
Vghost en el servidor web · 16/10/2026
138
KERNEL EN USO
sin el arreglo
147
INSTALADO
tampoco lo lleva
0
EN EL GRUPO KVM
solo root abre
0
MÓDULOS VHOST
cargados ahora
Por qué 0660 aquí y 0666 en otros
Los permisos los pone udev, desde 50-udev-default.rules, donde /dev/kvm y los dos nodos de vhost toman el mismo modo. systemd lo trae a 0666 por defecto (la opción dev-kvm-mode de la v255), y Ubuntu lo compila con 0660, igual que Debian.
Eso cuadra con la tabla de Tencent: el /dev/vhost-vsock de Ubuntu 26.04 era 0660 y el de las otras cuatro, 0666. Y quién entra en kvm depende de lo que instales: el postinst de libvirt-daemon-system, que bajé sin instalar, crea libvirt-qemu con kvm como grupo principal.
[INFO] Los dos nodos tienen fecha del 15 de octubre a las 06:06:21, como /dev/kvm y /dev/fuse: un segundo después de que unattended-upgrades actualizara udev, systemd reinició systemd-udevd. Por eso no propongo un chmod a mano; aquí udev rearranca sin pedir permiso.
Lo que propongo y no he aplicado
Aquí nadie usa vhost: no hay QEMU ni libvirt instalados y Docker no tiene contenedores. Lo más limpio es que no se cargue, como hizo Ubuntu con algif_aead en abril. Este es el fichero; no lo he puesto en /etc/modprobe.d, lo decide quien administra la máquina:
# CVE-2026-74580 (Vghost). Este servidor no ejecuta maquinas virtuales:
# nadie necesita vhost. Hasta arrancar un kernel con el arreglo (Ubuntu
# lo espera en 6.8.0-148.148), que no se cargue ni al abrir /dev/vhost-net
# o /dev/vhost-vsock. Se bloquea tambien vhost, el nucleo donde esta el
# fallo: si no, modprobe lo carga como dependencia antes del /bin/false.
install vhost /bin/false
install vhost_net /bin/false
install vhost_vsock /bin/false
install vhost_vdpa /bin/false
La primera línea es la que importa, y la añadí después de probar sin ella: con solo las otras tres, modprobe -n enseñaba que cargaría tap, vhost_iotlb y vhost antes del /bin/false de vhost_net. El módulo con el fallo se quedaba dentro. Con ella:
# -n: solo ensena lo que haria. Sin sudo; no carga nada.
# Hoy, lo que se cargaria al abrir /dev/vhost-net
modprobe -n -v vhost_net
# insmod .../kernel/drivers/net/tap.ko.zst
# insmod .../kernel/drivers/vhost/vhost_iotlb.ko.zst
# insmod .../kernel/drivers/vhost/vhost.ko.zst
# insmod .../kernel/drivers/vhost/vhost_net.ko.zst
# Con el fichero propuesto en una copia de modprobe.d (-C)
modprobe -n -v -C ./modprobe.d char-major-10-238
# insmod .../kernel/drivers/net/tap.ko.zst
# insmod .../kernel/drivers/vhost/vhost_iotlb.ko.zst
# install /bin/false
# install /bin/false
char-major-10-238 es el alias de vhost_net en modules.alias que corresponde al número del nodo. Contra el kernel 147, con -S, dio lo mismo. Red Hat, en su ficha, propone solo esa primera línea, con /bin/true; prefiero /bin/false, como el bloqueo de kmod, para que el fallo se vea.
Donde el nodo salga 0666, o haya en kvm cuentas que no lo necesitan, Tencent recomienda quitar el acceso. Esta regla debería dejarlo solo para root desde el arranque (para eso lleva static_node, como la original), pero de ella solo he comprobado la sintaxis:
# En /etc/udev/rules.d/. No aplicada en este servidor: aqui kvm esta vacio.
KERNEL=="vhost-net", GROUP="root", MODE="0600", OPTIONS+="static_node=vhost-net"
KERNEL=="vhost-vsock", GROUP="root", MODE="0600", OPTIONS+="static_node=vhost-vsock"
# udevadm verify 99-vhost-solo-root.rules
# 1 udev rules files have been checked.
# Success: 1
# Fail: 0
Nada de esto descarga un módulo ya cargado: para eso Red Hat indica modprobe -r, con las máquinas virtuales paradas. Y con huéspedes, la regla no sirve contra el escape (QEMU necesita el nodo); bloquear vhost entero sí corta ese camino, al precio que avisa Red Hat: red y discos virtuales más lentos, o máquinas que no arrancan.
Comprobación
Este guion junta lo anterior y solo lee. Hoy da esto; con el fichero puesto, la última línea debería decir install /bin/false:
#!/bin/sh
# Exposicion a CVE-2026-74580 (Vghost) en esta maquina. Solo lee: no abre
# los dispositivos ni carga modulos. Sin root ve casi todo.
echo "kernel en uso: $(uname -r)"
for n in /dev/vhost-net /dev/vhost-vsock; do
# 0666 = cualquier usuario puede abrirlo; 0660 = solo el grupo
[ -e "$n" ] && stat -c '%n %a %U:%G' "$n" || echo "$n no existe"
done
# Quien puede abrirlos por grupo: miembros secundarios y primarios
g=$(stat -c %G /dev/vhost-net 2>/dev/null)
gid=$(getent group "$g" | cut -d: -f3)
echo "grupo $g, miembros: $(getent group "$g" | cut -d: -f4)" \
"primarios: $(awk -F: -v g="$gid" '$4==g{printf "%s ", $1}' /etc/passwd)"
# Si el modulo ya esta cargado, bloquearlo en modprobe no basta
echo "modulos vhost cargados: $(lsmod | awk '/^vhost/{printf "%s ", $1}')"
# Lo que haria modprobe al abrir /dev/vhost-net (en seco)
echo "modprobe -n vhost_net: $(modprobe -n -v vhost_net 2>&1 | tail -1)"
# kernel en uso: 6.8.0-138-generic
# /dev/vhost-net 660 root:kvm
# /dev/vhost-vsock 660 root:kvm
# grupo kvm, miembros: primarios:
# modulos vhost cargados:
# modprobe -n vhost_net: insmod /lib/modules/6.8.0-138-generic/kernel/drivers/vhost/vhost_net.ko.zst
Vuelta atrás
De hoy no hay nada que deshacer: solo he leído, y el paquete de libvirt sigue sin instalar en un directorio de trabajo. Deshacer la propuesta es borrar el fichero de /etc/modprobe.d, sin reiniciar. La regla de udev se quita igual; sus permisos se van en el siguiente arranque.
Con el 148 arrancado, el fichero sobra. Que no se quede olvidado como el de algif_aead, ahí desde el 30 de abril sobre un kernel que ya no lo necesita.
Qué no he probado
- La prueba de concepto, ni aquí ni en otra máquina.
- Abrir
/dev/vhost-netcomo root: cargaría el módulo, que es justo lo que no quería. - El escape desde una máquina virtual. Aquí no hay ninguna.
- El kernel 6.8.0-148: no está publicado.
- La regla de udev en un arranque real, ni si gana siempre a la de
50-udev-default.rules. - Contenedores con acceso a
/dev/vhost-*. En este servidor no hay ninguno. - El homelab, la Machinist de la comparativa de AMD e Intel: no lo he mirado.
- Nada en ARM ni en otra versión de Ubuntu.
Me queda una duda. La prioridad media de Ubuntu cuadra con un servidor como este, con kvm vacío. En una máquina con libvirt y huéspedes de terceros no la entiendo: ahí el 148 corre prisa. Más guías así en el hub de Ubuntu y Linux.
Actualización del 2 de noviembre de 2026: otro fallo de kernel sin arreglo en Ubuntu 24.04, el CVE-2026-98432, tiene una mitigación de Red Hat que probé aparte: la regla de nftables, probada.
$ tail -f comentarios.log
La conversación empieza aquí
Escribir un comentario ↓[esperando] 0 mensajes en el hilo
Nadie ha escrito todavía. Si lo has probado en tu máquina, cuenta qué te salió: otra versión u otro resultado también ayudan.