Skip to content

Commit c28947d

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum_buffers: Fix memory corruptions on Spectrum-4 systems
The following two shared buffer operations make use of the Shared Buffer Status Register (SBSR): # devlink sb occupancy snapshot pci/0000:01:00.0 # devlink sb occupancy clearmax pci/0000:01:00.0 The register has two masks of 256 bits to denote on which ingress / egress ports the register should operate on. Spectrum-4 has more than 256 ports, so the register was extended by cited commit with a new 'port_page' field. However, when filling the register's payload, the driver specifies the ports as absolute numbers and not relative to the first port of the port page, resulting in memory corruptions [1]. Fix by specifying the ports relative to the first port of the port page. [1] BUG: KASAN: slab-use-after-free in mlxsw_sp_sb_occ_snapshot+0xb6d/0xbc0 Read of size 1 at addr ffff8881068cb00f by task devlink/1566 [...] Call Trace: <TASK> dump_stack_lvl+0xc6/0x120 print_report+0xce/0x670 kasan_report+0xd7/0x110 mlxsw_sp_sb_occ_snapshot+0xb6d/0xbc0 mlxsw_devlink_sb_occ_snapshot+0x75/0xb0 devlink_nl_sb_occ_snapshot_doit+0x1f9/0x2a0 genl_family_rcv_msg_doit+0x20c/0x300 genl_rcv_msg+0x567/0x800 netlink_rcv_skb+0x170/0x450 genl_rcv+0x2d/0x40 netlink_unicast+0x547/0x830 netlink_sendmsg+0x8d4/0xdb0 __sys_sendto+0x49b/0x510 __x64_sys_sendto+0xe5/0x1c0 do_syscall_64+0xc1/0x1d0 entry_SYSCALL_64_after_hwframe+0x77/0x7f [...] Allocated by task 1: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0x8f/0xa0 copy_verifier_state+0xbc2/0xfb0 do_check_common+0x2c51/0xc7e0 bpf_check+0x5107/0x9960 bpf_prog_load+0xf0e/0x2690 __sys_bpf+0x1a61/0x49d0 __x64_sys_bpf+0x7d/0xc0 do_syscall_64+0xc1/0x1d0 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 1: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 poison_slab_object+0x109/0x170 __kasan_slab_free+0x14/0x30 kfree+0xca/0x2b0 free_verifier_state+0xce/0x270 do_check_common+0x4828/0xc7e0 bpf_check+0x5107/0x9960 bpf_prog_load+0xf0e/0x2690 __sys_bpf+0x1a61/0x49d0 __x64_sys_bpf+0x7d/0xc0 do_syscall_64+0xc1/0x1d0 entry_SYSCALL_64_after_hwframe+0x77/0x7f Fixes: f8538ae ("mlxsw: Add support for more than 256 ports in SBSR register") Signed-off-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Petr Machata <petrm@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 0602697 commit c28947d

1 file changed

Lines changed: 14 additions & 6 deletions

File tree

drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,8 +1607,8 @@ static void mlxsw_sp_sb_sr_occ_query_cb(struct mlxsw_core *mlxsw_core,
16071607
int mlxsw_sp_sb_occ_snapshot(struct mlxsw_core *mlxsw_core,
16081608
unsigned int sb_index)
16091609
{
1610+
u16 local_port, local_port_1, first_local_port, last_local_port;
16101611
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1611-
u16 local_port, local_port_1, last_local_port;
16121612
struct mlxsw_sp_sb_sr_occ_query_cb_ctx cb_ctx;
16131613
u8 masked_count, current_page = 0;
16141614
unsigned long cb_priv = 0;
@@ -1628,6 +1628,7 @@ int mlxsw_sp_sb_occ_snapshot(struct mlxsw_core *mlxsw_core,
16281628
masked_count = 0;
16291629
mlxsw_reg_sbsr_pack(sbsr_pl, false);
16301630
mlxsw_reg_sbsr_port_page_set(sbsr_pl, current_page);
1631+
first_local_port = current_page * MLXSW_REG_SBSR_NUM_PORTS_IN_PAGE;
16311632
last_local_port = current_page * MLXSW_REG_SBSR_NUM_PORTS_IN_PAGE +
16321633
MLXSW_REG_SBSR_NUM_PORTS_IN_PAGE - 1;
16331634

@@ -1645,9 +1646,12 @@ int mlxsw_sp_sb_occ_snapshot(struct mlxsw_core *mlxsw_core,
16451646
if (local_port != MLXSW_PORT_CPU_PORT) {
16461647
/* Ingress quotas are not supported for the CPU port */
16471648
mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl,
1648-
local_port, 1);
1649+
local_port - first_local_port,
1650+
1);
16491651
}
1650-
mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1);
1652+
mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl,
1653+
local_port - first_local_port,
1654+
1);
16511655
for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
16521656
err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i,
16531657
&bulk_list);
@@ -1684,7 +1688,7 @@ int mlxsw_sp_sb_occ_max_clear(struct mlxsw_core *mlxsw_core,
16841688
unsigned int sb_index)
16851689
{
16861690
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1687-
u16 local_port, last_local_port;
1691+
u16 local_port, first_local_port, last_local_port;
16881692
LIST_HEAD(bulk_list);
16891693
unsigned int masked_count;
16901694
u8 current_page = 0;
@@ -1702,6 +1706,7 @@ int mlxsw_sp_sb_occ_max_clear(struct mlxsw_core *mlxsw_core,
17021706
masked_count = 0;
17031707
mlxsw_reg_sbsr_pack(sbsr_pl, true);
17041708
mlxsw_reg_sbsr_port_page_set(sbsr_pl, current_page);
1709+
first_local_port = current_page * MLXSW_REG_SBSR_NUM_PORTS_IN_PAGE;
17051710
last_local_port = current_page * MLXSW_REG_SBSR_NUM_PORTS_IN_PAGE +
17061711
MLXSW_REG_SBSR_NUM_PORTS_IN_PAGE - 1;
17071712

@@ -1719,9 +1724,12 @@ int mlxsw_sp_sb_occ_max_clear(struct mlxsw_core *mlxsw_core,
17191724
if (local_port != MLXSW_PORT_CPU_PORT) {
17201725
/* Ingress quotas are not supported for the CPU port */
17211726
mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl,
1722-
local_port, 1);
1727+
local_port - first_local_port,
1728+
1);
17231729
}
1724-
mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1);
1730+
mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl,
1731+
local_port - first_local_port,
1732+
1);
17251733
for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
17261734
err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i,
17271735
&bulk_list);

0 commit comments

Comments
 (0)