From 7ea07afb230f1342ab0f9365edd0aae137f425d3 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 6 Oct 2026 16:21:28 +0200 Subject: mlxsw: spectrum_flower: Fix port range register leak in tmplt_create() mlxsw_sp_flower_tmplt_create() parses a flow_cls_offload template into a stack-local struct mlxsw_sp_acl_rule_info purely to compute rulei.values.elusage. Parsing can acquire port range registers via mlxsw_sp_flower_parse_ports_range(), but since this rulei never goes through mlxsw_sp_acl_rulei_destroy(), those registers were never released, including through chain template deletion. Factor out of mlxsw_sp_acl_rulei_destroy() the code to actually release the necessary resources and call from mlxsw_sp_flower_tmplt_create() to plug the leak. The issue was found during a review of Wentao Liang's patch referenced below. Fixes: fe22f7410527 ("mlxsw: spectrum_flower: Add ability to match on port ranges") Reported-by: Wentao Liang Closes: https://lore.kernel.org/netdev/20260917113236.2149095-1-vulab@iscas.ac.cn/ Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Reviewed-by: Jacob Keller Link: https://patch.msgid.link/95339cf970ce78e1a74aa86ffcc104ecf7c7762c.1791294384.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 10 ++++++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 9 +++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index b03ff9e044f9..10af08ce72ef 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -989,6 +989,8 @@ void mlxsw_sp_acl_ruleset_prio_get(struct mlxsw_sp_acl_ruleset *ruleset, struct mlxsw_sp_acl_rule_info * mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl, struct mlxsw_afa_block *afa_block); +void mlxsw_sp_acl_rulei_free(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_rule_info *rulei); void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei); int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index cb232accb296..f7be4f3a1518 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -340,8 +340,8 @@ err_afa_block_create: return ERR_PTR(err); } -void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_rule_info *rulei) +void mlxsw_sp_acl_rulei_free(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_rule_info *rulei) { if (rulei->action_created) mlxsw_afa_block_destroy(rulei->act_block); @@ -351,6 +351,12 @@ void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, if (rulei->dst_port_range_reg_valid) mlxsw_sp_port_range_reg_put(mlxsw_sp, rulei->dst_port_range_reg_index); +} + +void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_rule_info *rulei) +{ + mlxsw_sp_acl_rulei_free(mlxsw_sp, rulei); kfree(rulei); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 353fd9ca89a6..5e4632cb792d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -862,14 +862,19 @@ int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp, memset(&rulei, 0, sizeof(rulei)); err = mlxsw_sp_flower_parse(mlxsw_sp, block, &rulei, f); if (err) - return err; + goto out; + ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block, f->common.chain_index, MLXSW_SP_ACL_PROFILE_FLOWER, &rulei.values.elusage); + err = PTR_ERR_OR_ZERO(ruleset); + +out: + mlxsw_sp_acl_rulei_free(mlxsw_sp, &rulei); /* keep the reference to the ruleset */ - return PTR_ERR_OR_ZERO(ruleset); + return err; } void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp, -- cgit v1.2.3 From 71198b59df56a9a0115115091cc1aad2a4e3c74d Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 6 Oct 2026 16:21:29 +0200 Subject: selftests: mlxsw: Test port range occupancy on template create Add a test that creates a tc chain template matching on both source and destination port ranges and verifies via devlink-resource occupancy that this does not leak port range registers, neither while the template exists nor after it is deleted. Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Reviewed-by: Jacob Keller Link: https://patch.msgid.link/e7b37b80adb7ac8b0ef20a22d7654a6656c1c545.1791294384.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- .../selftests/drivers/net/mlxsw/port_range_occ.sh | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh b/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh index b1f0781f6b25..c7eba3f15066 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh @@ -9,6 +9,7 @@ lib_dir=$(dirname $0)/../../../net/forwarding ALL_TESTS=" port_range_occ_test + port_range_occ_tmplt_test " NUM_NETIFS=2 source $lib_dir/lib.sh @@ -101,6 +102,31 @@ port_range_occ_test() log_test "port range occupancy" } +port_range_occ_tmplt_test() +{ + local occ + + RET=0 + occ=$(port_range_occ_get) + + # Addition of a chain template should not impact occupancy. + tc chain add dev "$swp1" ingress chain 1 protocol ip \ + flower ip_proto udp src_port 501-600 dst_port 701-800 + check_err $? "Could not add chain template" + + (( occ == $(port_range_occ_get) )) + check_err $? "Got occupancy $(port_range_occ_get), expected $occ" + + # And just for completeness sake, neither should deletion. + tc chain del dev "$swp1" ingress chain 1 + check_err $? "Could not delete chain template" + + (( occ == $(port_range_occ_get) )) + check_err $? "Got occupancy $(port_range_occ_get), expected $occ" + + log_test "port range occupancy after template create/destroy" +} + trap cleanup EXIT setup_prepare -- cgit v1.2.3