
Correção da vulnerabilidade CVE-2026-53359
dump_tool.py encontra os offsets automaticamente; para saber como usar, veja o código você mesmo.
CVE-2026-53359 (Januscape) é uma vulnerabilidade de use-after-free (UAF) na shadow MMU do KVM do kernel Linux.
A função kvm_mmu_get_page() procura tabelas de páginas sombra reutilizáveis na tabela hash comparando apenas o gfn (número do quadro de página física do guest), sem comparar o role (papel da tabela de páginas/papel da MMU), fazendo com que tabelas de páginas com papéis incompatíveis sejam reutilizadas incorretamente, resultando em UAF.
修复前(有漏洞):
┌──────────────────────────────────────┐
│ kvm_mmu_get_page() │
│ 遍历哈希表 │
│ if (child->gfn == gfn) │
│ return child ← 只比较gfn! │
│ 角色不匹配也复用 → UAF! │
│ 分配新页(安全) │
└──────────────────────────────────────┘
No commit 81ccda30b4e8 do kernel upstream, foi adicionada uma comparação 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)
Não modifica o código-fonte do kernel, não substitui funções; em vez disso, altera diretamente a instrução vulnerável na memória do kernel em execução.
二进制层面:
偏移 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 via kallsyms_lookup_nametext_poke via kallsyms_lookup_name (API de modificação a quente do código do kernel)stop_machine para pausar todas as CPUs, garantindo uma modificação seguratext_poke para substituir a instrução je de 6 bytes por 6 bytes de NOPtext_poke para restaurar a instrução original| 方案 | 问题 |
|---|---|
| Atualizar o kernel e reiniciar | Requer reiniciar o host; todas as VMs param |
| nested=0 (desativar a virtualização aninhada) | Perda da funcionalidade de virtualização aninhada; impossível executar VM dentro de VM |
| Método kpatch | Requer kernel-debuginfo; compilação leva de 10 a 20 minutos; dependências complexas |
| Substituição de função com ftrace | kvm_mmu_get_child_sp é inline pelo GCC; sem ponto de entrada de função independente |
| Minha solução com text_poke | Compila em 10 segundos; um único arquivo .c; modifica diretamente a instrução vulnerável |
| 功能 | 影响 |
|---|---|
| Reinício do host | Não é necessário |
| Reinício/migração de VM | Não é necessário |
| Virtualização aninhada (executar VM dentro de VM) | Preservada, uso normal |
| Criar/iniciar máquinas virtuais | Normal |
| Fusão de memória KSM | Sem impacto; funcionalidade independente |
| Desempenho da CPU | Quase sem impacto (NOP não consome CPU) |
| Memória | As tabelas de páginas sombra não são mais reutilizadas; uma nova página é alocada a cada vez, consumindo um pouco mais de memória |
| Descarregamento do módulo KVM | Normal (rmmod restaura automaticamente o código original) |
| 条件 | 说明 |
|---|---|
| Versão do kernel | Linux 4.18+ (CentOS 8 / RHEL 8 / Rocky 8, etc.) |
| Ambiente de compilação | kernel-devel + gcc + make |
| Reinício do host | Não é necessário |
| Parada de VMs | Não é necessário |
| Virtualização aninhada | Preservada |
# 编译
make
# 加载热补丁
insmod KVM-XJ.ko
# 查看状态
dmesg | grep KVM-XJ
cat /sys/module/kvm_intel/parameters/nested # 应该还是 1
lsmod | grep KVM_XJ
# 卸载(恢复原始代码)
rmmod KVM_XJ
Diferentes versões do kernel possuem otimizações de compilação diferentes, e o offset da instrução je também é diferente. Use o dump_tool.py para análise automática:
# 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
| 内核版本 | je 偏移 | 状态 |
|---|---|---|
| 4.18.0-496.el8.x86_64 | 0x108 | Testado |
| 4.18.0-358.el8.x86_64 | 0xe8 | Testado |