]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: riscv: PMU: Bound counter mask scan to BITS_PER_LONG
authorShengwen Cheng <shengwen1997.tw@gmail.com>
Fri, 26 Jun 2026 05:40:51 +0000 (13:40 +0800)
committerAnup Patel <anup@brainfault.org>
Mon, 13 Jul 2026 12:46:56 +0000 (18:16 +0530)
The PMU SBI handler passes the guest argument registers directly to
the PMU start/stop helpers:

kvm_riscv_vcpu_pmu_ctr_start(vcpu, cp->a0, cp->a1, cp->a2, ...)
kvm_riscv_vcpu_pmu_ctr_stop(vcpu, cp->a0, cp->a1, cp->a2, ...)

which map to:

unsigned long ctr_base
unsigned long ctr_mask
unsigned long flags

Thus cp->a1 is a single unsigned long ctr_mask, not a bitmap array
sized for RISCV_MAX_COUNTERS.

On RV32, RISCV_MAX_COUNTERS is 64 while BITS_PER_LONG is 32.  Using
for_each_set_bit() with RISCV_MAX_COUNTERS can therefore make
find_next_bit() access bits beyond the storage of ctr_mask on RV32.

Limit the scan to BITS_PER_LONG. The requested counter range is already
validated by kvm_pmu_validate_counter_mask(), so this preserves RV64
behavior and avoids an out-of-bounds bitmap read on RV32.

Fixes: 0cb74b65d2e5 ("RISC-V: KVM: Implement perf support without sampling")
Signed-off-by: Shengwen Cheng <shengwen1997.tw@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260626054051.3360865-1-shengwen1997.tw@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
arch/riscv/kvm/vcpu_pmu.c

index bb46dcbfb24da7521b896a206d3f0e35863b3f0c..2025b664961c80b6c180518f6dacc71c9a241221 100644 (file)
@@ -586,7 +586,7 @@ int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base,
                }
        }
        /* Start the counters that have been configured and requested by the guest */
-       for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
+       for_each_set_bit(i, &ctr_mask, BITS_PER_LONG) {
                pmc_index = array_index_nospec(i + ctr_base,
                                               RISCV_KVM_MAX_COUNTERS);
                if (!test_bit(pmc_index, kvpmu->pmc_in_use))
@@ -658,7 +658,7 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base,
        }
 
        /* Stop the counters that have been configured and requested by the guest */
-       for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
+       for_each_set_bit(i, &ctr_mask, BITS_PER_LONG) {
                pmc_index = array_index_nospec(i + ctr_base,
                                               RISCV_KVM_MAX_COUNTERS);
                if (!test_bit(pmc_index, kvpmu->pmc_in_use))