[PATCH 4.18 141/150] mlxsw: core: Fix devlink unregister flow
From: Greg Kroah-Hartman
Date: Fri Nov 02 2018 - 14:45:56 EST
4.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shalom Toledo <shalomt@xxxxxxxxxxxx>
[ Upstream commit a22712a962912faf257e857ab6857f56a93cfb34 ]
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: 24cc68ad6c46 ("mlxsw: core: Add support for reload")
Signed-off-by: Shalom Toledo <shalomt@xxxxxxxxxxxx>
Reviewed-by: Jiri Pirko <jiri@xxxxxxxxxxxx>
Signed-off-by: Ido Schimmel <idosch@xxxxxxxxxxxx>
Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/net/ethernet/mellanox/mlxsw/core.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -985,8 +985,8 @@ static int mlxsw_devlink_core_bus_device
mlxsw_core->bus,
mlxsw_core->bus_priv, true,
devlink);
- if (err)
- mlxsw_core->reload_fail = true;
+ mlxsw_core->reload_fail = !!err;
+
return err;
}
@@ -1126,8 +1126,15 @@ void mlxsw_core_bus_device_unregister(st
const char *device_kind = mlxsw_core->bus_info->device_kind;
struct devlink *devlink = priv_to_devlink(mlxsw_core);
- if (mlxsw_core->reload_fail)
- goto reload_fail;
+ if (mlxsw_core->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)
mlxsw_core->driver->fini(mlxsw_core);
@@ -1140,9 +1147,12 @@ void mlxsw_core_bus_device_unregister(st
if (!reload)
devlink_resources_unregister(devlink, NULL);
mlxsw_core->bus->fini(mlxsw_core->bus_priv);
- if (reload)
- return;
-reload_fail:
+
+ return;
+
+reload_fail_deinit:
+ devlink_unregister(devlink);
+ devlink_resources_unregister(devlink, NULL);
devlink_free(devlink);
mlxsw_core_driver_put(device_kind);
}