mlxsw: core: Fix devlink unregister flow

After a failed reload, the driver is still registered to devlink, its
devlink instance is still allocated and the 'reload_fail' flag is set.
Then, in the next reload try, the driver's allocated devlink instance will
be freed without unregistering from devlink and its components (e.g,
resources). This scenario can cause a use-after-free if the user tries to
execute command via devlink user-space tool.

Fix by not freeing the devlink instance during reload (failed or not).

Fixes: 24cc68ad6c ("mlxsw: core: Add support for reload")
Signed-off-by: Shalom Toledo <shalomt@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Shalom Toledo 2018-10-29 14:26:16 +00:00 committed by David S. Miller
parent ad0b9d9418
commit a22712a962
1 changed files with 17 additions and 7 deletions

View File

@ -943,8 +943,8 @@ static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink,
mlxsw_core->bus, mlxsw_core->bus,
mlxsw_core->bus_priv, true, mlxsw_core->bus_priv, true,
devlink); devlink);
if (err) mlxsw_core->reload_fail = !!err;
mlxsw_core->reload_fail = true;
return err; return err;
} }
@ -1083,8 +1083,15 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
{ {
struct devlink *devlink = priv_to_devlink(mlxsw_core); struct devlink *devlink = priv_to_devlink(mlxsw_core);
if (mlxsw_core->reload_fail) if (mlxsw_core->reload_fail) {
goto reload_fail; if (!reload)
/* Only the parts that were not de-initialized in the
* failed reload attempt need to be de-initialized.
*/
goto reload_fail_deinit;
else
return;
}
if (mlxsw_core->driver->fini) if (mlxsw_core->driver->fini)
mlxsw_core->driver->fini(mlxsw_core); mlxsw_core->driver->fini(mlxsw_core);
@ -1098,9 +1105,12 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
if (!reload) if (!reload)
devlink_resources_unregister(devlink, NULL); devlink_resources_unregister(devlink, NULL);
mlxsw_core->bus->fini(mlxsw_core->bus_priv); mlxsw_core->bus->fini(mlxsw_core->bus_priv);
if (reload)
return; return;
reload_fail:
reload_fail_deinit:
devlink_unregister(devlink);
devlink_resources_unregister(devlink, NULL);
devlink_free(devlink); devlink_free(devlink);
} }
EXPORT_SYMBOL(mlxsw_core_bus_device_unregister); EXPORT_SYMBOL(mlxsw_core_bus_device_unregister);