net: dsa: bcm_sf2: Fix possible memory leak in bcm_sf2_mdio_register()
commit 61b40cefe51af005c72dbdcf975a3d166c6e6406 upstream. 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: 461cd1b03e32 ("net: dsa: bcm_sf2: Register our slave MDIO bus") Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> Suggested-by: Simon Horman <horms@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com> Link: https://lore.kernel.org/r/20231011032419.2423290-1-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
30b7e67e33
commit
ccb950513d
1 changed files with 15 additions and 9 deletions
|
@ -497,17 +497,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;
|
||||
|
@ -564,11 +563,17 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
|
|||
}
|
||||
|
||||
err = mdiobus_register(priv->slave_mii_bus);
|
||||
if (err && dn) {
|
||||
mdiobus_free(priv->slave_mii_bus);
|
||||
of_node_put(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;
|
||||
}
|
||||
|
||||
|
@ -576,6 +581,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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue