From: sashiko-bot@kernel.org
To: "Jann Horn" <jannh@google.com>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH] KVM: SEV: Fix page dirtying in sev_gmem_post_populate()
Date: Mon, 10 Aug 2026 15:50:00 +0000 [thread overview]
Message-ID: <20260810155001.5CAC21F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260810-x86-kvm-setpagedirty-v1-1-85f180892d4f@google.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Leaked SEV-SNP pages (via snp_leak_pages) are incorrectly returned to the buddy allocator, causing host panics (RMP violations) upon reuse.
- [High] Unprivileged host userspace can trigger a kernel warning (WARN_ON_ONCE) in sev_gmem_post_populate() by passing a NULL user address.
--
--- Patch [1]: [PATCH] KVM: SEV: Fix page dirtying in sev_gmem_post_populate() ---
commit 6e5ffd2f92a045c6125ad2d714ea329e1a9b8c9a
Author: Jann Horn <jannh@google.com>
KVM: SEV: Fix page dirtying in sev_gmem_post_populate()
This patch fixes a potential use-after-free by replacing set_page_dirty()
with set_page_dirty_lock() for pages obtained from get_user_pages_fast().
This ensures the page's mapping cannot concurrently go away during the
dirtying process.
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 0f0ea7896af5b..49feef14787af 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -2337,7 +2337,7 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
> bool assigned = false;
> int level;
> int ret;
>
> if (WARN_ON_ONCE(sev_populate_args->type != KVM_SEV_SNP_PAGE_TYPE_ZERO && !src_page))
[Severity: High]
This isn't a bug introduced by this patch, but can an unprivileged host
userspace process trigger this WARN_ON_ONCE by passing a NULL user address?
If a userspace process invokes the KVM_SEV_SNP_LAUNCH_UPDATE ioctl with
params.type == KVM_SEV_SNP_PAGE_TYPE_CPUID and params.uaddr == 0, the
snp_launch_update() function computes src = NULL and bypasses the
PAGE_ALIGNED check:
arch/x86/kvm/svm/sev.c:snp_launch_update() {
src = params.type == KVM_SEV_SNP_PAGE_TYPE_ZERO ? NULL :
u64_to_user_ptr(params.uaddr);
if (!PAGE_ALIGNED(src))
return -EINVAL;
}
Since 0 is page-aligned, src remains NULL. When kvm_gmem_populate() is
subsequently called, it skips fetching user pages because src is NULL:
virt/kvm/guest_memfd.c:kvm_gmem_populate() {
if (src) {
unsigned long uaddr = (unsigned long)src + i * PAGE_SIZE;
...
}
}
This leaves src_page as NULL when it is passed to sev_gmem_post_populate(),
which triggers the WARN_ON_ONCE. Does this allow a malicious user to trigger
a host-side denial of service if the kernel boots with panic_on_warn?
> return -EINVAL;
[ ... ]
> @@ -2381,15 +2381,15 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
> * Copy this page back into the source buffer so userspace can use this
> * information to provide information on which CPUID leaves/fields
> * failed CPUID validation.
> */
> if (ret && !snp_page_reclaim(kvm, pfn) &&
[Severity: Critical]
This is a pre-existing issue, but does snp_page_reclaim() properly manage
reference counts for leaked pages?
If snp_page_reclaim() fails, it permanently leaks the page via
snp_leak_pages(). However, the page is added to the snp_leaked_pages_list
without taking an additional reference:
arch/x86/virt/svm/sev.c:__snp_leak_pages() {
if (likely(!PageCompound(page)) || ...)
list_add_tail(&page->buddy_list, &snp_leaked_pages_list);
}
For pages from guest_memfd, the owning subsystem controls the reference. When
operations drop references to the leaked folio (such as when the file is
closed or truncated), the reference count can drop to zero:
virt/kvm/guest_memfd.c:__kvm_gmem_populate() {
out_put_folio:
folio_put(folio);
}
Could this cause the leaked SEV-SNP page to be erroneously returned to the
buddy allocator while still in a hardware-enforced private state, leading to
fatal RMP violations upon subsequent reuse?
> sev_populate_args->type == KVM_SEV_SNP_PAGE_TYPE_CPUID &&
> sev_populate_args->fw_error == SEV_RET_INVALID_PARAM) {
> void *src_vaddr = kmap_local_page(src_page);
> void *dst_vaddr = kmap_local_pfn(pfn);
>
> memcpy(src_vaddr, dst_vaddr, PAGE_SIZE);
> - set_page_dirty(src_page);
> + set_page_dirty_lock(src_page);
>
> kunmap_local(dst_vaddr);
> kunmap_local(src_vaddr);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260810-x86-kvm-setpagedirty-v1-1-85f180892d4f@google.com?part=1
next prev parent reply other threads:[~2026-08-10 15:50 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-10 15:33 [PATCH] KVM: SEV: Fix page dirtying in sev_gmem_post_populate() Jann Horn
2026-08-10 15:50 ` sashiko-bot [this message]
2026-08-10 16:29 ` Sean Christopherson
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=20260810155001.5CAC21F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=jannh@google.com \
--cc=kvm@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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.