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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox