
Correctif de vulnérabilité CVE-2026-53359
dump_tool.py automatise la recherche des offsets ; pour son utilisation, lisez le code.
CVE-2026-53359 (Januscape) est une vulnérabilité use-after-free (UAF) dans le shadow MMU de KVM du noyau Linux.
Lorsque la fonction kvm_mmu_get_page() recherche dans la table de hachage une table de pages fantômes réutilisable, elle ne compare que la gfn (numéro de cadre de page physique de l'invité), sans comparer la role (rôle de la table de pages / rôle MMU), ce qui provoque une réutilisation erronée d'une table de pages dont le rôle ne correspond pas et déclenche une UAF.
修复前(有漏洞):
┌──────────────────────────────────────┐
│ kvm_mmu_get_page() │
│ 遍历哈希表 │
│ if (child->gfn == gfn) │
│ return child ← 只比较gfn! │
│ 角色不匹配也复用 → UAF! │
│ 分配新页(安全) │
└──────────────────────────────────────┘
Le commit amont 81ccda30b4e8 a ajouté une ligne de comparaison 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)
Sans modifier le code source du noyau ni remplacer de fonction, on modifie directement l'instruction vulnérable dans la mémoire du noyau en cours d'exécution.
二进制层面:
偏移 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 modification à chaud du code noyau)stop_machine pour suspendre tous les CPU et garantir la sécurité de la modificationje de 6 octets par un NOP de 6 octets avec text_poketext_poke| Solution | Problème |
|---|---|
| Mise à niveau du noyau et redémarrage | Redémarrage de l'hôte requis, toutes les VMs sont arrêtées |
| nested=0 (désactivation de la virtualisation imbriquée) | Perte de la virtualisation imbriquée, impossible d'exécuter une VM dans une VM |
| Méthode kpatch | Nécessite kernel-debuginfo, compilation de 10 à 20 minutes, dépendances complexes |
| Remplacement de fonction via ftrace | kvm_mmu_get_child_sp est inlinée par GCC, sans entrée de fonction indépendante |
| Ma solution text_poke | Compilation en 10 secondes, un fichier .c, modification directe de l'instruction vulnérable |
| Fonctionnalité | Impact |
|---|---|
| Redémarrage de l'hôte | Non requis |
| Redémarrage / migration des VMs | Non requis |
| Virtualisation imbriquée (exécuter une VM dans une VM) | Conservée, utilisable normalement |
| Création / démarrage de machines virtuelles | Normal |
| Fusion de mémoire KSM | Aucun impact, fonctionnalité indépendante |
| Performances CPU | Quasiment aucun impact (NOP ne consomme pas de CPU) |
| Mémoire | Les tables de pages fantômes ne sont plus réutilisées, une nouvelle page est allouée à chaque fois, légère augmentation de la mémoire |
| Déchargement du module KVM | Normal (rmmod restaure automatiquement le code d'origine) |
| Condition | Description |
|---|---|
| Version du noyau | Linux 4.18+ (CentOS 8 / RHEL 8 / Rocky 8, etc.) |
| Environnement de compilation | kernel-devel + gcc + make |
| Redémarrage de l'hôte | Non requis |
| Arrêt des VMs | Non requis |
| Virtualisation imbriquée | Conservée |
# 编译
make
# 加载热补丁
insmod KVM-XJ.ko
# 查看状态
dmesg | grep KVM-XJ
cat /sys/module/kvm_intel/parameters/nested # 应该还是 1
lsmod | grep KVM_XJ
# 卸载(恢复原始代码)
rmmod KVM_XJ
Les optimisations de compilation diffèrent selon les versions du noyau, et l'offset de l'instruction je varie également. Utilisez dump_tool.py pour l'analyse automatique :
# 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
| Version du noyau | Offset de l'instruction je | Statut |
|---|---|---|
| 4.18.0-496.el8.x86_64 | 0x108 | Testé |
| 4.18.0-358.el8.x86_64 | 0xe8 | Testé |