[PATCH v5 5/6] KVM: guest_memfd: Establish memslot<=>guest_memfd bindings *after* memslot is ready
From: Sean Christopherson
Date: Mon Sep 21 2026 - 20:17:01 EST
Wait to bind a memslot to a guest_memfd instance until *after* the memslot
is fully prepared, as creating the binding in guest_memfd will effectively
expose the memslot to readers. As pointed out by Sashiko, binding the
memslot before it's ready to be exposed to the rest of the world can break
various memslot assumption and rules. E.g. x86 could observe a NULL rmap
pointer if a PUNCH_HOLE hit the guest_memfd after the binding was created,
but before KVM made it through kvm_prepare_memory_region().
Fixes: a7800aa80ea4 ("KVM: Add KVM_CREATE_GUEST_MEMFD ioctl() for guest-specific backing memory")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Sashiko Bot <sashiko-bot@xxxxxxxxxx>
Closes: https://lore.kernel.org/all/20260826170551.BEF801F000E9@xxxxxxxxxxxxxxx
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
virt/kvm/kvm_main.c | 44 +++++++++++++++++++++++---------------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 45b509f4e54b..90461880ff85 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1944,6 +1944,15 @@ static int kvm_set_memslot(struct kvm *kvm,
if (r)
goto err;
+ if (change == KVM_MR_CREATE && (new->flags & KVM_MEM_GUEST_MEMFD)) {
+ r = kvm_gmem_commit_memory_region(kvm, new);
+ if (r) {
+ kvm_arch_free_memslot(kvm, new);
+ kvm_destroy_dirty_bitmap(new);
+ goto err;
+ }
+ }
+
/*
* For DELETE and MOVE, the working slot is now active as the INVALID
* version of the old slot. MOVE is particularly special as it reuses
@@ -2121,32 +2130,25 @@ static int kvm_set_memory_region(struct kvm *kvm,
mem->guest_memfd_offset);
if (r)
goto out;
-
- r = kvm_gmem_commit_memory_region(kvm, new);
-
- /*
- * Drop the reference to the file, even on success. The file
- * pins KVM, not the other way 'round. Active bindings are
- * invalidated if the file is closed before memslots are
- * destroyed.
- */
-#ifdef CONFIG_KVM_GUEST_MEMFD
- fput(new->gmem.file);
-#endif
-
- if (r)
- goto out;
}
r = kvm_set_memslot(kvm, old, new, change);
- if (r)
- goto out_unbind;
- return 0;
-
-out_unbind:
+ /*
+ * Drop the reference to the gmem file, even on success. The file pins
+ * KVM, not the other way 'round. Active bindings are invalidated if
+ * the file is closed before memslots are destroyed.
+ */
+#ifdef CONFIG_KVM_GUEST_MEMFD
if (change == KVM_MR_CREATE && (mem->flags & KVM_MEM_GUEST_MEMFD))
- kvm_gmem_unbind(new);
+ fput(new->gmem.file);
+#endif
+
+ if (r)
+ goto out;
+
+ return 0;
+
out:
kfree(new);
return r;
--
2.55.0.1082.g2b9226bbc0-goog