[PATCH v6 06/43] KVM: x86/mmu: Bug the VM if gmem attributes are queried to determine max mapping level
From: Ackerley Tng via B4 Relay
Date: Thu May 07 2026 - 16:29:20 EST
From: Ackerley Tng <ackerleytng@xxxxxxxxxx>
When the maximum mapping level is queried, KVM's MMU lock is held, and
while the MMU lock is held, guest_memfd cannot take the
filemap_invalidate_lock() to look up the current shared/private state of
the gfn, for these reasons:
+ The MMU lock is a spinlock or rwlock and cannot be held while taking a
lock that can sleep.
+ In guest_memfd's code paths (such as truncate), the
filemap_invalidate_lock() is held while taking the MMU lock, and taking
the locks in reverse order would introduce a AB-BA deadlock.
Currently, the maximum mapping level is only queried from guest_memfd in
the process of recovering huge pages, if dirty logging is disabled on a
memslot. Dirty logging is not currently supported for guest_memfd, and
guest_memfd memslots also cannot be updated.
For now, bug the VM if guest_memfd needs to be queried to determine the
maximum mapping level. This guard can be removed if/when support is added.
Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
arch/x86/kvm/mmu/mmu.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index a80a876ab4ad6..153bcc5369985 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3357,6 +3357,15 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm, struct kvm_page_fault *fault,
max_level = fault->max_level;
is_private = fault->is_private;
} else {
+ /*
+ * Memory attributes cannot be obtained from guest_memfd while
+ * the MMU lock is held.
+ */
+ if (KVM_BUG_ON(static_call_query(__kvm_get_memory_attributes) ==
+ kvm_gmem_get_memory_attributes, kvm)) {
+ return 0;
+ }
+
max_level = PG_LEVEL_NUM;
is_private = kvm_mem_is_private(kvm, gfn);
}
--
2.54.0.563.g4f69b47b94-goog