Unverified Commit d859edf6 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4690 CVE-2024-26586

Merge Pull Request from: @ci-robot 
 
PR sync from: Liu Jian <liujian56@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/DEYYUQD25E6I7CRVBH3BBYMU66WLJCEQ/ 
backport the fix patches from 5.10lts

Amit Cohen (1):
  mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure

Christophe JAILLET (1):
  mlxsw: spectrum: Use 'bitmap_zalloc()' when applicable

Ido Schimmel (4):
  mlxsw: spectrum_acl_tcam: Add missing mutex_destroy()
  mlxsw: spectrum_acl_tcam: Make fini symmetric to init
  mlxsw: spectrum_acl_tcam: Reorder functions to avoid forward
    declarations
  mlxsw: spectrum_acl_tcam: Fix stack corruption


-- 
2.34.1
 
https://gitee.com/src-openeuler/kernel/issues/I932WD 
 
Link:https://gitee.com/openeuler/kernel/pulls/4690

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 87e496fb af13452d
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -119,7 +119,6 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion)
{
	struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp;
	struct mlxsw_sp_acl_atcam_region_12kb *region_12kb;
	size_t alloc_size;
	u64 max_lkey_id;
	int err;

@@ -131,8 +130,7 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion)
	if (!region_12kb)
		return -ENOMEM;

	alloc_size = BITS_TO_LONGS(max_lkey_id) * sizeof(unsigned long);
	region_12kb->used_lkey_id = kzalloc(alloc_size, GFP_KERNEL);
	region_12kb->used_lkey_id = bitmap_zalloc(max_lkey_id, GFP_KERNEL);
	if (!region_12kb->used_lkey_id) {
		err = -ENOMEM;
		goto err_used_lkey_id_alloc;
@@ -149,7 +147,7 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion)
	return 0;

err_rhashtable_init:
	kfree(region_12kb->used_lkey_id);
	bitmap_free(region_12kb->used_lkey_id);
err_used_lkey_id_alloc:
	kfree(region_12kb);
	return err;
@@ -161,7 +159,7 @@ mlxsw_sp_acl_atcam_region_12kb_fini(struct mlxsw_sp_acl_atcam_region *aregion)
	struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv;

	rhashtable_destroy(&region_12kb->lkey_ht);
	kfree(region_12kb->used_lkey_id);
	bitmap_free(region_12kb->used_lkey_id);
	kfree(region_12kb);
}

+5 −3
Original line number Diff line number Diff line
@@ -301,6 +301,7 @@ mlxsw_sp_acl_erp_table_alloc(struct mlxsw_sp_acl_erp_core *erp_core,
			     unsigned long *p_index)
{
	unsigned int num_rows, entry_size;
	unsigned long index;

	/* We only allow allocations of entire rows */
	if (num_erps % erp_core->num_erp_banks != 0)
@@ -309,10 +310,11 @@ mlxsw_sp_acl_erp_table_alloc(struct mlxsw_sp_acl_erp_core *erp_core,
	entry_size = erp_core->erpt_entries_size[region_type];
	num_rows = num_erps / erp_core->num_erp_banks;

	*p_index = gen_pool_alloc(erp_core->erp_tables, num_rows * entry_size);
	if (*p_index == 0)
	index = gen_pool_alloc(erp_core->erp_tables, num_rows * entry_size);
	if (!index)
		return -ENOBUFS;
	*p_index -= MLXSW_SP_ACL_ERP_GENALLOC_OFFSET;

	*p_index = index - MLXSW_SP_ACL_ERP_GENALLOC_OFFSET;

	return 0;
}
+67 −64
Original line number Diff line number Diff line
@@ -29,70 +29,6 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp)
#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000 /* ms */
#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS 100 /* number of entries */

int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
			   struct mlxsw_sp_acl_tcam *tcam)
{
	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
	u64 max_tcam_regions;
	u64 max_regions;
	u64 max_groups;
	size_t alloc_size;
	int err;

	mutex_init(&tcam->lock);
	tcam->vregion_rehash_intrvl =
			MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT;
	INIT_LIST_HEAD(&tcam->vregion_list);

	max_tcam_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core,
					      ACL_MAX_TCAM_REGIONS);
	max_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_REGIONS);

	/* Use 1:1 mapping between ACL region and TCAM region */
	if (max_tcam_regions < max_regions)
		max_regions = max_tcam_regions;

	alloc_size = sizeof(tcam->used_regions[0]) * BITS_TO_LONGS(max_regions);
	tcam->used_regions = kzalloc(alloc_size, GFP_KERNEL);
	if (!tcam->used_regions)
		return -ENOMEM;
	tcam->max_regions = max_regions;

	max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
	alloc_size = sizeof(tcam->used_groups[0]) * BITS_TO_LONGS(max_groups);
	tcam->used_groups = kzalloc(alloc_size, GFP_KERNEL);
	if (!tcam->used_groups) {
		err = -ENOMEM;
		goto err_alloc_used_groups;
	}
	tcam->max_groups = max_groups;
	tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
						 ACL_MAX_GROUP_SIZE);

	err = ops->init(mlxsw_sp, tcam->priv, tcam);
	if (err)
		goto err_tcam_init;

	return 0;

err_tcam_init:
	kfree(tcam->used_groups);
err_alloc_used_groups:
	kfree(tcam->used_regions);
	return err;
}

void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
			    struct mlxsw_sp_acl_tcam *tcam)
{
	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;

