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: 21+ 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-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
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 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.