From ac16c6b604961525bb096c0513c6ad4dbf5a5695 Mon Sep 17 00:00:00 2001 From: Alexander Chuprunov Date: Thu, 18 Sep 2025 12:07:06 +0300 Subject: [PATCH] lib: sbi: sbi_pmu: added checks for ctr_idx in match Previously, in sbi_pmu_ctr_cfg_match() function, ctr_idx was used immediately after pmu_ctr_find_fw() or pmu_ctr_find_hw() calls. In first case, array index was (ctr_idx - num_hw_ctrs), in second - ctr_idx. But pmu_ctr_find_fw() and pmu_ctr_find_hw() functions can return negative value, in which case writing in arrays with such indexes would corrupt sbi_pmu_hart_state structure. To avoid this situation, direct ctr_idx value check added. Signed-off-by: Alexander Chuprunov Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20250918090706.2217603-4-alexander.chuprunov@syntacore.com Signed-off-by: Anup Patel --- lib/sbi/sbi_pmu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c index b618be43..70c49abc 100644 --- a/lib/sbi/sbi_pmu.c +++ b/lib/sbi/sbi_pmu.c @@ -830,7 +830,7 @@ static int pmu_ctr_find_fw(struct sbi_pmu_hart_state *phs, cidx = i + cbase; if (cidx < num_hw_ctrs || total_ctrs <= cidx) continue; - if (phs->active_events[i] != SBI_PMU_EVENT_IDX_INVALID) + if (phs->active_events[cidx] != SBI_PMU_EVENT_IDX_INVALID) continue; if (SBI_PMU_FW_PLATFORM == event_code && pmu_dev && pmu_dev->fw_counter_match_encoding) { @@ -840,7 +840,7 @@ static int pmu_ctr_find_fw(struct sbi_pmu_hart_state *phs, continue; } - return i; + return cidx; } return SBI_ENOTSUPP; @@ -886,13 +886,14 @@ int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask, /* Any firmware counter can be used track any firmware event */ ctr_idx = pmu_ctr_find_fw(phs, cidx_base, cidx_mask, event_code, event_data); - if (event_code == SBI_PMU_FW_PLATFORM) + if ((event_code == SBI_PMU_FW_PLATFORM) && (ctr_idx >= num_hw_ctrs)) phs->fw_counters_data[ctr_idx - num_hw_ctrs] = event_data; } else { ctr_idx = pmu_ctr_find_hw(phs, cidx_base, cidx_mask, flags, event_idx, event_data); - phs->hw_counters_data[ctr_idx] = event_data; + if (ctr_idx >= 0) + phs->hw_counters_data[ctr_idx] = event_data; } if (ctr_idx < 0)