[PATCH net] net: ethernet: sunplus: spl2sw: fix multiple of_node refcount leaks in probe
From: Shitalkumar Gandhi <hidden>
Date: 2026-06-07 19:37:34
Also in:
lkml, stable
Subsystem:
networking drivers, sunplus ethernet driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Wells Lu, Linus Torvalds
spl2sw_probe() acquires three of_node references that are never properly
released in all paths:
- eth_ports_np from of_get_child_by_name() leaks on every probe.
- port_np returned from spl2sw_get_eth_child_node() (which exits a
for_each_child_of_node() loop mid-iteration) leaks per loop pass.
- phy_np from of_parse_phandle() leaks on the -EPROBE_DEFER and
spl2sw_init_netdev() failure goto paths, and the registered netdev's
mac->phy_node is not released on the out_unregister_dev cleanup path.
Convert eth_ports_np and port_np to scoped __free(device_node), add
explicit of_node_put(phy_np) on the two early-error gotos where
ownership has not yet been transferred to mac->phy_node, and release
each registered ndev's mac->phy_node in the out_unregister_dev loop
before unregister_netdev().
The mac->phy_node release in the normal driver-remove path is handled
by the preceding fix to spl2sw_phy_remove().
Fixes: fd3040b9394c ("net: ethernet: Add driver for Sunplus SP7021")
Cc: stable@vger.kernel.org
Signed-off-by: Shitalkumar Gandhi <redacted>
---
drivers/net/ethernet/sunplus/spl2sw_driver.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/sunplus/spl2sw_driver.c b/drivers/net/ethernet/sunplus/spl2sw_driver.c
index 5e0e4c9ecbb0..d78bda050ee4 100644
--- a/drivers/net/ethernet/sunplus/spl2sw_driver.c
+++ b/drivers/net/ethernet/sunplus/spl2sw_driver.c@@ -319,10 +319,8 @@ static struct device_node *spl2sw_get_eth_child_node(struct device_node *ether_n static int spl2sw_probe(struct platform_device *pdev) { - struct device_node *eth_ports_np; - struct device_node *port_np; + struct device_node *eth_ports_np __free(device_node) = NULL; struct spl2sw_common *comm; - struct device_node *phy_np; phy_interface_t phy_mode; struct net_device *ndev; struct spl2sw_mac *mac;
@@ -418,8 +416,10 @@ static int spl2sw_probe(struct platform_device *pdev) } for (i = 0; i < MAX_NETDEV_NUM; i++) { - /* Get port@i of node ethernet-ports. */ - port_np = spl2sw_get_eth_child_node(eth_ports_np, i); + struct device_node *port_np __free(device_node) = + spl2sw_get_eth_child_node(eth_ports_np, i); + struct device_node *phy_np; + if (!port_np) continue;
@@ -441,6 +441,7 @@ static int spl2sw_probe(struct platform_device *pdev) /* Get mac-address from nvmem. */ ret = spl2sw_nvmem_get_mac_address(&pdev->dev, port_np, mac_addr); if (ret == -EPROBE_DEFER) { + of_node_put(phy_np); goto out_unregister_dev; } else if (ret) { dev_info(&pdev->dev, "Generate a random mac address!\n");
@@ -449,8 +450,10 @@ static int spl2sw_probe(struct platform_device *pdev) /* Initialize the net device. */ ret = spl2sw_init_netdev(pdev, mac_addr, &ndev); - if (ret) + if (ret) { + of_node_put(phy_np); goto out_unregister_dev; + } ndev->irq = irq; comm->ndev[i] = ndev;
@@ -500,8 +503,11 @@ static int spl2sw_probe(struct platform_device *pdev) out_unregister_dev: for (i = 0; i < MAX_NETDEV_NUM; i++) - if (comm->ndev[i]) + if (comm->ndev[i]) { + mac = netdev_priv(comm->ndev[i]); + of_node_put(mac->phy_node); unregister_netdev(comm->ndev[i]); + } out_free_mdio: spl2sw_mdio_remove(comm);
--
2.25.1