[PATCH] lib: sbi_pmu: fix integer overflow and zero-address in event_get_info
liutong <[email protected]> Sun, 28 Jun 2026 17:04:21 +0800
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <[email protected]> |
sbi_pmu_event_get_info() computes the shared memory size as num_events * sizeof(struct sbi_pmu_event_info) without checking for integer overflow. A sufficiently large num_events causes the product to wrap around, making the domain check pass on a truncated size while the loop iterates with the original count. Also reject a zero physical address for the shared memory, which would cause M-mode to write to address 0 and hang the hart. Add bounds checking on num_events before the multiplication and reject zero shmem addresses early. Signed-off-by: liutong <[email protected]> --- lib/sbi/sbi_pmu.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c index 480a9723..f7fe79d4 100644 --- a/lib/sbi/sbi_pmu.c +++ b/lib/sbi/sbi_pmu.c @@ -1050,7 +1050,7 @@ int sbi_pmu_ctr_get_info(uint32_t cidx, unsigned long *ctr_info) int sbi_pmu_event_get_info(unsigned long shmem_phys_lo, unsigned long shmem_phys_hi, unsigned long num_events, unsigned long flags) { - unsigned long shmem_size = num_events * sizeof(struct sbi_pmu_event_info); + unsigned long shmem_size; int i, j, event_type; struct sbi_pmu_event_info *einfo; struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr(); @@ -1065,6 +1065,21 @@ int sbi_pmu_event_get_info(unsigned long shmem_phys_lo, unsigned long shmem_phys if (!num_events || (shmem_phys_lo & 0xF)) return SBI_ERR_INVALID_PARAM; + /* Reject zero physical address to avoid M-mode writing to address 0 */ + if (!shmem_phys_lo) + return SBI_ERR_INVALID_ADDRESS; + + /* + * Bound num_events to prevent integer overflow in the + * shmem_size computation below. The division ensures + * num_events * sizeof(struct sbi_pmu_event_info) fits in + * an unsigned long. + */ + if (num_events > ((unsigned long)-1) / sizeof(struct sbi_pmu_event_info)) + return SBI_ERR_INVALID_PARAM; + + shmem_size = num_events * sizeof(struct sbi_pmu_event_info); + /* * On RV32, the M-mode can only access the first 4GB of * the physical address space because M-mode does not have -- 2.34.1 -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi