[PATCH v2 2/2] PCI/AER: Fix memory leak in aer_recover_work_func() when pci_dev is missing
Priyank Rathod <[email protected]> Mon, 03 Aug 2026 21:59:39 +0000
| Newsgroups | org.kernel.vger.linux-pci,org.kernel.vger.linux-kernel,org.ozlabs.lists.linuxppc-dev |
|---|---|
| Message-ID | <[email protected]> |
When ACPI APEI/GHES processes PCIe AER error records, it allocates memory for aer_capability_regs (entry.regs) from ghes_estatus_pool and queues the entry into aer_recover_ring. In aer_recover_work_func(), items are popped from aer_recover_ring via kfifo_get(). If pci_get_domain_bus_and_slot() fails to find a matching pci_dev, the code previously executed 'continue', bypassing the call to ghes_estatus_pool_region_free(). As a result, the memory allocated for entry.regs from ghes_estatus_pool was leaked. Refactor aer_recover_work_func() to ensure ghes_estatus_pool_region_free() is called unconditionally for every dequeued entry, releasing the pool memory even when pci_dev is missing. Signed-off-by: Priyank Rathod <[email protected]> --- drivers/pci/pcie/aer.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 967cde9dd519..9683cdef649b 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -1223,14 +1223,13 @@ static void aer_recover_work_func(struct work_struct *work) while (kfifo_get(&aer_recover_ring, &entry)) { pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus, entry.devfn); - if (!pdev) { + if (!pdev) pr_err_ratelimited("%04x:%02x:%02x.%x: no pci_dev found\n", entry.domain, entry.bus, PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn)); - continue; - } - pci_print_aer(pdev, entry.severity, entry.regs); + else + pci_print_aer(pdev, entry.severity, entry.regs); /* * Memory for aer_capability_regs(entry.regs) is being @@ -1242,13 +1241,15 @@ static void aer_recover_work_func(struct work_struct *work) ghes_estatus_pool_region_free((unsigned long)entry.regs, sizeof(struct aer_capability_regs)); - if (entry.severity == AER_NONFATAL) - pcie_do_recovery(pdev, pci_channel_io_normal, - aer_root_reset); - else if (entry.severity == AER_FATAL) - pcie_do_recovery(pdev, pci_channel_io_frozen, - aer_root_reset); - pci_dev_put(pdev); + if (pdev) { + if (entry.severity == AER_NONFATAL) + pcie_do_recovery(pdev, pci_channel_io_normal, + aer_root_reset); + else if (entry.severity == AER_FATAL) + pcie_do_recovery(pdev, pci_channel_io_frozen, + aer_root_reset); + pci_dev_put(pdev); + } } } -- 2.55.0.571.g244d577d93-goog