Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mailbox: mchp-ipc-sbi: fix out-of-bounds access in mchp_ipc_get_cluster_aggr_irq()

The cluster_cfg array is dynamically allocated to hold per-CPU
configuration structures, with its size based on the number of online
CPUs. Previously, this array was indexed using hartid, which may be
non-contiguous or exceed the bounds of the array, leading to
out-of-bounds access.
Switch to using cpuid as the index, as it is guaranteed to be within
the valid range provided by for_each_online_cpu().

Signed-off-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>

authored by

Valentina Fernandez and committed by
Jassi Brar
f7c330a8 d96ebba3

+11 -11
+11 -11
drivers/mailbox/mailbox-mchp-ipc-sbi.c
··· 180 180 /* Find out the hart that originated the irq */ 181 181 for_each_online_cpu(i) { 182 182 hartid = cpuid_to_hartid_map(i); 183 - if (irq == ipc->cluster_cfg[hartid].irq) 183 + if (irq == ipc->cluster_cfg[i].irq) 184 184 break; 185 185 } 186 186 187 187 status_msg.cluster = hartid; 188 - memcpy(ipc->cluster_cfg[hartid].buf_base, &status_msg, sizeof(struct mchp_ipc_status)); 188 + memcpy(ipc->cluster_cfg[i].buf_base, &status_msg, sizeof(struct mchp_ipc_status)); 189 189 190 - ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[hartid].buf_base_addr); 190 + ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[i].buf_base_addr); 191 191 if (ret < 0) { 192 192 dev_err_ratelimited(ipc->dev, "could not get IHC irq status ret=%d\n", ret); 193 193 return IRQ_HANDLED; 194 194 } 195 195 196 - memcpy(&status_msg, ipc->cluster_cfg[hartid].buf_base, sizeof(struct mchp_ipc_status)); 196 + memcpy(&status_msg, ipc->cluster_cfg[i].buf_base, sizeof(struct mchp_ipc_status)); 197 197 198 198 /* 199 199 * Iterate over each bit set in the IHC interrupt status register (IRQ_STATUS) to identify ··· 385 385 if (ret <= 0) 386 386 continue; 387 387 388 - ipc->cluster_cfg[hartid].irq = ret; 389 - ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[hartid].irq, 388 + ipc->cluster_cfg[cpuid].irq = ret; 389 + ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[cpuid].irq, 390 390 mchp_ipc_cluster_aggr_isr, IRQF_SHARED, 391 391 "miv-ihc-irq", ipc); 392 392 if (ret) 393 393 return ret; 394 394 395 - ipc->cluster_cfg[hartid].buf_base = devm_kmalloc(ipc->dev, 396 - sizeof(struct mchp_ipc_status), 397 - GFP_KERNEL); 395 + ipc->cluster_cfg[cpuid].buf_base = devm_kmalloc(ipc->dev, 396 + sizeof(struct mchp_ipc_status), 397 + GFP_KERNEL); 398 398 399 - if (!ipc->cluster_cfg[hartid].buf_base) 399 + if (!ipc->cluster_cfg[cpuid].buf_base) 400 400 return -ENOMEM; 401 401 402 - ipc->cluster_cfg[hartid].buf_base_addr = __pa(ipc->cluster_cfg[hartid].buf_base); 402 + ipc->cluster_cfg[cpuid].buf_base_addr = __pa(ipc->cluster_cfg[cpuid].buf_base); 403 403 404 404 irq_found = true; 405 405 }