For some Tx paths (e.g., tpacket_snd()), ixgbe_atr may be
passed down an sk_buff that has the network and transport
header in the paged data, so it needs to make sure these
headers are available in the headlen bytes to calculate the
l4_proto.

This patch bails out if the headlen is "too short", and does
not attempt to call skb_header_pointer() to get the needed
bytes: the assumption is that the caller should set things
up properly if the l4_proto based tx steering is desired.

Signed-off-by: Sowmini Varadhan <sowmini.varad...@oracle.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index a244d9a..0868de1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7632,6 +7632,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
        struct sk_buff *skb;
        __be16 vlan_id;
        int l4_proto;
+       int min_hdr_size = 0;
 
        /* if ring doesn't have a interrupt vector, cannot perform ATR */
        if (!q_vector)
@@ -7650,6 +7651,14 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
 
        /* snag network header to get L4 type and address */
        skb = first->skb;
+       if (first->protocol == htons(ETH_P_IP))
+               min_hdr_size = sizeof(struct iphdr) +
+                              sizeof(struct tcphdr);
+       else if (first->protocol == htons(ETH_P_IPV6))
+               min_hdr_size = sizeof(struct ipv6hdr) +
+                              sizeof(struct tcphdr);
+       if (min_hdr_size && skb_headlen(skb) < ETH_HLEN + min_hdr_size)
+               return;
        hdr.network = skb_network_header(skb);
        if (skb->encapsulation &&
            first->protocol == htons(ETH_P_IP) &&
-- 
1.7.1

Reply via email to