	mutex_destroy(&tcam->lock);
	ops->fini(mlxsw_sp, tcam->priv);
	kfree(tcam->used_groups);
	kfree(tcam->used_regions);
}

int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
				   struct mlxsw_sp_acl_rule_info *rulei,
				   u32 *priority, bool fillup_priority)
@@ -1545,6 +1481,73 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
		mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx);
}

int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
			   struct mlxsw_sp_acl_tcam *tcam)
{
	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
	u64 max_tcam_regions;
	u64 max_regions;
	u64 max_groups;
	int err;

	mutex_init(&tcam->lock);
	tcam->vregion_rehash_intrvl =
			MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT;
	INIT_LIST_HEAD(&tcam->vregion_list);

	max_tcam_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core,
					      ACL_MAX_TCAM_REGIONS);
	max_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_REGIONS);

	/* Use 1:1 mapping between ACL region and TCAM region */
	if (max_tcam_regions < max_regions)
		max_regions = max_tcam_regions;

	tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL);
	if (!tcam->used_regions) {
		err = -ENOMEM;
		goto err_alloc_used_regions;
	}
	tcam->max_regions = max_regions;

	max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
	tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL);
	if (!tcam->used_groups) {
		err = -ENOMEM;
		goto err_alloc_used_groups;
	}
	tcam->max_groups = max_groups;
	tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
						  ACL_MAX_GROUP_SIZE);
	tcam->max_group_size = min_t(unsigned int, tcam->max_group_size,
				     MLXSW_REG_PAGT_ACL_MAX_NUM);

	err = ops->init(mlxsw_sp, tcam->priv, tcam);
	if (err)
		goto err_tcam_init;

	return 0;

err_tcam_init:
	bitmap_free(tcam->used_groups);
err_alloc_used_groups:
	bitmap_free(tcam->used_regions);
err_alloc_used_regions:
	mutex_destroy(&tcam->lock);
	return err;
}

void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
			    struct mlxsw_sp_acl_tcam *tcam)
{
	const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;

	ops->fini(mlxsw_sp, tcam->priv);
	bitmap_free(tcam->used_groups);
	bitmap_free(tcam->used_regions);
	mutex_destroy(&tcam->lock);
}

static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = {
	MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
	MLXSW_AFK_ELEMENT_DMAC_32_47,
+3 −6
Original line number Diff line number Diff line
@@ -122,7 +122,6 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)
	unsigned int sub_pools_count = ARRAY_SIZE(mlxsw_sp_counter_sub_pools);
	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
	struct mlxsw_sp_counter_pool *pool;
	unsigned int map_size;
	int err;

	pool = kzalloc(struct_size(pool, sub_pools, sub_pools_count),
@@ -143,9 +142,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)
	devlink_resource_occ_get_register(devlink, MLXSW_SP_RESOURCE_COUNTERS,
					  mlxsw_sp_counter_pool_occ_get, pool);

	map_size = BITS_TO_LONGS(pool->pool_size) * sizeof(unsigned long);

	pool->usage = kzalloc(map_size, GFP_KERNEL);
	pool->usage = bitmap_zalloc(pool->pool_size, GFP_KERNEL);
	if (!pool->usage) {
		err = -ENOMEM;
		goto err_usage_alloc;
@@ -158,7 +155,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)
	return 0;

err_sub_pools_init:
	kfree(pool->usage);
	bitmap_free(pool->usage);
err_usage_alloc:
	devlink_resource_occ_get_unregister(devlink,
					    MLXSW_SP_RESOURCE_COUNTERS);
@@ -176,7 +173,7 @@ void mlxsw_sp_counter_pool_fini(struct mlxsw_sp *mlxsw_sp)
	WARN_ON(find_first_bit(pool->usage, pool->pool_size) !=
			       pool->pool_size);
	WARN_ON(atomic_read(&pool->active_entries_count));
	kfree(pool->usage);
	bitmap_free(pool->usage);
	devlink_resource_occ_get_unregister(devlink,
					    MLXSW_SP_RESOURCE_COUNTERS);
	kfree(pool);
+4 −7
Original line number Diff line number Diff line
@@ -1631,16 +1631,13 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
				  u16 fid)
{
	struct mlxsw_sp_mid *mid;
	size_t alloc_size;

	mid = kzalloc(sizeof(*mid), GFP_KERNEL);
	if (!mid)
		return NULL;

	alloc_size = sizeof(unsigned long) *
		     BITS_TO_LONGS(mlxsw_core_max_ports(mlxsw_sp->core));

	mid->ports_in_mid = kzalloc(alloc_size, GFP_KERNEL);
	mid->ports_in_mid = bitmap_zalloc(mlxsw_core_max_ports(mlxsw_sp->core),
					  GFP_KERNEL);
	if (!mid->ports_in_mid)
		goto err_ports_in_mid_alloc;

@@ -1659,7 +1656,7 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
	return mid;

err_write_mdb_entry:
	kfree(mid->ports_in_mid);
	bitmap_free(mid->ports_in_mid);
err_ports_in_mid_alloc:
	kfree(mid);
	return NULL;
@@ -1676,7 +1673,7 @@ static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
			 mlxsw_core_max_ports(mlxsw_sp->core))) {
		err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
		list_del(&mid->list);
		kfree(mid->ports_in_mid);
		bitmap_free(mid->ports_in_mid);
		kfree(mid);
	}
	return err;
Loading