aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorZongmin Zhou <zhouzongmin@kylinos.cn>2026-08-26 14:41:17 +0800
committerAnup Patel <anup@brainfault.org>2026-09-15 18:55:51 +0530
commitb7749531a9b195f4fd7db92ca3cc49bda1a4dc8d (patch)
treebd3184833ff3f176b3140115c3388010a4b46fa4
parentKVM: riscv: Fix NACL hfence entry update order (diff)
RISC-V: KVM: Fix sdata leak and stale snapshot_addr in snapshot_set_shmem
A guest may call SBI_PMU_SNAPSHOT_SET_SHMEM repeatedly. Each call overwrites kvpmu->sdata without freeing the old buffer (memory leak), and if a later kvm_vcpu_write_guest() fails, the error path frees sdata but leaves snapshot_addr stale. A subsequent SBI_PMU_COUNTER_START then passes the INVALID_GPA check and crashes the host with a NULL buffer in kvm_vcpu_read_guest(). Fix this by clearing the previously installed snapshot area before installing a new one, which keeps sdata and snapshot_addr consistent. The SBI spec suggests a single invocation but defines no error code for repeated calls, so KVM must tolerate them. Fixes: c2f41ddbcdd756 ("RISC-V: KVM: Implement SBI PMU Snapshot feature") Cc: stable@vger.kernel.org Signed-off-by: Zongmin Zhou <zhouzongmin@kylinos.cn> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260826064117.58029-1-min_halo@163.com Signed-off-by: Anup Patel <anup@brainfault.org>
-rw-r--r--arch/riscv/kvm/vcpu_pmu.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c
index 6ff741ee7803..cc0c138651bc 100644
--- a/arch/riscv/kvm/vcpu_pmu.c
+++ b/arch/riscv/kvm/vcpu_pmu.c
@@ -454,6 +454,14 @@ int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long s
}
}
+ /*
+ * Clear any previously installed snapshot area to avoid leaking
+ * the old sdata and to keep sdata/snapshot_addr consistent if
+ * the re-install fails below.
+ */
+ if (kvpmu->snapshot_addr != INVALID_GPA)
+ kvm_pmu_clear_snapshot_area(vcpu);
+
kvpmu->sdata = kzalloc(snapshot_area_size, GFP_ATOMIC | __GFP_ACCOUNT);
if (!kvpmu->sdata) {
sbiret = SBI_ERR_FAILURE;