Commit 4340f42f authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

mlxsw: spectrum: Fix use-after-free of split/unsplit/type_set in case reload fails

In case of reload fail, the mlxsw_sp->ports contains a pointer to a
freed memory (either by reload_down() or reload_up() error path).
Fix this by initializing the pointer to NULL and checking it before
dereferencing in split/unsplit/type_set callpaths.

Fixes: 24cc68ad ("mlxsw: core: Add support for reload")
Reported-by: default avatarDanielle Ratson <danieller@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a96ac8a0
...@@ -3986,6 +3986,7 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) ...@@ -3986,6 +3986,7 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp_port_remove(mlxsw_sp, i); mlxsw_sp_port_remove(mlxsw_sp, i);
mlxsw_sp_cpu_port_remove(mlxsw_sp); mlxsw_sp_cpu_port_remove(mlxsw_sp);
kfree(mlxsw_sp->ports); kfree(mlxsw_sp->ports);
mlxsw_sp->ports = NULL;
} }
static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
...@@ -4022,6 +4023,7 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) ...@@ -4022,6 +4023,7 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp_cpu_port_remove(mlxsw_sp); mlxsw_sp_cpu_port_remove(mlxsw_sp);
err_cpu_port_create: err_cpu_port_create:
kfree(mlxsw_sp->ports); kfree(mlxsw_sp->ports);
mlxsw_sp->ports = NULL;
return err; return err;
} }
...@@ -4143,6 +4145,14 @@ static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core, ...@@ -4143,6 +4145,14 @@ static int mlxsw_sp_local_ports_offset(struct mlxsw_core *mlxsw_core,
return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id); return mlxsw_core_res_get(mlxsw_core, local_ports_in_x_res_id);
} }
static struct mlxsw_sp_port *
mlxsw_sp_port_get_by_local_port(struct mlxsw_sp *mlxsw_sp, u8 local_port)
{
if (mlxsw_sp->ports && mlxsw_sp->ports[local_port])
return mlxsw_sp->ports[local_port];
return NULL;
}
static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
unsigned int count, unsigned int count,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
...@@ -4156,7 +4166,7 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port, ...@@ -4156,7 +4166,7 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
int i; int i;
int err; int err;
mlxsw_sp_port = mlxsw_sp->ports[local_port]; mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port);
if (!mlxsw_sp_port) { if (!mlxsw_sp_port) {
dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n", dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
local_port); local_port);
...@@ -4251,7 +4261,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port, ...@@ -4251,7 +4261,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
int offset; int offset;
int i; int i;
mlxsw_sp_port = mlxsw_sp->ports[local_port]; mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port);
if (!mlxsw_sp_port) { if (!mlxsw_sp_port) {
dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n", dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
local_port); local_port);
......
...@@ -1259,6 +1259,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx) ...@@ -1259,6 +1259,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx)
if (mlxsw_sx_port_created(mlxsw_sx, i)) if (mlxsw_sx_port_created(mlxsw_sx, i))
mlxsw_sx_port_remove(mlxsw_sx, i); mlxsw_sx_port_remove(mlxsw_sx, i);
kfree(mlxsw_sx->ports); kfree(mlxsw_sx->ports);
mlxsw_sx->ports = NULL;
} }
static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
...@@ -1293,6 +1294,7 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx) ...@@ -1293,6 +1294,7 @@ static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
if (mlxsw_sx_port_created(mlxsw_sx, i)) if (mlxsw_sx_port_created(mlxsw_sx, i))
mlxsw_sx_port_remove(mlxsw_sx, i); mlxsw_sx_port_remove(mlxsw_sx, i);
kfree(mlxsw_sx->ports); kfree(mlxsw_sx->ports);
mlxsw_sx->ports = NULL;
return err; return err;
} }
...@@ -1376,6 +1378,12 @@ static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port, ...@@ -1376,6 +1378,12 @@ static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port,
u8 module, width; u8 module, width;
int err; int err;
if (!mlxsw_sx->ports || !mlxsw_sx->ports[local_port]) {
dev_err(mlxsw_sx->bus_info->dev, "Port number \"%d\" does not exist\n",
local_port);
return -EINVAL;
}
if (new_type == DEVLINK_PORT_TYPE_AUTO) if (new_type == DEVLINK_PORT_TYPE_AUTO)
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment