[PATCH] KVM: x86/mmu: Fix double-free of mmu_page_header_cache on vendor module reload

From: Phil Rosenthal

Date: Sat Jul 18 2026 - 09:03:49 EST


mmu_destroy_caches() frees pte_list_desc_cache and mmu_page_header_cache
but does not set the pointers to NULL. Because they are static globals in
the always-resident kvm.ko, they survive a vendor module unload/reload
cycle. If a reload of kvm_intel/kvm_amd fails because the first
kmem_cache allocation returns NULL (e.g., under memory pressure), the
error path calls mmu_destroy_caches() again. On that second call,
mmu_page_header_cache still points to the already-freed cache, resulting
in a double-free.

Concrete trigger:
1. Load kvm.ko and vendor module (both caches created).
2. Unload vendor module [leave kvm.ko loaded] (caches freed, pointers left dangling).
3. Reload vendor module; first cache creation fails → error path
double-frees mmu_page_header_cache.

Fix by resetting both pointers to NULL immediately after destroying the
caches, making the cleanup idempotent.

The bug was verified on a KASAN-enabled kernel by instrumenting
kvm_mmu_vendor_module_init() to force the first allocation to fail on a
second load, simulating OOM; KASAN reported:

BUG: KASAN: slab-use-after-free in kvm_mmu_vendor_module_init+0x1ba/0x1e0 [kvm]
...
Allocated by task 11693: <- first load
Freed by task 11696: <- previous unload

Signed-off-by: Phil Rosenthal <phil@xxxxxxx>
Tested-by: Phil Rosenthal <phil@xxxxxxx>
---
arch/x86/kvm/mmu/mmu.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 234d0a95abf5..ec49ce98a449 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -7574,7 +7574,9 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
static void mmu_destroy_caches(void)
{
kmem_cache_destroy(pte_list_desc_cache);
+ pte_list_desc_cache = NULL;
kmem_cache_destroy(mmu_page_header_cache);
+ mmu_page_header_cache = NULL;
}
static void kvm_wake_nx_recovery_thread(struct kvm *kvm)
-- 2.47.3