
Parche de vulnerabilidad CVE-2026-53359
dump_tool.py encuentra los offsets automáticamente; para saber cómo usarlo, lee el código tú mismo.
CVE-2026-53359 (Januscape) es una vulnerabilidad de use-after-free (UAF) en el MMU sombra de KVM del kernel de Linux.
Cuando la función kvm_mmu_get_page() busca una tabla de páginas sombra reutilizable en la tabla hash, solo compara el gfn (número de marco de página física de la máquina invitada) y no compara el role (rol de la tabla de páginas / rol de MMU). Esto hace que se reutilice por error una tabla de páginas con un rol no coincidente, lo que provoca un UAF.
修复前(有漏洞):
┌──────────────────────────────────────┐
│ kvm_mmu_get_page() │
│ 遍历哈希表 │
│ if (child->gfn == gfn) │
│ return child ← 只比较gfn! │
│ 角色不匹配也复用 → UAF! │
│ 分配新页(安全) │
└──────────────────────────────────────┘
En el commit 81ccda30b4e8 del kernel upstream se añadió una comparación de role:
// 修复前
if (... && spte_to_child_sp(*sptep)->gfn == gfn)
// 修复后
if (... && spte_to_child_sp(*sptep)->gfn == gfn
&& spte_to_child_sp(*sptep)->role.word == role.word)
No modifica el código fuente del kernel ni reemplaza funciones; en su lugar, modifica directamente las instrucciones vulnerables en la memoria del kernel en ejecución.
二进制层面:
偏移 0x104: 49 39 47 28 cmp %rax, 0x28(%r15) ← 比较 gfn
偏移 0x108: 0f 84 9f 01 00 00 je +0x19f ← 匹配就跳转复用
打补丁后:
偏移 0x108: 66 0f 1f 44 00 00 NOP × 6 ← 什么也不做
修复后:
┌──────────────────────────────────────┐
│ kvm_mmu_get_page() │
│ 遍历哈希表 │
│ if (child->gfn == gfn) │
│ NOP(跳转被抹掉,滑过去) │
│ 分配新页(强制走安全路径) │
│ → 不复用 = 不触发 UAF = 漏洞修复 │
└──────────────────────────────────────┘
kvm_mmu_get_page mediante kallsyms_lookup_nametext_poke (API de modificación en caliente del código del kernel) mediante kallsyms_lookup_namestop_machine para garantizar una modificación seguraje de 6 bytes por 6 bytes de NOP con text_poketext_poke| Solución | Problema |
|---|---|
| Actualizar el kernel y reiniciar | Requiere reiniciar el host; todas las VM se detienen |
| nested=0 (desactivar la virtualización anidada) | Se pierde la virtualización anidada; no se pueden ejecutar VM dentro de VM |
| Enfoque kpatch | Requiere kernel-debuginfo; la compilación tarda de 10 a 20 minutos; dependencias complejas |
| Sustitución de funciones con ftrace | kvm_mmu_get_child_sp es inlineada por GCC; no tiene entrada de función independiente |
| Mi solución con text_poke | Compila en 10 segundos; un solo archivo .c; modifica directamente la instrucción vulnerable |
| Funcionalidad | Impacto |
|---|---|
| Reinicio del host | No necesario |
| Reinicio/migración de VM | No necesario |
| Virtualización anidada (VM dentro de VM) | Se conserva; uso normal |
| Crear/iniciar máquinas virtuales | Normal |
| Fusión de memoria KSM | Sin impacto; función independiente |
| Rendimiento de CPU | Casi sin impacto (NOP no consume CPU) |
| Memoria | Las tablas de páginas sombra ya no se reutilizan; cada vez se asigna una página nueva, ocupando un poco más de memoria |
| Descarga del módulo KVM | Normal (rmmod restaura automáticamente el código original) |
| Requisito | Descripción |
|---|---|
| Versión del kernel | Linux 4.18+ (CentOS 8 / RHEL 8 / Rocky 8, etc.) |
| Entorno de compilación | kernel-devel + gcc + make |
| Reinicio del host | No necesario |
| Apagado de VM | No necesario |
| Virtualización anidada | Se conserva |
# 编译
make
# 加载热补丁
insmod KVM-XJ.ko
# 查看状态
dmesg | grep KVM-XJ
cat /sys/module/kvm_intel/parameters/nested # 应该还是 1
lsmod | grep KVM_XJ
# 卸载(恢复原始代码)
rmmod KVM_XJ
Distintas versiones del kernel tienen distintas optimizaciones de compilación, por lo que el offset de la instrucción je también varía. Usa dump_tool.py para analizarlo automáticamente:
# 1. 从母鸡下载 kvm.ko
scp root@母鸡:/lib/modules/.../kvm.ko.xz .
xz -d kvm.ko.xz
# 2. 运行分析工具
python dump_tool.py kvm.ko
# 3. 工具会输出 patch 偏移,修改 KVM-XJ.c 中的 0x108
| Versión del kernel | Offset de je | Estado |
|---|---|---|
| 4.18.0-496.el8.x86_64 | 0x108 | Probado |
| 4.18.0-358.el8.x86_64 | 0xe8 | Probado |