Re: [PATCH] RISC-V: KVM: Fix double-free of sdata in kvm_pmu_clear_snapshot_area()
From: Nutty.Liu
Date: Fri Mar 27 2026 - 03:40:44 EST
On 3/18/2026 5:29 PM, Jiakai Xu wrote:
In kvm_riscv_vcpu_pmu_snapshot_set_shmem(), when kvm_vcpu_write_guest()Reviewed-by: Nutty Liu <nutty.liu@xxxxxxxxxxx>
fails, kvpmu->sdata is freed but not set to NULL. This leaves a dangling
pointer that will be freed again when kvm_pmu_clear_snapshot_area() is
called during vcpu teardown, triggering a KASAN double-free report.
First free occurs in kvm_riscv_vcpu_pmu_snapshot_set_shmem():
kvm_riscv_vcpu_pmu_snapshot_set_shmem arch/riscv/kvm/vcpu_pmu.c:443
kvm_sbi_ext_pmu_handler arch/riscv/kvm/vcpu_sbi_pmu.c:74
kvm_riscv_vcpu_sbi_ecall arch/riscv/kvm/vcpu_sbi.c:608
kvm_riscv_vcpu_exit arch/riscv/kvm/vcpu_exit.c:240
kvm_arch_vcpu_ioctl_run arch/riscv/kvm/vcpu.c:1008
kvm_vcpu_ioctl virt/kvm/kvm_main.c:4476
Second free (double-free) occurs in kvm_pmu_clear_snapshot_area():
kvm_pmu_clear_snapshot_area arch/riscv/kvm/vcpu_pmu.c:403 [inline]
kvm_riscv_vcpu_pmu_deinit.part arch/riscv/kvm/vcpu_pmu.c:905
kvm_riscv_vcpu_pmu_deinit arch/riscv/kvm/vcpu_pmu.c:893
kvm_arch_vcpu_destroy arch/riscv/kvm/vcpu.c:199
kvm_vcpu_destroy virt/kvm/kvm_main.c:469 [inline]
kvm_destroy_vcpus virt/kvm/kvm_main.c:489
kvm_arch_destroy_vm arch/riscv/kvm/vm.c:54
kvm_destroy_vm virt/kvm/kvm_main.c:1301 [inline]
kvm_put_kvm virt/kvm/kvm_main.c:1338
kvm_vm_release virt/kvm/kvm_main.c:1361
Fix it by setting kvpmu->sdata to NULL after kfree() in
kvm_riscv_vcpu_pmu_snapshot_set_shmem(), so that the subsequent
kfree(NULL) in kvm_pmu_clear_snapshot_area() becomes a safe no-op.
This bug was found by fuzzing the KVM RISC-V PMU interface.
Fixes: c2f41ddbcdd756 ("RISC-V: KVM: Implement SBI PMU Snapshot feature")
Signed-off-by: Jiakai Xu <jiakaiPeanut@xxxxxxxxx>
Signed-off-by: Jiakai Xu <xujiakai2025@xxxxxxxxxxx>
Thanks,
Nutty
---
arch/riscv/kvm/vcpu_pmu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c
index e873430e596b2..ac1b9a91a19db 100644
--- a/arch/riscv/kvm/vcpu_pmu.c
+++ b/arch/riscv/kvm/vcpu_pmu.c
@@ -441,6 +441,7 @@ int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long s
/* No need to check writable slot explicitly as kvm_vcpu_write_guest does it internally */
if (kvm_vcpu_write_guest(vcpu, saddr, kvpmu->sdata, snapshot_area_size)) {
kfree(kvpmu->sdata);
+ kvpmu->sdata = NULL;
sbiret = SBI_ERR_INVALID_ADDRESS;
goto out;
}