Skip to content

Commit f0cd446

Browse files
sodarraslandarawsheh
authored andcommitted
net/mlx5: fix VLAN handling in meter split
On the attempt to create a flow rule with: - matching on REPRESENTED_PORT, - matching on outer VLAN tag, - matching on inner VLAN tag, - METER action, flow splitting mechanism for handling metering flows was causing memory corruption. It was assumed that suffix flow will have a single VLAN item (used for translation of OF_PUSH_VLAN/OF_SET_VLAN_VID actions), however during flow_meter_split_prep() 2 VLAN items were parsed. This caused the buffer overflow on allocated suffix flow item buffer. This patch fixes this overflow, by account for number of VLAN items in flow rule pattern when allocating items for suffix flow. Fixes: 50f576d ("net/mlx5: fix VLAN actions in meter") Cc: [email protected] Cc: [email protected] Signed-off-by: Dariusz Sosnowski <[email protected]> Acked-by: Suanming Mou <[email protected]>
1 parent c4a2f77 commit f0cd446

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

drivers/net/mlx5/mlx5_flow.c

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5707,8 +5707,8 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
57075707
struct mlx5_rte_flow_item_tag *tag_item_spec;
57085708
struct mlx5_rte_flow_item_tag *tag_item_mask;
57095709
uint32_t tag_id = 0;
5710-
struct rte_flow_item *vlan_item_dst = NULL;
5711-
const struct rte_flow_item *vlan_item_src = NULL;
5710+
bool vlan_actions;
5711+
struct rte_flow_item *orig_sfx_items = sfx_items;
57125712
const struct rte_flow_item *orig_items = items;
57135713
struct rte_flow_action *hw_mtr_action;
57145714
struct rte_flow_action *action_pre_head = NULL;
@@ -5725,6 +5725,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
57255725

57265726
/* Prepare the suffix subflow items. */
57275727
tag_item = sfx_items++;
5728+
tag_item->type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG;
57285729
for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
57295730
int item_type = items->type;
57305731

@@ -5747,10 +5748,13 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
57475748
sfx_items++;
57485749
break;
57495750
case RTE_FLOW_ITEM_TYPE_VLAN:
5750-
/* Determine if copy vlan item below. */
5751-
vlan_item_src = items;
5752-
vlan_item_dst = sfx_items++;
5753-
vlan_item_dst->type = RTE_FLOW_ITEM_TYPE_VOID;
5751+
/*
5752+
* Copy VLAN items in case VLAN actions are performed.
5753+
* If there are no VLAN actions, these items will be VOID.
5754+
*/
5755+
memcpy(sfx_items, items, sizeof(*sfx_items));
5756+
sfx_items->type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_VLAN;
5757+
sfx_items++;
57545758
break;
57555759
default:
57565760
break;
@@ -5767,6 +5771,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
57675771
tag_action = actions_pre++;
57685772
}
57695773
/* Prepare the actions for prefix and suffix flow. */
5774+
vlan_actions = false;
57705775
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
57715776
struct rte_flow_action *action_cur = NULL;
57725777

@@ -5797,16 +5802,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
57975802
break;
57985803
case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
57995804
case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
5800-
if (vlan_item_dst && vlan_item_src) {
5801-
memcpy(vlan_item_dst, vlan_item_src,
5802-
sizeof(*vlan_item_dst));
5803-
/*
5804-
* Convert to internal match item, it is used
5805-
* for vlan push and set vid.
5806-
*/
5807-
vlan_item_dst->type = (enum rte_flow_item_type)
5808-
MLX5_RTE_FLOW_ITEM_TYPE_VLAN;
5809-
}
5805+
vlan_actions = true;
58105806
break;
58115807
case RTE_FLOW_ACTION_TYPE_COUNT:
58125808
if (fm->def_policy)
@@ -5821,6 +5817,14 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
58215817
actions_sfx++ : actions_pre++;
58225818
memcpy(action_cur, actions, sizeof(struct rte_flow_action));
58235819
}
5820+
/* If there are no VLAN actions, convert VLAN items to VOID in suffix flow items. */
5821+
if (!vlan_actions) {
5822+
struct rte_flow_item *it = orig_sfx_items;
5823+
5824+
for (; it->type != RTE_FLOW_ITEM_TYPE_END; it++)
5825+
if (it->type == (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
5826+
it->type = RTE_FLOW_ITEM_TYPE_VOID;
5827+
}
58245828
/* Add end action to the actions. */
58255829
actions_sfx->type = RTE_FLOW_ACTION_TYPE_END;
58265830
if (priv->sh->meter_aso_en) {
@@ -5910,8 +5914,6 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
59105914
tag_action->type = (enum rte_flow_action_type)
59115915
MLX5_RTE_FLOW_ACTION_TYPE_TAG;
59125916
tag_action->conf = set_tag;
5913-
tag_item->type = (enum rte_flow_item_type)
5914-
MLX5_RTE_FLOW_ITEM_TYPE_TAG;
59155917
tag_item->spec = tag_item_spec;
59165918
tag_item->last = NULL;
59175919
tag_item->mask = tag_item_mask;
@@ -6739,6 +6741,19 @@ flow_meter_create_drop_flow_with_org_pattern(struct rte_eth_dev *dev,
67396741
&drop_split_info, error);
67406742
}
67416743

6744+
static int
6745+
flow_count_vlan_items(const struct rte_flow_item items[])
6746+
{
6747+
int items_n = 0;
6748+
6749+
for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
6750+
if (items->type == RTE_FLOW_ITEM_TYPE_VLAN ||
6751+
items->type == (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
6752+
items_n++;
6753+
}
6754+
return items_n;
6755+
}
6756+
67426757
/**
67436758
* The splitting for meter feature.
67446759
*
@@ -6794,6 +6809,7 @@ flow_create_split_meter(struct rte_eth_dev *dev,
67946809
size_t act_size;
67956810
size_t item_size;
67966811
int actions_n = 0;
6812+
int vlan_items_n = 0;
67976813
int ret = 0;
67986814

67996815
if (priv->mtr_en)
@@ -6853,9 +6869,11 @@ flow_create_split_meter(struct rte_eth_dev *dev,
68536869
act_size = (sizeof(struct rte_flow_action) *
68546870
(actions_n + METER_PREFIX_ACTION)) +
68556871
sizeof(struct mlx5_rte_flow_action_set_tag);
6856-
/* Suffix items: tag, vlan, port id, end. */
6857-
#define METER_SUFFIX_ITEM 4
6858-
item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM +
6872+
/* Flow can have multiple VLAN items. Account for them in suffix items. */
6873+
vlan_items_n = flow_count_vlan_items(items);
6874+
/* Suffix items: tag, [vlans], port id, end. */
6875+
#define METER_SUFFIX_ITEM 3
6876+
item_size = sizeof(struct rte_flow_item) * (METER_SUFFIX_ITEM + vlan_items_n) +
68596877
sizeof(struct mlx5_rte_flow_item_tag) * 2;
68606878
sfx_actions = mlx5_malloc(MLX5_MEM_ZERO, (act_size + item_size),
68616879
0, SOCKET_ID_ANY);

0 commit comments

Comments
 (0)