From 34780984173fb332fdcc7462ce54ef0e2ff8e9cc Mon Sep 17 00:00:00 2001 From: Yangyu Chen Date: Tue, 20 Jan 2026 23:27:55 +0800 Subject: [PATCH] irqchip/sifive-plic: Fix insufficient irq_groups allocation Since the first irq source is 1 instead of 0, when the number of irqs is multiple of 32, the last irq group will be ignored during allocation, saving, and restoring. This lead to memory corruption when accessing enable_save beyond allocated memory after commit 14ff9e54dd14 ("irqchip/sifive-plic: Cache the interrupt enable state") which will access enable_save for all sources during plic_probe. Thus, we should allocate irq_groups based on (nr_irqs + 1) instead of nr_irqs to avoid this issue. Fixes: 14ff9e54dd14 ("irqchip/sifive-plic: Cache the interrupt enable state") Signed-off-by: Yangyu Chen Signed-off-by: Linux RISC-V bot --- drivers/irqchip/irq-sifive-plic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c index 210a5795963772b..d6515bf764442bf 100644 --- a/drivers/irqchip/irq-sifive-plic.c +++ b/drivers/irqchip/irq-sifive-plic.c @@ -293,7 +293,7 @@ static void plic_irq_resume(void *data) continue; raw_spin_lock_irqsave(&handler->enable_lock, flags); - for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) { + for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs + 1, 32); i++) { reg = handler->enable_base + i * sizeof(u32); writel(handler->enable_save[i], reg); } @@ -431,7 +431,7 @@ static u32 cp100_isolate_pending_irq(int nr_irq_groups, struct plic_handler *han static irq_hw_number_t cp100_get_hwirq(struct plic_handler *handler, void __iomem *claim) { - int nr_irq_groups = DIV_ROUND_UP(handler->priv->nr_irqs, 32); + int nr_irq_groups = DIV_ROUND_UP(handler->priv->nr_irqs + 1, 32); u32 __iomem *enable = handler->enable_base; irq_hw_number_t hwirq = 0; u32 iso_mask; @@ -718,7 +718,7 @@ static int plic_probe(struct fwnode_handle *fwnode) context_id * CONTEXT_ENABLE_SIZE; handler->priv = priv; - handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32), + handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs + 1, 32), sizeof(*handler->enable_save), GFP_KERNEL); if (!handler->enable_save) { error = -ENOMEM;