Skip to content

Commit 483ae90

Browse files
idoschkuba-moo
authored andcommitted
mlxsw: spectrum_acl_tcam: Fix stack corruption
When tc filters are first added to a net device, the corresponding local port gets bound to an ACL group in the device. The group contains a list of ACLs. In turn, each ACL points to a different TCAM region where the filters are stored. During forwarding, the ACLs are sequentially evaluated until a match is found. One reason to place filters in different regions is when they are added with decreasing priorities and in an alternating order so that two consecutive filters can never fit in the same region because of their key usage. In Spectrum-2 and newer ASICs the firmware started to report that the maximum number of ACLs in a group is more than 16, but the layout of the register that configures ACL groups (PAGT) was not updated to account for that. It is therefore possible to hit stack corruption [1] in the rare case where more than 16 ACLs in a group are required. Fix by limiting the maximum ACL group size to the minimum between what the firmware reports and the maximum ACLs that fit in the PAGT register. Add a test case to make sure the machine does not crash when this condition is hit. [1] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: mlxsw_sp_acl_tcam_group_update+0x116/0x120 [...] dump_stack_lvl+0x36/0x50 panic+0x305/0x330 __stack_chk_fail+0x15/0x20 mlxsw_sp_acl_tcam_group_update+0x116/0x120 mlxsw_sp_acl_tcam_group_region_attach+0x69/0x110 mlxsw_sp_acl_tcam_vchunk_get+0x492/0xa20 mlxsw_sp_acl_tcam_ventry_add+0x25/0xe0 mlxsw_sp_acl_rule_add+0x47/0x240 mlxsw_sp_flower_replace+0x1a9/0x1d0 tc_setup_cb_add+0xdc/0x1c0 fl_hw_replace_filter+0x146/0x1f0 fl_change+0xc17/0x1360 tc_new_tfilter+0x472/0xb90 rtnetlink_rcv_msg+0x313/0x3b0 netlink_rcv_skb+0x58/0x100 netlink_unicast+0x244/0x390 netlink_sendmsg+0x1e4/0x440 ____sys_sendmsg+0x164/0x260 ___sys_sendmsg+0x9a/0xe0 __sys_sendmsg+0x7a/0xc0 do_syscall_64+0x40/0xe0 entry_SYSCALL_64_after_hwframe+0x63/0x6b Fixes: c3ab435 ("mlxsw: spectrum: Extend to support Spectrum-2 ASIC") Reported-by: Orel Hagag <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Amit Cohen <[email protected]> Signed-off-by: Petr Machata <[email protected]> Acked-by: Paolo Abeni <[email protected]> Link: https://lore.kernel.org/r/2d91c89afba59c22587b444994ae419dbea8d876.1705502064.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent efeb7df commit 483ae90

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
15641564
tcam->max_groups = max_groups;
15651565
tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
15661566
ACL_MAX_GROUP_SIZE);
1567+
tcam->max_group_size = min_t(unsigned int, tcam->max_group_size,
1568+
MLXSW_REG_PAGT_ACL_MAX_NUM);
15671569

15681570
err = ops->init(mlxsw_sp, tcam->priv, tcam);
15691571
if (err)

tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ ALL_TESTS="single_mask_test identical_filters_test two_masks_test \
1111
multiple_masks_test ctcam_edge_cases_test delta_simple_test \
1212
delta_two_masks_one_key_test delta_simple_rehash_test \
1313
bloom_simple_test bloom_complex_test bloom_delta_test \
14-
max_erp_entries_test"
14+
max_erp_entries_test max_group_size_test"
1515
NUM_NETIFS=2
1616
source $lib_dir/lib.sh
1717
source $lib_dir/tc_common.sh
@@ -1033,6 +1033,60 @@ max_erp_entries_test()
10331033
"max chain $chain_failed, mask $mask_failed"
10341034
}
10351035

1036+
max_group_size_test()
1037+
{
1038+
# The number of ACLs in an ACL group is limited. Once the maximum
1039+
# number of ACLs has been reached, filters cannot be added. This test
1040+
# verifies that when this limit is reached, insertion fails without
1041+
# crashing.
1042+
1043+
RET=0
1044+
1045+
local num_acls=32
1046+
local max_size
1047+
local ret
1048+
1049+
if [[ "$tcflags" != "skip_sw" ]]; then
1050+
return 0;
1051+
fi
1052+
1053+
for ((i=1; i < $num_acls; i++)); do
1054+
if [[ $(( i % 2 )) == 1 ]]; then
1055+
tc filter add dev $h2 ingress pref $i proto ipv4 \
1056+
flower $tcflags dst_ip 198.51.100.1/32 \
1057+
ip_proto tcp tcp_flags 0x01/0x01 \
1058+
action drop &> /dev/null
1059+
else
1060+
tc filter add dev $h2 ingress pref $i proto ipv6 \
1061+
flower $tcflags dst_ip 2001:db8:1::1/128 \
1062+
action drop &> /dev/null
1063+
fi
1064+
1065+
ret=$?
1066+
[[ $ret -ne 0 ]] && max_size=$((i - 1)) && break
1067+
done
1068+
1069+
# We expect to exceed the maximum number of ACLs in a group, so that
1070+
# insertion eventually fails. Otherwise, the test should be adjusted to
1071+
# add more filters.
1072+
check_fail $ret "expected to exceed number of ACLs in a group"
1073+
1074+
for ((; i >= 1; i--)); do
1075+
if [[ $(( i % 2 )) == 1 ]]; then
1076+
tc filter del dev $h2 ingress pref $i proto ipv4 \
1077+
flower $tcflags dst_ip 198.51.100.1/32 \
1078+
ip_proto tcp tcp_flags 0x01/0x01 \
1079+
action drop &> /dev/null
1080+
else
1081+
tc filter del dev $h2 ingress pref $i proto ipv6 \
1082+
flower $tcflags dst_ip 2001:db8:1::1/128 \
1083+
action drop &> /dev/null
1084+
fi
1085+
done
1086+
1087+
log_test "max ACL group size test ($tcflags). max size $max_size"
1088+
}
1089+
10361090
setup_prepare()
10371091
{
10381092
h1=${NETIFS[p1]}

0 commit comments

Comments
 (0)