From: sashiko-bot@kernel.org
To: "Wei-Lin Chang" <weilin.chang@arm.com>
Cc: "Oliver Upton" <oupton@kernel.org>,
"Marc Zyngier" <maz@kernel.org>,
kvmarm@lists.linux.dev
Subject: Re: [PATCH v2 6/6] KVM: arm64: ptdump: Introduce the shadow ptdump file
Date: Tue, 30 Jun 2026 12:27:58 +0000 [thread overview]
Message-ID: <20260630122758.891011F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260630121005.1130996-7-weilin.chang@arm.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
New issues:
- [High] Concurrent reallocation of nested_mmus array leads to Use-After-Free in kvm_ptdump_guest_nested_show().
- [High] If kvm_ptdump_parser_init() fails, st->kvm is left as NULL, causing a kernel panic on subsequent debugfs reads.
- [Medium] Missing note_page_flush() causes the last contiguous block of page table entries to be silently dropped.
Pre-existing issues:
- [Critical] kvm_arch_flush_shadow_all() frees the nested_mmus array even if active VCPUs hold references to its elements.
- [High] Unprotected iteration over nested_mmus in kvm_arch_flush_shadow_all() races with array reallocation.
--
commit 4dce12b467bf2d3540834dccee1f3e623af43d42
Author: Wei-Lin Chang <weilin.chang@arm.com>
KVM: arm64: ptdump: Introduce the shadow ptdump file
This commit creates a ptdump file for shadow page tables used in nested
virtualization. It dumps all valid shadow page tables, their mmu index,
VTCR_EL2, VTTBR_EL2, and stage-2 enablement status. It also modifies
kvm_arch_flush_shadow_all() to detach the nested mmu array under mmu_lock.
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index efd5d21c7ac75..cbf7143819669 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -1184,6 +1184,7 @@ void kvm_nested_s2_flush(struct kvm *kvm)
>
> void kvm_arch_flush_shadow_all(struct kvm *kvm)
> {
> + struct kvm_s2_mmu *mmus;
> int i;
>
> for (i = 0; i < kvm->arch.nested_mmus_size; i++) {
[Severity: High]
This is a pre-existing issue, but can this loop race with array reallocation?
If a concurrent thread calls KVM_ARM_VCPU_INIT to initialize a new nested
vCPU, kvm_vcpu_init_nested() expands the array via kvrealloc() holding
only kvm->arch.config_lock. Since this loop doesn't hold config_lock or
mmu_lock, could it dereference the array while or after it is freed?
> struct kvm_s2_mmu *mmu = &kvm->arch.nested_mmus[i];
>
> if (!WARN_ON(atomic_read(&mmu->refcnt)))
> kvm_free_stage2_pgd(mmu);
> }
> - kvfree(kvm->arch.nested_mmus);
> - kvm->arch.nested_mmus = NULL;
> - kvm->arch.nested_mmus_size = 0;
> +
> + scoped_guard(write_lock, &kvm->mmu_lock) {
> + mmus = kvm->arch.nested_mmus;
> + kvm->arch.nested_mmus = NULL;
> + kvm->arch.nested_mmus_size = 0;
> + }
> +
> + kvfree(mmus);
[Severity: Critical]
This is a pre-existing issue, but does this prematurely free the array if
active VCPUs hold references?
If a running vCPU holds a reference to its nested MMU, where atomic_read
shows refcnt > 0, the loop above skips freeing the page table, but the
backing array is freed anyway.
When the vCPU exits and calls kvm_vcpu_put_hw_mmu(), it will dereference the
freed pointer. Should the array lifetime be tied to the active references?
> kvm_uninit_stage2_mmu(kvm);
> }
[ ... ]
> diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
> index 40f93b7c7ad98..1649eaa75798c 100644
> --- a/arch/arm64/kvm/ptdump.c
> +++ b/arch/arm64/kvm/ptdump.c
> @@ -181,6 +181,50 @@ static int kvm_ptdump_guest_canonical_show(struct seq_file *m, void *unused)
> return 0;
> }
>
> +static int kvm_ptdump_guest_nested_show(struct seq_file *m, void *unused)
> +{
> + int ret = 0, i;
> + struct kvm_ptdump_guest_state *st = m->private;
> + struct kvm *kvm = st->kvm;
> + struct kvm_pgtable_walker walker = (struct kvm_pgtable_walker) {
> + .cb = kvm_ptdump_visitor,
> + .arg = &st->parser_state,
> + .flags = KVM_PGTABLE_WALK_LEAF,
> + };
> +
> + guard(write_lock)(&kvm->mmu_lock);
> +
> + if (!kvm->arch.nested_mmus)
> + return 0;
> +
> + for (i = 0; i < kvm->arch.nested_mmus_size; i++) {
[Severity: High]
Is it safe to iterate over the nested_mmus array holding only mmu_lock?
If userspace reads the debugfs file while a concurrent thread issues a
KVM_ARM_VCPU_INIT ioctl to initialize a new nested vCPU, kvm_vcpu_init_nested()
expands the array via kvrealloc() holding only kvm->arch.config_lock:
kvm_vcpu_init_nested()
tmp = kvrealloc(kvm->arch.nested_mmus, ...);
swap(kvm->arch.nested_mmus, tmp);
Could the debugfs reader dereference the array while or after it is freed by
kvrealloc()?
> + struct kvm_s2_mmu *mmu = &kvm->arch.nested_mmus[i];
> +
> + if (!mmu->pgt)
> + continue;
> +
> + if (kvm_s2_mmu_valid(mmu)) {
> + memset(st, 0, sizeof(*st));
> + ret = kvm_ptdump_parser_init(st, kvm, mmu->pgt);
> + if (ret)
> + return ret;
[Severity: High]
Does an early return here leave st->kvm as NULL?
The memset() clears st->kvm. If kvm_ptdump_parser_init() returns an error,
the function propagates it, leaving st->kvm NULL.
If userspace issues another read() on the same file descriptor, seq_read will
call the show() callback again, which will dereference the NULL st->kvm
at the mmu_lock acquisition:
guard(write_lock)(&kvm->mmu_lock);
Could we restore st->kvm on the error path?
> + st->parser_state = (struct ptdump_pg_state) {
> + .marker = &st->ipa_marker[0],
> + .level = -1,
> + .pg_level = &st->level[0],
> + .seq = m,
> + };
> + seq_printf(m, "nested mmu %d VTCR: 0x%016llx VTTBR: 0x%016llx s2: %s\n",
> + i, mmu->tlb_vtcr, mmu->tlb_vttbr,
> + mmu->nested_stage2_enabled ? "enabled" : "disabled");
> + ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker);
> + if (ret)
> + return ret;
[Severity: Medium]
Does the page table walk lack a subsequent call to note_page_flush()?
The ptdump API requires a final call to note_page_flush() to emit the final
buffered contiguous block of page table attributes. Because this is missing
after the kvm_pgtable_walk() completion, does the last block get silently
dropped from the debugfs output?
> + }
> + }
> + return ret;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260630121005.1130996-1-weilin.chang@arm.com?part=6
next prev parent reply other threads:[~2026-06-30 12:27 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 12:09 [PATCH v2 0/6] KVM: arm64: ptdump: Shadow ptdump fixes Wei-Lin Chang
2026-06-30 12:10 ` [PATCH v2 1/6] KVM: arm64: ptdump: Remove shadow ptdump files Wei-Lin Chang
2026-06-30 12:10 ` [PATCH v2 2/6] KVM: arm64: ptdump: Undo making the ptdump code mmu aware Wei-Lin Chang
2026-06-30 12:10 ` [PATCH v2 3/6] KVM: arm64: ptdump: Fix UAF when mmu->pgt is freed Wei-Lin Chang
2026-07-01 15:00 ` Leonardo Bras
2026-07-01 17:27 ` Wei-Lin Chang
2026-07-02 10:58 ` Leonardo Bras
2026-07-03 9:26 ` Wei-Lin Chang
2026-06-30 12:10 ` [PATCH v2 4/6] KVM: arm64: ptdump: Factor out initialization of kvm_ptdump_guest_state Wei-Lin Chang
2026-06-30 12:10 ` [PATCH v2 5/6] KVM: arm64: ptdump: Extract kvm_ptdump_guest_open() from canonical ptdump path Wei-Lin Chang
2026-06-30 12:10 ` [PATCH v2 6/6] KVM: arm64: ptdump: Introduce the shadow ptdump file Wei-Lin Chang
2026-06-30 12:27 ` sashiko-bot [this message]
2026-07-17 14:52 ` Wei-Lin Chang
2026-07-01 15:28 ` Leonardo Bras
2026-07-01 17:35 ` Wei-Lin Chang
2026-07-02 11:00 ` Leonardo Bras
2026-07-02 21:48 ` Itaru Kitayama
2026-07-03 10:27 ` Wei-Lin Chang
2026-07-02 6:55 ` [PATCH v2 0/6] KVM: arm64: ptdump: Shadow ptdump fixes Itaru Kitayama
2026-07-02 7:41 ` Wei-Lin Chang
2026-07-02 23:02 ` Itaru Kitayama
2026-07-03 10:24 ` Wei-Lin Chang
2026-07-09 7:34 ` Itaru Kitayama
2026-07-10 6:43 ` Wei-Lin Chang
2026-07-10 7:26 ` Itaru Kitayama
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=20260630122758.891011F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=weilin.chang@arm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox