[PATCH net-next] net: ethernet: adi: adin1110: Fix phy_device leak in probe_netdevs()

From
Xia Yan <hidden>
Date
2026-11-06 07:23:06
Also in
lkml
adin1110_probe_netdevs() probes each port with get_phy_device(), which
allocates a phy_device without registering it. The pointer's only use
is phydev_name() for the phy_connect() call, and phy_connect() attaches
the device the earlier bus scan registered, not the one allocated here.
port_priv->phydev is then overwritten with the phy_connect() result and
the allocated object is lost.

The devm cleanup action only disconnects the PHY that phy_connect()
attached, so nothing frees the lost object: one struct phy_device per
port leaks on every probe.

Keep the get_phy_device() result in a local variable and free it with
phy_device_free() after phy_connect() returns, success or not, as
mdiobus_scan() already does when phy_device_register() fails.

Found during a code review of the MDIO attach paths. get_phy_device()
only calls phy_device_create(), and phy_connect() can only return a
registered device.

Signed-off-by: Xia Yan <redacted>
---
 drivers/net/ethernet/adi/adin1110.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c
index 53fac3d..fd769f1 100644
--- a/drivers/net/ethernet/adi/adin1110.c
+++ b/drivers/net/ethernet/adi/adin1110.c
@@ -1571,6 +1571,7 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv)
 	struct device *dev = &priv->spidev->dev;
 	struct adin1110_port_priv *port_priv;
 	struct net_device *netdev;
+	struct phy_device *phydev;
 	int ret;
 	int i;
 
@@ -1604,16 +1605,17 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv)
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 		netdev->netns_immutable = true;
 
-		port_priv->phydev = get_phy_device(priv->mii_bus, i + 1, false);
-		if (IS_ERR(port_priv->phydev)) {
+		phydev = get_phy_device(priv->mii_bus, i + 1, false);
+		if (IS_ERR(phydev)) {
 			netdev_err(netdev, "Could not find PHY with device address: %d.\n", i);
-			return PTR_ERR(port_priv->phydev);
+			return PTR_ERR(phydev);
 		}
 
 		port_priv->phydev = phy_connect(netdev,
-						phydev_name(port_priv->phydev),
+						phydev_name(phydev),
 						adin1110_adjust_link,
 						PHY_INTERFACE_MODE_INTERNAL);
+		phy_device_free(phydev);
 		if (IS_ERR(port_priv->phydev)) {
 			netdev_err(netdev, "Could not connect PHY with device address: %d.\n", i);
 			return PTR_ERR(port_priv->phydev);

Thread (4 messages) 4 messages, 3 authors, last reply 1d ago
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help