From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Naveen N Rao <naveen@kernel.org>,
Alexandru Elisei <alexandru.elisei@arm.com>
Subject: Re: [PATCH v3] KVM: Skip gfn-based MMU notifier invalidations for guest_memfd-only memslots
Date: Fri, 13 Nov 2026 17:25:25 +0000 [thread overview]
Message-ID: <avdAIMDfgL_wy1rx@gremlin> (raw)
In-Reply-To: <20261113164000.467175-1-seanjc@google.com>
On Fri, Nov 13, 2026 at 08:40:00AM -0800, Sean Christopherson wrote:
> From: Alexandru Elisei <alexandru.elisei@arm.com>
>
> Don't invalidate gmem-only memslots when responding to MMU notifier
> invalidations, as the entire point of gmem-only memslots is so that KVM
> doesn't need a VMA to install mappings into KVM's MMU. Specifically,
> page faults are resolved by going straight to guest_memfd, using the gfn
> and the associated memslot's gmem.file. I.e. whether or not userspace
> happens to have valid mappings to the same gmem instance is irrelevant,
> as are any invalidations for those mappings.
>
> Note! The exception is KVM's gfn_to_pfn_cache implementation which isn't
> yet wired up to pull pfns directly from guest_memfd, i.e. still relies on
> userspace mappings/VMAs and thus need to be invalidated, e.g. to ensure KVM
> doesn't retain a kernel mapping+pointer to PRIVATE memory. However, as of
> commit da260bcb56fe ("KVM: pfncache: use a dedicated invalidation sequence
> for cache refresh"), GPC invalidation no longer relies on memslot lookups,
> because GPCs also support HVA-based mappings. I.e. KVM *must* be able to
> detect and handle relevant MMU notifier invalidations even if there is *no*
> memslot whatsoever.
>
> In addition to the obvious performance benefits, avoiding unnecessary and
> spurious SPTE zaps and TLB flushes will allow KVM to support features like
> ARM's Statistical Profiling Extension (SPE)[1] and x86's Secure AVIC[2],
> both of which rely on the pages *never* being unmapped from the stage-2
> page tables.
>
> Link: https://lore.kernel.org/all/20260903160623.315525-1-alexandru.elisei@arm.com [1]
> Link: https://lore.kernel.org/all/cover.1783490022.git.naveen@kernel.org [2]
> Cc: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> Cc: Naveen N Rao (AMD) <naveen@kernel.org>
> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
> [sean: rewrite changelog to capture the new gpc behavior]
> Signed-off-by: Sean Christopherson <seanjc@google.com>
Thanks a lot for this Sean + Alex! :)
Though, having local AI do a review pass on it flagged an issue (don't worry my
own analysis - not pasting some slop here :).
I think actually this might need an additional change for x86, since it doesn't
have a gmem-only check for the shadow MMU PTE prefetch:
direct_map()
-> direct_pte_prefetch()
-> __direct_pte_prefetch()
-> direct_pte_prefetch_many()
-> kvm_mmu_prefetch_sptes()
-> kvm_prefetch_pages()
-> get_user_pages_fast_only()
And a VMM that's doing something broken (i.e. trying to take advantage of this
as a vulnerability), could then intentionally set up a gmem-only slot to point
at ordinary anon memory, munmap(), and have a UAF on the underlying folio due to
no MMU notifier invalidation.
Fix would be something like:
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index cf4cb586f140..76350dc55d8f 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3172,6 +3172,9 @@ int kvm_prefetch_pages(struct kvm_memory_slot *slot, gfn_t gfn,
unsigned long addr;
gfn_t entry = 0;
+ if (kvm_memslot_is_gmem_only(slot))
+ return 0;
+
addr = gfn_to_hva_many(slot, gfn, &entry);
if (kvm_is_error_hva(addr))
return -1;
> ---
>
> v3: v1, but with a different changelog.
>
> v2: https://lore.kernel.org/all/20260714160411.302386-1-alexandru.elisei@arm.com
>
> v1: https://lore.kernel.org/all/20260615155244.183044-1-alexandru.elisei@arm.com
>
> virt/kvm/kvm_main.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index cf4cb586f140..599dea22afb8 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -601,6 +601,10 @@ static __always_inline kvm_mn_ret_t kvm_handle_hva_range(struct kvm *kvm,
> unsigned long hva_start, hva_end;
>
> slot = container_of(node, struct kvm_memory_slot, hva_node[slots->node_idx]);
> +
> + if (kvm_slot_has_gmem(slot) && kvm_memslot_is_gmem_only(slot))
> + continue;
> +
> hva_start = max_t(unsigned long, range->start, slot->userspace_addr);
> hva_end = min_t(unsigned long, range->end,
> slot->userspace_addr + (slot->npages << PAGE_SHIFT));
>
> base-commit: d21eef2084a9af87ac2a783bc7c2b175ba114e4e
> --
> 2.56.1.703.gf848ed807c-goog
>
--
Cheers, Lorenzo
prev parent reply other threads:[~2026-11-13 17:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 16:40 [PATCH v3] KVM: Skip gfn-based MMU notifier invalidations for guest_memfd-only memslots Sean Christopherson
2026-11-13 17:10 ` sashiko-bot
2026-11-13 17:17 ` Sean Christopherson
2026-11-13 17:36 ` sashiko-bot
2026-11-13 17:25 ` Lorenzo Stoakes (ARM) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=avdAIMDfgL_wy1rx@gremlin \
--to=ljs@kernel.org \
--cc=alexandru.elisei@arm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=naveen@kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.