DORMANTno replies

[PATCH 6/6] perf/x86/intel/uncore: Fix PCI device reference leak in box register paths

From: Wentao Liang <hidden>
Date: 2026-09-15 04:39:06
Also in: lkml, stable
Subsystem: performance events subsystem, the rest, x86 architecture (32-bit and 64-bit) · Maintainers: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Linus Torvalds, Thomas Gleixner, Borislav Petkov, Dave Hansen

uncore_pci_pmus_register() obtains a PCI device reference with
pci_get_domain_bus_and_slot() and hands it to uncore_pci_pmu_register(),
which stores the device in box->pci_dev.  Nothing ever drops the
reference: both uncore_pci_pmu_unregister() and the PMU registration
failure path in uncore_pci_pmu_register() simply kfree() the box, so
one device reference is leaked per registered box, and each discovery
loop iteration additionally drops the previous reference on the floor
when it looks up the next unit.

Make the box own a reference to its PCI device instead: take an extra
reference in uncore_pci_pmu_register() and drop it in both box release
paths, and have uncore_pci_pmus_register() release its own reference
right after registering the box.  This also covers the case where
uncore_pmu_register() fails after the box has been installed.  The
reference held by the driver core for a device probed by the uncore
PCI driver is left alone, since it belongs to the PCI core and must
not be put.

Fixes: f76a8420444b ("perf/x86/uncore: Apply the unit control RB tree to PCI uncore units")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <redacted>
---
 arch/x86/events/intel/uncore.c | 4 ++++
 1 file changed, 4 insertions(+)
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index e9cc1ba921c5..70f654e06ef6 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -1154,6 +1154,7 @@ static int uncore_pci_pmu_register(struct pci_dev *pdev,
 	atomic_inc(&box->refcnt);
 	box->dieid = die;
 	box->pci_dev = pdev;
+	pci_dev_get(pdev);
 	box->pmu = pmu;
 	uncore_box_init(box);
 
@@ -1166,6 +1167,7 @@ static int uncore_pci_pmu_register(struct pci_dev *pdev,
 	if (ret) {
 		pmu->boxes[die] = NULL;
 		uncore_box_exit(box);
+		pci_dev_put(box->pci_dev);
 		kfree(box);
 	}
 	return ret;
@@ -1233,6 +1235,7 @@ static void uncore_pci_pmu_unregister(struct intel_uncore_pmu *pmu, int die)
 	if (atomic_dec_return(&pmu->activeboxes) == 0)
 		uncore_pmu_unregister(pmu);
 	uncore_box_exit(box);
+	pci_dev_put(box->pci_dev);
 	kfree(box);
 }
 
@@ -1376,6 +1379,7 @@ static void uncore_pci_pmus_register(void)
 				continue;
 			pmu = &type->pmus[unit->pmu_idx];
 			uncore_pci_pmu_register(pdev, type, pmu, unit->die);
+			pci_dev_put(pdev);
 		}
 	}
 
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help