[PATCH 2/3] KVM: arm64: ptdump: Store both mmu and kvm pointers in kvm_ptdump_guest_state
Wei-Lin Chang
weilin.chang at arm.com
Tue Jun 23 07:24:42 PDT 2026
In the nested case, the nested mmu could be freed when .release() is
called, e.g. another process closes the ptdump debugfs file after the VM
is destroyed. This causes a UAF when the nested mmu is accessed to reach
kvm for kvm_put_kvm(). Store the kvm pointer in kvm_ptdump_guest_state
so that it can be reached without going through the nested mmu.
Fixes: 204f7c018d76 ("KVM: arm64: ptdump: Make KVM ptdump code s2 mmu aware")
Signed-off-by: Wei-Lin Chang <weilin.chang at arm.com>
---
arch/arm64/kvm/ptdump.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
index 2a6afe67646a..a089e87ea366 100644
--- a/arch/arm64/kvm/ptdump.c
+++ b/arch/arm64/kvm/ptdump.c
@@ -19,7 +19,12 @@
#define KVM_PGTABLE_MAX_LEVELS (KVM_PGTABLE_LAST_LEVEL + 1)
#define S2FNAMESZ sizeof("0x0123456789abcdef-0x0123456789abcdef-s2-disabled")
+/*
+ * Nested mmus could be freed when .release() is called, so also keep the kvm
+ * pointer for kvm_put_kvm().
+ */
struct kvm_ptdump_guest_state {
+ struct kvm *kvm;
struct kvm_s2_mmu *mmu;
struct ptdump_pg_state parser_state;
struct addr_marker ipa_marker[MARKERS_LEN];
@@ -133,6 +138,7 @@ static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm_s2_mmu
st->ipa_marker[1].start_address = BIT(pgtable->ia_bits);
st->mmu = mmu;
+ st->kvm = kvm_s2_mmu_to_kvm(mmu);
return st;
}
@@ -197,11 +203,10 @@ static int kvm_ptdump_guest_open(struct inode *m, struct file *file)
static int kvm_ptdump_guest_close(struct inode *m, struct file *file)
{
- struct kvm *kvm = kvm_s2_mmu_to_kvm(m->i_private);
void *st = ((struct seq_file *)file->private_data)->private;
+ kvm_put_kvm(((struct kvm_ptdump_guest_state *)st)->kvm);
kfree(st);
- kvm_put_kvm(kvm);
return single_release(m, file);
}
--
2.43.0
More information about the linux-arm-kernel
mailing list