From: sashiko-bot@kernel.org
To: "Paolo Bonzini" <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH 12/24] KVM: x86/mmu: move CPU-related fields to struct kvm_pagewalk
Date: Wed, 03 Jun 2026 11:27:32 +0000 [thread overview]
Message-ID: <20260603112732.89DF71F00898@smtp.kernel.org> (raw)
In-Reply-To: <20260603105814.10236-13-pbonzini@redhat.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] When using nested virtualization with shadow paging (EPT disabled), L1's PDPTRs are overwritten by L2's PDPTRs during a nested VM-Entry but are never restored on a failed VM-Entry. This allows L2 to control L1's shadow page tables.
--
commit a87d952b84013700c29cd0401e35d07fb7710cf4
Author: Paolo Bonzini <pbonzini@redhat.com>
KVM: x86/mmu: move CPU-related fields to struct kvm_pagewalk
This commit moves CPU-related fields and their page format dependencies
into struct kvm_pagewalk. This allows the walk_mmu function to remain
self-contained while cleaning up the accessor functions.
> diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> index 4fbb7508e2413..e2bfecf655d9a 100644
> --- a/arch/x86/kvm/mmu/mmu.c
> +++ b/arch/x86/kvm/mmu/mmu.c
[ ... ]
> @@ -4083,7 +4083,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
> * On SVM, reading PDPTRs might access guest memory, which might fault
> * and thus might sleep. Grab the PDPTRs before acquiring mmu_lock.
> */
> - if (mmu->cpu_role.base.level == PT32E_ROOT_LEVEL) {
> + if (mmu->w.cpu_role.base.level == PT32E_ROOT_LEVEL) {
> for (i = 0; i < 4; ++i) {
> pdptrs[i] = mmu->w.get_pdptr(vcpu, i);
[Severity: Critical]
This is a pre-existing issue, but while reviewing the PDPTR accesses here,
I noticed a problem with how PDPTRs are handled on nested VM-Entry failures.
When using nested virtualization with shadow paging (EPT disabled), L1's
PDPTRs are overwritten by L2's PDPTRs during a nested VM-Entry but are never
restored on a failed VM-Entry.
Looking at nested_vmx_restore_host_state() in arch/x86/kvm/vmx/nested.c:
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
kvm_register_mark_available(vcpu, VCPU_REG_CR3);
/*
* Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs
* from vmcs01 (if necessary). The PDPTRs are not loaded on
* VMFail, like everything else we just need to ensure our
* software model is up-to-date.
*/
if (enable_ept && is_pae_paging(vcpu))
ept_save_pdptrs(vcpu);
L1's CR3 is restored here upon a VM-Entry failure, but the PDPTRs are only
restored if EPT is enabled. If shadow paging is used (enable_ept is false),
the L2 PDPTRs loaded during the aborted entry attempt remain in KVM's software
model (vcpu->arch.pdptrs).
Furthermore, in vmx_cache_reg() in arch/x86/kvm/vmx/vmx.c:
case VCPU_REG_PDPTR:
if (enable_ept)
ept_save_pdptrs(vcpu);
break;
After the failed VM-Entry, VCPU_REG_PDPTR is marked as unavailable. When KVM's
shadow MMU reads the PDPTRs via get_pdptr(), it calls vmx_cache_reg(). For
shadow paging, this does nothing and simply marks the register as available,
causing the MMU to use the stale L2 PDPTRs.
Since L2 can provide arbitrary addresses for its PDPTRs, does this enable L2
to hijack L1's memory mappings and escalate privileges from the nested guest
to the L1 hypervisor?
> if (!(pdptrs[i] & PT_PRESENT_MASK))
> continue;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260603105814.10236-1-pbonzini@redhat.com?part=12
next prev parent reply other threads:[~2026-06-03 11:27 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 10:57 [PATCH 00/24] KVM: apply chainsaw to struct kvm_mmu Paolo Bonzini
2026-06-03 10:57 ` [PATCH 01/24] KVM: x86: remove nested_mmu from mmu_is_nested() Paolo Bonzini
2026-06-03 10:57 ` [PATCH 02/24] KVM: nVMX: remove unnecessary code in prepare_vmcs02_rare Paolo Bonzini
2026-06-03 10:57 ` [PATCH 03/24] KVM: nSVM: invalidate cached PDPTRs across nested NPT transitions Paolo Bonzini
2026-06-03 10:57 ` [PATCH 04/24] KVM: x86: check that kvm_handle_invpcid is only invoked with shadow paging Paolo Bonzini
2026-06-03 10:57 ` [PATCH 05/24] KVM: x86/mmu: move pdptrs out of the MMU Paolo Bonzini
2026-06-03 10:57 ` [PATCH 06/24] KVM: x86/hyperv: remove unnecessary mmu_is_nested() check Paolo Bonzini
2026-06-03 10:57 ` [PATCH 07/24] KVM: x86/mmu: introduce struct kvm_pagewalk Paolo Bonzini
2026-06-03 10:57 ` [PATCH 08/24] KVM: x86/mmu: move get_guest_pgd to " Paolo Bonzini
2026-06-03 10:57 ` [PATCH 09/24] KVM: x86/mmu: move gva_to_gpa " Paolo Bonzini
2026-06-03 10:58 ` [PATCH 10/24] KVM: x86/mmu: move get_pdptr " Paolo Bonzini
2026-06-03 10:58 ` [PATCH 11/24] KVM: x86/mmu: move inject_page_fault " Paolo Bonzini
2026-06-03 10:58 ` [PATCH 12/24] KVM: x86/mmu: move CPU-related fields " Paolo Bonzini
2026-06-03 11:27 ` sashiko-bot [this message]
2026-06-03 12:36 ` Paolo Bonzini
2026-06-03 10:58 ` [PATCH 13/24] KVM: x86/mmu: change CPU-role accessor fields to take " Paolo Bonzini
2026-06-03 10:58 ` [PATCH 14/24] KVM: x86/mmu: move remaining permission fields to " Paolo Bonzini
2026-06-03 10:58 ` [PATCH 15/24] KVM: x86/mmu: pass struct kvm_pagewalk to kvm_mmu_invalidate_addr Paolo Bonzini
2026-06-03 10:58 ` [PATCH 16/24] KVM: x86/mmu: change walk_mmu to struct kvm_pagewalk Paolo Bonzini
2026-06-03 10:58 ` [PATCH 17/24] KVM: x86/mmu: change nested_mmu.w to ngva_walk Paolo Bonzini
2026-06-03 10:58 ` [PATCH 18/24] KVM: x86/mmu: make gva_walk a value Paolo Bonzini
2026-06-03 11:24 ` sashiko-bot
2026-06-03 11:47 ` Paolo Bonzini
2026-06-03 10:58 ` [PATCH 19/24] KVM: x86/mmu: pull struct kvm_pagewalk out of struct kvm_mmu Paolo Bonzini
2026-06-03 10:58 ` [PATCH 20/24] KVM: x86/mmu: cleanup functions that initialize shadow MMU Paolo Bonzini
2026-06-03 10:58 ` [PATCH 21/24] KVM: x86/mmu: pull page format to a new struct Paolo Bonzini
2026-06-03 10:58 ` [PATCH 22/24] KVM: x86/mmu: merge struct rsvd_bits_validate into struct kvm_page_format Paolo Bonzini
2026-06-03 10:58 ` [PATCH 23/24] KVM: x86/mmu: parameterize update_permission_bitmask() Paolo Bonzini
2026-06-03 10:58 ` [PATCH 24/24] KVM: x86/mmu: use kvm_page_format to test SPTEs Paolo Bonzini
2026-06-03 11:34 ` sashiko-bot
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=20260603112732.89DF71F00898@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--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