Re: [PATCH] PCI/AER: Fix memory leak in aer_recover_work_func() when pci_dev is missing
[email protected] Mon, 03 Aug 2026 18:53:22 +0000
| Newsgroups | org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 1 potential issue(= s) to consider: Pre-existing issues: - [High] Memory allocated from `ghes_estatus_pool` for `aer_regs` is leaked= in `aer_recover_queue()` when `aer_recover_ring` kfifo is full. -- --- Patch [1]: [PATCH] PCI/AER: Fix memory leak in aer_recover_work_func() = when pci_dev is missing --- commit 6bb7331494c5c24e65c258479be47a6a7424c240 Author: Priyank Rathod <[email protected]> PCI/AER: Fix memory leak in aer_recover_work_func() when pci_dev is missing This commit fixes a memory leak in aer_recover_work_func() by ensuring that memory allocated for entry.regs is freed via ghes_estatus_pool_region_free() unconditionally, even when pci_get_domain_bus_and_slot() fails to find a matching PCI device. > diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c > index c4fd9c0b2a548..555f39b60b14d 100644 > --- a/drivers/pci/pcie/aer.c > +++ b/drivers/pci/pcie/aer.c [ ... ] > @@ -1242,13 +1241,15 @@ static void aer_recover_work_func(struct work_str= uct *work) > ghes_estatus_pool_region_free((unsigned long)entry.regs, > sizeof(struct aer_capability_regs)); > =20 > - if (entry.severity =3D=3D AER_NONFATAL) > - pcie_do_recovery(pdev, pci_channel_io_normal, > - aer_root_reset); > - else if (entry.severity =3D=3D AER_FATAL) > - pcie_do_recovery(pdev, pci_channel_io_frozen, > - aer_root_reset); > - pci_dev_put(pdev); > + if (pdev) { > + if (entry.severity =3D=3D AER_NONFATAL) > + pcie_do_recovery(pdev, pci_channel_io_normal, > + aer_root_reset); > + else if (entry.severity =3D=3D AER_FATAL) > + pcie_do_recovery(pdev, pci_channel_io_frozen, > + aer_root_reset); > + pci_dev_put(pdev); > + } > } > } [Severity: High] This is a pre-existing issue, but while reviewing this fix for the memory leak in the consumer (aer_recover_work_func), I noticed a similar leak could occur in the producer (aer_recover_queue). In drivers/acpi/apei/ghes.c:ghes_handle_aer(), aer_info is allocated from the ghes_estatus_pool: aer_info =3D (void *)gen_pool_alloc(ghes_estatus_pool, sizeof(struct aer_capability_regs)); /* ... */ aer_recover_queue(pcie_err->device_id.segment, pcie_err->device_id.bus, devfn, aer_severity, (struct aer_capability_regs *) aer_info); If the aer_recover_ring kfifo is full (e.g., during an AER storm with more than 16 errors), kfifo_in_spinlocked() fails in aer_recover_queue(): drivers/pci/pcie/aer.c:aer_recover_queue() { ... if (kfifo_in_spinlocked(&aer_recover_ring, &entry, 1, &aer_recover_ring_lock)) schedule_work(&aer_recover_work); else pr_err("buffer overflow in recovery for %04x:%02x:%02x.%x\n", domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); } Since aer_recover_queue() returns void, the caller ghes_handle_aer() does not know if the queueing failed. The else branch logs a buffer overflow but does not call ghes_estatus_pool_region_free() to release the memory. Could this exhaust the finite ghes_estatus_pool during an AER storm, preventing the system from handling future hardware errors like fatal MCEs? --=20 Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260803183853.4324= [email protected]?part=3D1