gro: Only verify TCP checksums for candidates
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 22 Nov 2013 02:31:29 +0000 (10:31 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Dec 2013 15:29:14 +0000 (07:29 -0800)
[ Upstream commit cc5c00bbb44c5d68b883aa5cb9d01514a2525d94 ]

In some cases we may receive IP packets that are longer than
their stated lengths.  Such packets are never merged in GRO.
However, we may end up computing their checksums incorrectly
and end up allowing packets with a bogus checksum enter our
stack with the checksum status set as verified.

Since such packets are rare and not performance-critical, this
patch simply skips the checksum verification for them.

Reported-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
Thanks,
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/ipv4/tcp_offload.c
net/ipv6/tcpv6_offload.c

index 533c58a5cfb7a9cf9f4f2b1842533916b20b39da..44c8678fe9bb70c8b3cea2288bdecab6bb13e727 100644 (file)
@@ -274,6 +274,10 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
        __wsum wsum;
        __sum16 sum;
 
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
                if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
@@ -299,6 +303,7 @@ flush:
                break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 2ec6bf6a0aa002d6c21468d090767736161a5d1b..78081d84a652ef67e75a89204e5c6039c95bd10a 100644 (file)
@@ -39,6 +39,10 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
        __wsum wsum;
        __sum16 sum;
 
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
                if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
@@ -65,6 +69,7 @@ flush:
                break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }