Commit 61b40cef authored by Jinjie Ruan's avatar Jinjie Ruan Committed by Jakub Kicinski
Browse files

net: dsa: bcm_sf2: Fix possible memory leak in bcm_sf2_mdio_register()



In bcm_sf2_mdio_register(), the class_find_device() will call get_device()
to increment reference count for priv->master_mii_bus->dev if
of_mdio_find_bus() succeeds. If mdiobus_alloc() or mdiobus_register()
fails, it will call get_device() twice without decrement reference count
for the device. And it is the same if bcm_sf2_mdio_register() succeeds but
fails in bcm_sf2_sw_probe(), or if bcm_sf2_sw_probe() succeeds. If the
reference count has not decremented to zero, the dev related resource will
not be freed.

So remove the get_device() in bcm_sf2_mdio_register(), and call
put_device() if mdiobus_alloc() or mdiobus_register() fails and in
bcm_sf2_mdio_unregister() to solve the issue.

And as Simon suggested, unwind from errors for bcm_sf2_mdio_register() and
just return 0 if it succeeds to make it cleaner.

Fixes: 461cd1b0 ("net: dsa: bcm_sf2: Register our slave MDIO bus")
Signed-off-by: default avatarJinjie Ruan <ruanjinjie@huawei.com>
Suggested-by: default avatarSimon Horman <horms@kernel.org>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Reviewed-by: default avatarFlorian Fainelli <florian.fainelli@broadcom.com>
Link: https://lore.kernel.org/r/20231011032419.2423290-1-ruanjinjie@huawei.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent dda5e1ee
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -617,17 +617,16 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
	dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio");
	priv->master_mii_bus = of_mdio_find_bus(dn);
	if (!priv->master_mii_bus) {
		of_node_put(dn);
		return -EPROBE_DEFER;
		err = -EPROBE_DEFER;
		goto err_of_node_put;
	}

	get_device(&priv->master_mii_bus->dev);
	priv->master_mii_dn = dn;

	priv->slave_mii_bus = mdiobus_alloc();
	if (!priv->slave_mii_bus) {
		of_node_put(dn);
		return -ENOMEM;
		err = -ENOMEM;
		goto err_put_master_mii_bus_dev;
	}

	priv->slave_mii_bus->priv = priv;
@@ -684,11 +683,17 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
	}

	err = mdiobus_register(priv->slave_mii_bus);
	if (err && dn) {
	if (err && dn)
		goto err_free_slave_mii_bus;

	return 0;

err_free_slave_mii_bus:
	mdiobus_free(priv->slave_mii_bus);
err_put_master_mii_bus_dev:
	put_device(&priv->master_mii_bus->dev);
err_of_node_put:
	of_node_put(dn);
	}

	return err;
}

@@ -696,6 +701,7 @@ static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv)
{
	mdiobus_unregister(priv->slave_mii_bus);
	mdiobus_free(priv->slave_mii_bus);
	put_device(&priv->master_mii_bus->dev);
	of_node_put(priv->master_mii_dn);
}