Skip to content

Commit

Permalink
mlxsw: spectrum: Guard against invalid local ports
Browse files Browse the repository at this point in the history
When processing events generated by the device's firmware, the driver
protects itself from events reported for non-existent local ports, but
not for the CPU port (local port 0), which exists, but does not have all
the fields as any local port.

This can result in a NULL pointer dereference when trying access
'struct mlxsw_sp_port' fields which are not initialized for CPU port.

Commit 63b08b1 ("mlxsw: spectrum: Protect driver from buggy firmware")
already handled such issue by bailing early when processing a PUDE event
reported for the CPU port.

Generalize the approach by moving the check to a common function and
making use of it in all relevant places.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Amit Cohen authored and Jakub Kicinski committed Jan 28, 2022
1 parent 636d3ad commit bcdfd61
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 7 deletions.
4 changes: 1 addition & 3 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -2148,13 +2148,11 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
struct mlxsw_sp *mlxsw_sp = priv;
struct mlxsw_sp_port *mlxsw_sp_port;
enum mlxsw_reg_pude_oper_status status;
unsigned int max_ports;
u16 local_port;

max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
local_port = mlxsw_reg_pude_local_port_get(pude_pl);

if (WARN_ON_ONCE(!local_port || local_port >= max_ports))
if (WARN_ON_ONCE(!mlxsw_sp_local_port_is_valid(mlxsw_sp, local_port)))
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port)
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ int
mlxsw_sp_port_vlan_classification_set(struct mlxsw_sp_port *mlxsw_sp_port,
bool is_8021ad_tagged,
bool is_8021q_tagged);
static inline bool
mlxsw_sp_local_port_is_valid(struct mlxsw_sp *mlxsw_sp, u16 local_port)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);

return local_port < max_ports && local_port;
}

/* spectrum_buffers.c */
struct mlxsw_sp_hdroom_prio {
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,12 +568,11 @@ void mlxsw_sp1_ptp_got_timestamp(struct mlxsw_sp *mlxsw_sp, bool ingress,
u8 domain_number, u16 sequence_id,
u64 timestamp)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
struct mlxsw_sp_port *mlxsw_sp_port;
struct mlxsw_sp1_ptp_key key;
u8 types;

if (WARN_ON_ONCE(local_port >= max_ports))
if (WARN_ON_ONCE(!mlxsw_sp_local_port_is_valid(mlxsw_sp, local_port)))
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port)
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2616,7 +2616,6 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
char *sfn_pl, int rec_index,
bool adding)
{
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
struct mlxsw_sp_bridge_device *bridge_device;
struct mlxsw_sp_bridge_port *bridge_port;
Expand All @@ -2630,7 +2629,7 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,

mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port);

if (WARN_ON_ONCE(local_port >= max_ports))
if (WARN_ON_ONCE(!mlxsw_sp_local_port_is_valid(mlxsw_sp, local_port)))
return;
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port) {
Expand Down

0 comments on commit bcdfd61

Please sign in to comment.