4.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Shalom Toledo <shal...@mellanox.com>

[ 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 <shal...@mellanox.com>
Reviewed-by: Jiri Pirko <j...@mellanox.com>
Signed-off-by: Ido Schimmel <ido...@mellanox.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 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);
 }


Reply via email to