]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
irqchip/imgpdc: Fix resource leak, add missing chained handler cleanup on remove
authorQingshuang Fu <fuqingshuang@kylinos.cn>
Thu, 18 Jun 2026 02:13:52 +0000 (10:13 +0800)
committerThomas Gleixner <tglx@kernel.org>
Mon, 22 Jun 2026 16:09:56 +0000 (18:09 +0200)
The driver allocates domain generic chips using
irq_alloc_domain_generic_chips() during probe and sets up chained
handlers using irq_set_chained_handler_and_data(). However, on driver
removal, the generic chips are not freed and the chained handlers are
not removed.

The generic chips remain on the global gc_list and may later be accessed by
generic interrupt chip suspend, resume, or shutdown callbacks after the
driver has been removed, potentially resulting in a use-after-free and
kernel crash.

The chained handlers that were installed in probe for peripheral and
syswake interrupts are also left dangling, which can lead to spurious
interrupts accessing freed memory.

Fix these issues by:

  - Setting IRQ_DOMAIN_FLAG_DESTROY_GC flag in domain->flags, so the
    core code automatically removes generic chips when irq_domain_remove()
    is called

  - Clearing all chained handlers with NULL in pdc_intc_remove()

Fixes: b6ef9161e43a ("irq-imgpdc: add ImgTec PDC irqchip driver")
Signed-off-by: Qingshuang Fu <fuqingshuang@kylinos.cn>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260618021352.661773-1-fffsqian@163.com
drivers/irqchip/irq-imgpdc.c

index e9ef2f5a7207ee0ee7c81082a10d0b71af2d32ff..4feef4ab5fecc075cfc98f624ef45b59916ecc78 100644 (file)
@@ -378,6 +378,7 @@ static int pdc_intc_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "cannot add IRQ domain\n");
                return -ENOMEM;
        }
+       priv->domain->flags |= IRQ_DOMAIN_FLAG_DESTROY_GC;
 
        /*
         * Set up 2 generic irq chips with 2 chip types.
@@ -465,6 +466,11 @@ static void pdc_intc_remove(struct platform_device *pdev)
 {
        struct pdc_intc_priv *priv = platform_get_drvdata(pdev);
 
+       for (unsigned int i = 0; i < priv->nr_perips; ++i)
+               irq_set_chained_handler_and_data(priv->perip_irqs[i], NULL, NULL);
+
+       irq_set_chained_handler_and_data(priv->syswake_irq, NULL, NULL);
+
        irq_domain_remove(priv->domain);
 }