瀏覽代碼

gro: Only verify TCP checksums for candidates

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>
Herbert Xu 11 年之前
父節點
當前提交
cc5c00bbb4
共有 2 個文件被更改,包括 10 次插入0 次删除
  1. 5 0
      net/ipv4/tcp_offload.c
  2. 5 0
      net/ipv6/tcpv6_offload.c

+ 5 - 0
net/ipv4/tcp_offload.c

@@ -276,6 +276,10 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
 	__wsum wsum;
 	__wsum wsum;
 	__sum16 sum;
 	__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) {
 	switch (skb->ip_summed) {
 	case CHECKSUM_COMPLETE:
 	case CHECKSUM_COMPLETE:
 		if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
 		if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
@@ -301,6 +305,7 @@ flush:
 		break;
 		break;
 	}
 	}
 
 
+skip_csum:
 	return tcp_gro_receive(head, skb);
 	return tcp_gro_receive(head, skb);
 }
 }
 
 

+ 5 - 0
net/ipv6/tcpv6_offload.c

@@ -39,6 +39,10 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
 	__wsum wsum;
 	__wsum wsum;
 	__sum16 sum;
 	__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) {
 	switch (skb->ip_summed) {
 	case CHECKSUM_COMPLETE:
 	case CHECKSUM_COMPLETE:
 		if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
 		if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
@@ -65,6 +69,7 @@ flush:
 		break;
 		break;
 	}
 	}
 
 
+skip_csum:
 	return tcp_gro_receive(head, skb);
 	return tcp_gro_receive(head, skb);
 }
 }