Skip to content

Commit 627f9c1

Browse files
idoschkuba-moo
authored andcommitted
mlxsw: spectrum_acl_tcam: Fix race in region ID allocation
Region identifiers can be allocated both when user space tries to insert a new tc filter and when filters are migrated from one region to another as part of the rehash delayed work. There is no lock protecting the bitmap from which these identifiers are allocated from, which is racy and leads to bad parameter errors from the device's firmware. Fix by converting the bitmap to IDA which handles its own locking. For consistency, do the same for the group identifiers that are part of the same structure. Fixes: 2bffc53 ("mlxsw: spectrum_acl: Don't take mutex in mlxsw_sp_acl_tcam_vregion_rehash_work()") Reported-by: Amit Cohen <amcohen@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Tested-by: Alexander Zubkov <green@qrator.net> Reviewed-by: Petr Machata <petrm@nvidia.com> Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://lore.kernel.org/r/ce494b7940cadfe84f3e18da7785b51ef5f776e3.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 5ea7b72 commit 627f9c1

File tree

2 files changed

+30
-36
lines changed

2 files changed

+30
-36
lines changed

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

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/netdevice.h>
1111
#include <linux/mutex.h>
1212
#include <linux/refcount.h>
13+
#include <linux/idr.h>
1314
#include <net/devlink.h>
1415
#include <trace/events/mlxsw.h>
1516

@@ -58,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
5859
static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam,
5960
u16 *p_id)
6061
{
61-
u16 id;
62+
int id;
6263

63-
id = find_first_zero_bit(tcam->used_regions, tcam->max_regions);
64-
if (id < tcam->max_regions) {
65-
__set_bit(id, tcam->used_regions);
66-
*p_id = id;
67-
return 0;
68-
}
69-
return -ENOBUFS;
64+
id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1,
65+
GFP_KERNEL);
66+
if (id < 0)
67+
return id;
68+
69+
*p_id = id;
70+
71+
return 0;
7072
}
7173

7274
static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam,
7375
u16 id)
7476
{
75-
__clear_bit(id, tcam->used_regions);
77+
ida_free(&tcam->used_regions, id);
7678
}
7779

7880
static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam,
7981
u16 *p_id)
8082
{
81-
u16 id;
83+
int id;
8284

83-
id = find_first_zero_bit(tcam->used_groups, tcam->max_groups);
84-
if (id < tcam->max_groups) {
85-
__set_bit(id, tcam->used_groups);
86-
*p_id = id;
87-
return 0;
88-
}
89-
return -ENOBUFS;
85+
id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1,
86+
GFP_KERNEL);
87+
if (id < 0)
88+
return id;
89+
90+
*p_id = id;
91+
92+
return 0;
9093
}
9194

9295
static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam,
9396
u16 id)
9497
{
95-
__clear_bit(id, tcam->used_groups);
98+
ida_free(&tcam->used_groups, id);
9699
}
97100

98101
struct mlxsw_sp_acl_tcam_pattern {
@@ -1549,19 +1552,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
15491552
if (max_tcam_regions < max_regions)
15501553
max_regions = max_tcam_regions;
15511554

1552-
tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL);
1553-
if (!tcam->used_regions) {
1554-
err = -ENOMEM;
1555-
goto err_alloc_used_regions;
1556-
}
1555+
ida_init(&tcam->used_regions);
15571556
tcam->max_regions = max_regions;
15581557

15591558
max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
1560-
tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL);
1561-
if (!tcam->used_groups) {
1562-
err = -ENOMEM;
1563-
goto err_alloc_used_groups;
1564-
}
1559+
ida_init(&tcam->used_groups);
15651560
tcam->max_groups = max_groups;
15661561
tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
15671562
ACL_MAX_GROUP_SIZE);
@@ -1575,10 +1570,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
15751570
return 0;
15761571

15771572
err_tcam_init:
1578-
bitmap_free(tcam->used_groups);
1579-
err_alloc_used_groups:
1580-
bitmap_free(tcam->used_regions);
1581-
err_alloc_used_regions:
1573+
ida_destroy(&tcam->used_groups);
1574+
ida_destroy(&tcam->used_regions);
15821575
mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
15831576
err_rehash_params_register:
15841577
mutex_destroy(&tcam->lock);
@@ -1591,8 +1584,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
15911584
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
15921585

15931586
ops->fini(mlxsw_sp, tcam->priv);
1594-
bitmap_free(tcam->used_groups);
1595-
bitmap_free(tcam->used_regions);
1587+
ida_destroy(&tcam->used_groups);
1588+
ida_destroy(&tcam->used_regions);
15961589
mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
15971590
mutex_destroy(&tcam->lock);
15981591
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66

77
#include <linux/list.h>
88
#include <linux/parman.h>
9+
#include <linux/idr.h>
910

1011
#include "reg.h"
1112
#include "spectrum.h"
1213
#include "core_acl_flex_keys.h"
1314

1415
struct mlxsw_sp_acl_tcam {
15-
unsigned long *used_regions; /* bit array */
16+
struct ida used_regions;
1617
unsigned int max_regions;
17-
unsigned long *used_groups; /* bit array */
18+
struct ida used_groups;
1819
unsigned int max_groups;
1920
unsigned int max_group_size;
2021
struct mutex lock; /* guards vregion list */

0 commit comments

Comments
 (0)