[PATCH iwl-net v2 6/6] ixgbe: fix integer overflow and wrong bit position in ixgbe_validate_rtr()

Aleksandr Loktionov
2026-04-08T13:12:06Z

Two bugs in the same loop in ixgbe_validate_rtr():

1. The 3-bit traffic-class field was extracted by shifting a u32 and
assigning the result directly to a u8. For user priority 0 this is
harmless; for UP[5..7] the shift leaves bits [15..21] in the u32
which are then silently truncated when stored in u8. Mask with
IXGBE_RTRUP2TC_UP_MASK before the assignment so only the intended
3 bits are kept.

2. When clearing an out-of-bounds entry the mask was always shifted by
the fixed constant IXGBE_RTRUP2TC_UP_SHIFT (== 3), regardless of
which loop iteration was being processed. This means only UP1 (bit
position 3) was ever cleared; UP0,2..7 (positions 0, 6, 9, ..., 21)
were left unreset, so invalid TC mappings persisted in hardware and
could mis-steer received packets to the wrong traffic class.
Use i * IXGBE_RTRUP2TC_UP_SHIFT to target the correct 3-bit field
for each iteration.

Swap the operand order in the mask expression to place the constant
on the right per kernel coding style (noted by David Laight).

Fixes: e7589eab9291 ("ixgbe: consolidate, setup for multiple traffic classes")
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
v1 -> v2:
- Add Fixes: tag; reroute to iwl-net (wrong bit positions cause packet
mis-steering); swap to (reg >> ...) & MASK operand order per David
Laight.

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 210c7b9..c9e4f12 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9772,11 +9772,12 @@ static void ixgbe_validate_rtr(struct ixgbe_adapter *adapter, u8 tc)
rsave = reg;

for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
- u8 up2tc = reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT);
+ u8 up2tc = (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)) &
+ IXGBE_RTRUP2TC_UP_MASK;

/* If up2tc is out of bounds default to zero */
if (up2tc > tc)
- reg &= ~(0x7 << IXGBE_RTRUP2TC_UP_SHIFT);
+ reg &= ~(IXGBE_RTRUP2TC_UP_MASK << (i * IXGBE_RTRUP2TC_UP_SHIFT));
}

if (reg != rsave)
--
2.52.0