All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] usb: cdns3: Fix PCI device reference leak in cdns3_pci_probe()
@ 2026-10-13  2:08 Ma Ke
  2026-10-13  2:21 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Ma Ke @ 2026-10-13  2:08 UTC (permalink / raw)
  To: peter.chen, pawell, rogerq, gregkh, felipe.balbi
  Cc: linux-usb, linux-kernel, akpm, Ma Ke, stable

cdns3_get_second_fun() looks up the second PCI function with
pci_get_device(), which returns the device with a reference held, and
hands it back to its callers. Neither cdns3_pci_probe() nor
cdns3_pci_remove() ever drops that reference, so the second function's
pci_dev can never be released.

Route the error paths of cdns3_pci_probe() through a put_pci label and
drop the reference there.

cdns3_pci_remove() needs the reference dropped too, and it is missing
a NULL check while at it. cdns3_get_second_fun() can return NULL, and
pci_is_enabled() reads pci_dev->enable_cnt without checking its
argument.

The same error path also frees the wrong object. When the second
function has already been probed, wrap is its drvdata, obtained with
pci_get_drvdata(), and it is shared. The second function keeps
pointing at it, and cdns3_pci_remove() dereferences it when that
function goes away.  Freeing it here leaves that function with a
dangling drvdata.

Both branches that assign wrap are guarded by the same
pci_is_enabled() test as the registration block that can fail, so the
wrap freed there is always the one taken from the sibling function.
Track whether wrap was allocated here and only free it in that case.

Found by code review.

Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
Cc: stable@vger.kernel.org
Signed-off-by: Ma Ke <make_ruc2021@163.com>
---
Changes in v3:
- Do not free a wrap that was taken from the second function's drvdata.
  The free in that error path can only ever run on the shared object, so
  it left the sibling function with a dangling drvdata. Reported by
  Sashiko. cdnsp-pci.c has the same construct.
- Keep the rest of v2.
Changes in v2:
- rebase on current mainline. cdns3_pci_probe() gained a -EPROBE_DEFER
  path in e5052f2c5c73 that returns after the reference has been taken, 
  so it has to drop it too.
---
 drivers/usb/cdns3/cdns3-pci-wrap.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/cdns3/cdns3-pci-wrap.c b/drivers/usb/cdns3/cdns3-pci-wrap.c
index fd06a3d8e638..31089eb9ca29 100644
--- a/drivers/usb/cdns3/cdns3-pci-wrap.c
+++ b/drivers/usb/cdns3/cdns3-pci-wrap.c
@@ -72,6 +72,7 @@ static int cdns3_pci_probe(struct pci_dev *pdev,
 	struct cdns3_wrap *wrap;
 	struct resource *res;
 	struct pci_dev *func;
+	bool own_wrap;
 	int err;
 
 	/*
@@ -99,12 +100,17 @@ static int cdns3_pci_probe(struct pci_dev *pdev,
 		if (!wrap) {
 			dev_err(&pdev->dev,
 				"second function not initialized, retrying\n");
-			return -EPROBE_DEFER;
+			err = -EPROBE_DEFER;
+			goto put_pci;
 		}
+		own_wrap = false;
 	} else {
 		wrap = kzalloc_obj(*wrap);
-		if (!wrap)
-			return -ENOMEM;
+		if (!wrap) {
+			err = -ENOMEM;
+			goto put_pci;
+		}
+		own_wrap = true;
 	}
 
 	res = wrap->dev_res;
@@ -164,12 +170,15 @@ static int cdns3_pci_probe(struct pci_dev *pdev,
 		wrap->plat_dev = platform_device_register_full(&plat_info);
 		if (IS_ERR(wrap->plat_dev)) {
 			err = PTR_ERR(wrap->plat_dev);
-			kfree(wrap);
-			return err;
+			if (own_wrap)
+				kfree(wrap);
+			goto put_pci;
 		}
 	}
 
 	pci_set_drvdata(pdev, wrap);
+put_pci:
+	pci_dev_put(func);
 	return err;
 }
 
@@ -184,8 +193,10 @@ static void cdns3_pci_remove(struct pci_dev *pdev)
 	if (wrap->devfn == pdev->devfn)
 		platform_device_unregister(wrap->plat_dev);
 
-	if (!pci_is_enabled(func))
+	if (!func || !pci_is_enabled(func))
 		kfree(wrap);
+
+	pci_dev_put(func);
 }
 
 static const struct pci_device_id cdns3_pci_ids[] = {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-13  2:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13  2:08 [PATCH v3] usb: cdns3: Fix PCI device reference leak in cdns3_pci_probe() Ma Ke
2026-10-13  2:21 ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.