Re: [PATCH RFC v2 2/4] KVM: guest_memfd: implement folio migration for non-confidential VMs

"Garg, Shivank" <[email protected]> Wed, 29 Jul 2026 12:10:21 +0000
Newsgroups dev.linux.lists.sashiko-reviews,org.kernel.vger.kvm
Message-ID <[email protected]>
On Tue, 2026-07-28 at 09:20 +0000, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] Pre-existing ABBA deadlock between `mapping->invalidate_lock` and `folio_lock` via `kvm_gmem_error_folio`.
> - [High] Unpaired `kvm_mmu_invalidate_start` due to lockless `f->bindings` xarray modification during `kvm_gmem_unbind`.
> --
> 
> --- Patch [2]: [PATCH RFC v2 2/4] KVM: guest_memfd: implement folio migration for non-confidential VMs ---
> commit cb30b8cd0e73b5e7ad80d0285306810cbf4d963e
> Author: Shivank Garg <[email protected]>
> KVM: guest_memfd: implement folio migration for non-confidential VMs
> 
> Implement kvm_gmem_migrate_folio using filemap_migrate_folio for
> non-confidential VMs but don't enable it yet. Guest_memfd mappings are still
> marked unmovable, so MM never calls it.
> 
> > diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> > index d3b1186b03b3a..ec881cabe8e3e 100644
> > --- a/virt/kvm/guest_memfd.c
> > +++ b/virt/kvm/guest_memfd.c
> [ ... ]
> > +	start = src->index;
> > +	end = start + folio_nr_pages(src);
> > +
> > +	kvm_gmem_invalidate_start(inode, start, end);
> > +
> > +	/*
> > +	 * For non-confidential guests the folio is host-readable, so
> > +	 * filemap_migrate_folio() can copy the contents itself via
> > +	 * folio_mc_copy().
> > +	 * For confidential guests, this would need firmware assistance.
> > +	 */
> > +	ret = filemap_migrate_folio(mapping, dst, src, mode);
> > +
> > +	kvm_gmem_invalidate_end(inode, start, end);
> 
> [Severity: High]
> This is a pre-existing issue, but does the iteration over bindings here race
> with kvm_gmem_unbind?
> 
> If a guest_memfd file is being closed and its refcount reaches zero
> concurrently, kvm_gmem_unbind takes the !file branch and removes the memslot
> from f->bindings without taking filemap_invalidate_lock.
> 
> Could this lockless modification happen between the calls to
> kvm_gmem_invalidate_start and kvm_gmem_invalidate_end?
> 
> If f->bindings is modified during this window, __kvm_gmem_invalidate_end
> might fail to find the binding and skip the slot, resulting in an unpaired
> start call. This would permanently leak the mmu_invalidate_in_progress
> counter and cause guest page faults to hang indefinitely.

This is valid point.
So, IIUC, I can remove !file branch and take an invalidate lock for slots-
>gmem.file, if I can't get reference on gmem.file.

	CLASS(gmem_get_file, file)(slot);
	struct file* f = file ? file: slot->gmem.file;

	filemap_invalidate_lock(f->f_mapping);
	__kvm_gmem_unbind(slot, f->private_data);
	filemap_invalidate_unlock(f->f_mapping);

This would prevent it from removing the memslot.

> > +
> > +	filemap_invalidate_unlock_shared(mapping);
> > +	return ret;
> >  }
> > +#else
> > +#define kvm_gmem_migrate_folio NULL
> > +#endif
> >  
> >  static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *folio)
> >  {
> 
> [Severity: High]
> This isn't a bug introduced by this patch, but does kvm_gmem_error_folio
> have the exact same ABBA deadlock that you correctly avoided above in
> kvm_gmem_migrate_folio?
> 
> In kvm_gmem_error_folio, it unconditionally calls
> filemap_invalidate_lock_shared while the caller (memory_failure) already
> holds the folio lock.
> 
> Meanwhile, the opposing truncation path in kvm_gmem_punch_hole establishes
> the strict lock ordering of acquiring mapping->invalidate_lock followed by
> locking the folio.
> 
> Could a concurrent fallocate PUNCH_HOLE and a memory failure on the same
> guest_memfd file deadlock the kernel here?
> 

Hao Zhang is actively working on this issue. [1]

[1] https://lore.kernel.org/all/[email protected]

Thanks,
Shivank