mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
mlxsw: spectrum: Fix use-after-free of split/unsplit/type_set in case reload fails
commit4340f42f20upstream. 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:24cc68ad6c("mlxsw: core: Add support for reload") Reported-by: Danielle Ratson <danieller@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
9aeacb829c
commit
c5b2233ad5
@@ -3932,6 +3932,7 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
|
||||
mlxsw_sp_cpu_port_remove(mlxsw_sp);
|
||||
kfree(mlxsw_sp->port_to_module);
|
||||
kfree(mlxsw_sp->ports);
|
||||
mlxsw_sp->ports = NULL;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
|
||||
@@ -3986,6 +3987,7 @@ err_cpu_port_create:
|
||||
kfree(mlxsw_sp->port_to_module);
|
||||
err_port_to_module_alloc:
|
||||
kfree(mlxsw_sp->ports);
|
||||
mlxsw_sp->ports = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -4040,6 +4042,14 @@ static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned int count,
|
||||
struct netlink_ext_ack *extack)
|
||||
@@ -4058,7 +4068,7 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
|
||||
local_ports_in_1x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_1X);
|
||||
local_ports_in_2x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_2X);
|
||||
|
||||
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) {
|
||||
dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
|
||||
local_port);
|
||||
@@ -4136,7 +4146,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
|
||||
local_ports_in_1x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_1X);
|
||||
local_ports_in_2x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_2X);
|
||||
|
||||
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) {
|
||||
dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
|
||||
local_port);
|
||||
|
||||
@@ -1258,6 +1258,7 @@ static void mlxsw_sx_ports_remove(struct mlxsw_sx *mlxsw_sx)
|
||||
if (mlxsw_sx_port_created(mlxsw_sx, i))
|
||||
mlxsw_sx_port_remove(mlxsw_sx, i);
|
||||
kfree(mlxsw_sx->ports);
|
||||
mlxsw_sx->ports = NULL;
|
||||
}
|
||||
|
||||
static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
|
||||
@@ -1292,6 +1293,7 @@ err_port_module_info_get:
|
||||
if (mlxsw_sx_port_created(mlxsw_sx, i))
|
||||
mlxsw_sx_port_remove(mlxsw_sx, i);
|
||||
kfree(mlxsw_sx->ports);
|
||||
mlxsw_sx->ports = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1375,6 +1377,12 @@ static int mlxsw_sx_port_type_set(struct mlxsw_core *mlxsw_core, u8 local_port,
|
||||
u8 module, width;
|
||||
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)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user