Thread (145 messages) flat view 145 messages, 11 authors, 6d ago

Re: [PATCH v10 09/41] KVM: guest_memfd: Filter both shared and private when invalidating

From: Sean Christopherson <seanjc@google.com>
Date: 2026-08-26 13:53:16
Also in: kvm, linux-coco, linux-doc, linux-kselftest, linux-mm, lkml
Subsystem: kernel virtual machine (kvm), kvm guest_memfd, the rest · Maintainers: Paolo Bonzini, Sean Christopherson, Linus Torvalds

On Wed, Aug 26, 2026, Ackerley Tng wrote:
Xiaoyao Li [off-list ref] writes:
quoted
On 8/26/2026 2:55 AM, Sean Christopherson wrote:
quoted
On Tue, Aug 25, 2026, Michael Roth wrote:
quoted
On Wed, Aug 26, 2026 at 12:13:47AM +0800, Xiaoyao Li wrote:
quoted
On 8/20/2026 9:32 AM, Sean Christopherson wrote:
quoted
And vice versa, a PUNCH_HOLE on a SHARED gmem (if userspace is
using an INIT_SHARED gmem for the shared branch of a memslot) could invalidate the
PRIVATE mappings (of a different gmem instance).
I'm wondering now how this could happen.

the requirement for PUNCH_HOLE on gmem to trigger mapping invalidation is
the gmem is bound with the memslot. But how can a memslot bound with two
gmem instances?
I think this is for when userspace uses an mmap'able guest_memfd instance
to handle shared memory, and a 'normal' guest_memfd instance for private
memory. Each instance is bound to the same memslot/GPA range, and
KVM_SET_MEMORY_ATTRIBUTES handles switching between the 2.
What I didn't figure out is exactly how the two gmem instances are bound
to the same memslot.

The case I can imagine is

1. create gmem1 with GUEST_MEMFD_FLAG_MMAP and
GUEST_MEMFD_FLAG_INIT_SHARED, and get fd1. mmap the returned fd1 to get
a hva.

2. create gmem2 to get a fd2.

3. call KVM_SET_USER_MEMORY_REGION2 with KVM_MEM_GUEST_MEMFD flag. Pass
the @hva from 1) to 'userspace_addr' field and pass the gmem fd2 to
'guest_memfd' field.

However, with this case, only gmem2 is bound to the memslot while gmem1
is not. Following PUNCH_HOLE on gmem1 doesn't invalidate any mappings
because the f->bindings of it is empty.

Do I miss anything?
Oh, I misread your question.  You were specifically asking about a PUNCH_HOLE in
a SHARED gmem instance over-invalidating PRIVATE mappings.  You're right, that
wouldn't happen because the invalidations would come in via mmu_notifiers, not
from KVM.
I think Xiaoyao is right about this, the "vice versa" part is wrong,
Ya.
Is this just a case of user error? That with gmem_in_place_conversion,
userspace should not use userspace_addr from something other than the
gmem for the same memslot?
Yes.  It's not just invalidations that will go sideways, KVM accesses to guest
memory won't hit the same physical page as actual guest accesses.

Huh.  But that isn't strictly guaranteed, because userspace could bind to a
memslot that isn't configured with GUEST_MEMFD_FLAG_MMAP, in which case SHARED
faults will go through the VMA, not kvm_mmu_faultin_pfn_gmem().  It's a bit early
in the morning, but off the top of my head, I can't think of any reason we need
to support such a setup.  If userspace really, really wants to use a separate
mapping, they could DELETE+CREATE an equivalent memslot without the guest_memfd
file descriptor.

So I think we should do this?
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 9c2d52bdf25e..86f53e53a136 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -1013,7 +1013,7 @@ int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot,
 	 */
 	WRITE_ONCE(slot->gmem.file, file);
 	slot->gmem.pgoff = start;
-	if (kvm_gmem_supports_mmap(inode))
+	if (gmem_in_place_conversion || kvm_gmem_supports_mmap(inode))
 		slot->flags |= KVM_MEMSLOT_GMEM_ONLY;
 
 	xa_store_range(&f->bindings, start, end - 1, slot, GFP_KERNEL);
Regardless, the key aspect of all this is that in-place conversion is brand new
functionality, so we don't have to ensure backwards compatibility.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help