[PATCH] [v2] net/mlx5e: fix a double-free in arfs_create_groups

From: Zhipeng Lu
Date: Mon Jan 08 2024 - 10:29:40 EST


When `in` allocated by kvzalloc fails, arfs_create_groups will free
ft->g and return an error. However, arfs_create_table, the only caller of
arfs_create_groups, will hold this error and call to
mlx5e_destroy_flow_table, in which the ft->g will be freed again.

Fixes: 1cabe6b0965e ("net/mlx5e: Create aRFS flow tables")
Signed-off-by: Zhipeng Lu <alexious@xxxxxxxxxx>
Reviewed-by: Simon Horman <horms@xxxxxxxxxx>
---
Changelog:

v2: free ft->g just in arfs_create_groups with a unwind ladde.
---
.../net/ethernet/mellanox/mlx5/core/en_arfs.c | 17 +++++++++--------
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c | 1 -
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index bb7f86c993e5..c96f4c571b63 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -252,13 +252,14 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
int err;
u8 *mc;

+ ft->num_groups = 0;
+
ft->g = kcalloc(MLX5E_ARFS_NUM_GROUPS,
sizeof(*ft->g), GFP_KERNEL);
in = kvzalloc(inlen, GFP_KERNEL);
if (!in || !ft->g) {
- kfree(ft->g);
- kvfree(in);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto free_ft;
}

mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
@@ -278,7 +279,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
break;
default:
err = -EINVAL;
- goto out;
+ goto free_ft;
}

switch (type) {
@@ -300,7 +301,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
break;
default:
err = -EINVAL;
- goto out;
+ goto free_ft;
}

MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
@@ -327,7 +328,9 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft,
err:
err = PTR_ERR(ft->g[ft->num_groups]);
ft->g[ft->num_groups] = NULL;
-out:
+free_ft:
+ kfree(ft->g);
+ ft->g = NULL;
kvfree(in);

return err;
@@ -343,8 +346,6 @@ static int arfs_create_table(struct mlx5e_flow_steering *fs,
struct mlx5_flow_table_attr ft_attr = {};
int err;

- ft->num_groups = 0;
-
ft_attr.max_fte = MLX5E_ARFS_TABLE_SIZE;
ft_attr.level = MLX5E_ARFS_FT_LEVEL;
ft_attr.prio = MLX5E_NIC_PRIO;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index 777d311d44ef..7b6aa0c8b58d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -883,7 +883,6 @@ void mlx5e_fs_init_l2_addr(struct mlx5e_flow_steering *fs, struct net_device *ne
void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft)
{
mlx5e_destroy_groups(ft);
- kfree(ft->g);
mlx5_destroy_flow_table(ft->t);
ft->t = NULL;
}
--
2.34.1