[PATCH] net/i40e: fix FDIR flexible payload issues

sandeep.penigalapati at intel.com sandeep.penigalapati at intel.com
Wed Jul 8 02:20:45 CEST 2026


From: Sandeep Penigalapati <sandeep.penigalapati at intel.com>

This fixes two issues in the i40e Flow Director flexible payload path.

The bitmask array bound was checked after the write to
bitmask[nb_bitmask], allowing a one-slot out-of-bounds write when the
number of partial-mask words exceeds I40E_FDIR_BITMASK_NUM_WORD. Move
the check before the write and use '>=' so the array is never indexed
out of bounds.

In addition, i40e_flow_set_fdir_flex_pit() programs the global GLQF_ORT
register, which is shared by all PFs on the NIC. It was called before
the flex mask was validated, so a rule that is later rejected still left
the global register modified, affecting other PFs. Validate the flex
mask first and only touch the hardware registers once it has passed.

Fixes: 6ced3dd72f5f ("net/i40e: support flexible payload parsing for FDIR")
Cc: stable at dpdk.org
Signed-off-by: Sandeep Penigalapati <sandeep.penigalapati at intel.com>
---
 drivers/net/intel/i40e/i40e_fdir.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/net/intel/i40e/i40e_fdir.c b/drivers/net/intel/i40e/i40e_fdir.c
index ad256a5a11..8a233f8a97 100644
--- a/drivers/net/intel/i40e/i40e_fdir.c
+++ b/drivers/net/intel/i40e/i40e_fdir.c
@@ -1230,12 +1230,12 @@ i40e_flow_store_flex_mask(struct i40e_pf *pf,
 			flex_mask.word_mask |=
 				I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
 			if (mask_tmp != UINT16_MAX) {
+				if (nb_bitmask >= I40E_FDIR_BITMASK_NUM_WORD)
+					return -1;
 				flex_mask.bitmask[nb_bitmask].mask = ~mask_tmp;
 				flex_mask.bitmask[nb_bitmask].offset =
 					i / sizeof(uint16_t);
 				nb_bitmask++;
-				if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD)
-					return -1;
 			}
 		}
 	}
@@ -1488,15 +1488,17 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 				}
 			}
 
-			if (cfg_flex_pit)
-				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
-						filter->input.flow_ext.raw_id);
-
 			/* Store flex mask to SW */
 			for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++)
 				flex_mask[i] =
 					filter->input.flow_ext.flex_mask[i];
 
+			/* Validate the flex mask before writing any hardware
+			 * register. i40e_flow_set_fdir_flex_pit() below programs
+			 * the global GLQF_ORT register, which is shared by all
+			 * PFs on the NIC, so it must not be touched for a rule
+			 * that is going to be rejected.
+			 */
 			ret = i40e_flow_store_flex_mask(pf, pctype, flex_mask);
 			if (ret == -1) {
 				PMD_DRV_LOG(ERR, "Exceed maximal"
@@ -1506,9 +1508,14 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 				PMD_DRV_LOG(ERR, "Conflict with the"
 					    " first flexible rule");
 				return -EINVAL;
-			} else if (ret == 0) {
-				i40e_flow_set_fdir_flex_msk(pf, pctype);
 			}
+
+			if (cfg_flex_pit)
+				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
+						filter->input.flow_ext.raw_id);
+
+			if (ret == 0)
+				i40e_flow_set_fdir_flex_msk(pf, pctype);
 		}
 
 		ret = i40e_sw_fdir_filter_insert(pf, &check_filter);
-- 
2.27.0



More information about the stable mailing list