]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: Harden and prepare for modifying existing guest_memfd memslots
authorSean Christopherson <seanjc@google.com>
Tue, 2 Dec 2025 02:03:34 +0000 (18:03 -0800)
committerSean Christopherson <seanjc@google.com>
Tue, 2 Dec 2025 16:49:37 +0000 (08:49 -0800)
Unbind guest_memfd memslots if KVM commits a MOVE or FLAGS_ONLY memslot
change to harden against use-after-free, and to prepare for eventually
supporting dirty logging on guest_memfd memslots, at which point
FLAGS_ONLY changes will be expected/supported.

Add two separate WARNs, once to yell if a guest_memfd memslot is moved
(which KVM is never expected to allow/support), and again if the unbind()
is triggered, to help detect uAPI goofs prior to deliberately allowing
FLAGS_ONLY changes.

Link: https://patch.msgid.link/20251202020334.1171351-3-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
virt/kvm/kvm_main.c

index 7fea6ba91c1ef30427d9ad431a189f14a5c5ab10..32b6c6209b63883e4c6121c39d8dddcbe910bcf9 100644 (file)
@@ -1748,6 +1748,12 @@ static void kvm_commit_memory_region(struct kvm *kvm,
                kvm_free_memslot(kvm, old);
                break;
        case KVM_MR_MOVE:
+               /*
+                * Moving a guest_memfd memslot isn't supported, and will never
+                * be supported.
+                */
+               WARN_ON_ONCE(old->flags & KVM_MEM_GUEST_MEMFD);
+               fallthrough;
        case KVM_MR_FLAGS_ONLY:
                /*
                 * Free the dirty bitmap as needed; the below check encompasses
@@ -1756,6 +1762,15 @@ static void kvm_commit_memory_region(struct kvm *kvm,
                if (old->dirty_bitmap && !new->dirty_bitmap)
                        kvm_destroy_dirty_bitmap(old);
 
+               /*
+                * Unbind the guest_memfd instance as needed; the @new slot has
+                * already created its own binding.  TODO: Drop the WARN when
+                * dirty logging guest_memfd memslots is supported.  Until then,
+                * flags-only changes on guest_memfd slots should be impossible.
+                */
+               if (WARN_ON_ONCE(old->flags & KVM_MEM_GUEST_MEMFD))
+                       kvm_gmem_unbind(old);
+
                /*
                 * The final quirk.  Free the detached, old slot, but only its
                 * memory, not any metadata.  Metadata, including arch specific