On Sat, Sep 26, 2026 at 8:23 PM Ren Wei <[email protected]> wrote: > > From: Zixuan Chai <[email protected]> > > i40e_atr() uses ipv6_find_hdr() to locate the TCP header. A successful > protocol match does not verify that the complete TCP header is present in > the skb, so dereferencing the result can access data beyond the packet. > > Check that the complete TCP header is available before inspecting it. > > Fixes: fd0a05ce74ef ("i40e: transmit, receive, and NAPI") > Cc: [email protected] > Reported-by: Florian Westphal <[email protected]> > Closes: https://lore.kernel.org/netfilter-devel/[email protected]/ > Assisted-by: LLM > Signed-off-by: Zixuan Chai <[email protected]> > Signed-off-by: Ren Wei <[email protected]> > --- > drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c > b/drivers/net/ethernet/intel/i40e/i40e_txrx.c > index ef5e657816f0..cdac279b8aed 100644 > --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c > +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c > @@ -2911,6 +2911,9 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct > sk_buff *skb, > > if (l4_proto != IPPROTO_TCP) > return; > + if (unlikely(skb_tail_pointer(skb) < hdr.network + hlen + > + sizeof(struct tcphdr))) > + return; > > th = (struct tcphdr *)(hdr.network + hlen); >
pw-bot: cr 1) Please do not add bogus Reported-by: / Closes: tags. Florian never reported an issue in i40e, unless this was not public? 2) How can this code be reached with a truncated or non-linear TCP header? Unlike ixgbe_atr(), i40e_atr() returns immediately unless tx_flags & (I40E_TX_FLAGS_IPV4 | I40E_TX_FLAGS_IPV6) is set. Those flags are only set in i40e_tx_enable_csum(), which only acts on CHECKSUM_PARTIAL packets and runs right before i40e_atr(). Furthermore, i40e_tx_enable_csum() (and i40e_tso()) already assumes the network and transport headers are present in the linear skb head and already dereferences ip.v4->version, ip.v6->nexthdr, and l4.tcp->doff before i40e_atr() is ever called. Even within i40e_atr(), hdr.network is already dereferenced prior to your check in the IPv4 branch.
