Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2674

kernel-2.6.18-238.el5.src.rpm

From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 22 Jan 2009 13:10:11 +0100
Subject: [net] gso: ensure that the packet is long enough
Message-id: 20090122121010.GE3421@psychotron.englab.brq.redhat.com
O-Subject: [RHEL5.4 patch] BZ479927 gso: Ensure that the packet is long enough
Bugzilla: 479927
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: Anton Arapov <aarapov@redhat.com>
RH-Acked-by: Tomas Henzl <thenzl@redhat.com>
RH-Acked-by: Herbert Xu <herbert.xu@redhat.com>

BZ479927
https://bugzilla.redhat.com/show_bug.cgi?id=479927

Description:
When we get a GSO packet from an untrusted source, we need to
ensure that it is sufficiently long so that we don't end up
crashing.

Upstream:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=4e704ee3c2cd38748ca59d835435d6a7e7f6f613

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=1655886

Test:
Booted on x84_64

Jirka

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 401983b..deff959 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2166,7 +2166,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 	unsigned int seq;
 	unsigned int delta;
 	unsigned int oldlen;
-	unsigned int len;
+	unsigned int mss;
 
 	if (!pskb_may_pull(skb, sizeof(*th)))
 		goto out;
@@ -2182,10 +2182,13 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 	oldlen = (u16)~skb->len;
 	__skb_pull(skb, thlen);
 
+	mss = skb_shinfo(skb)->gso_size;
+	if (unlikely(skb->len <= mss))
+		goto out;
+
 	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
 		int type = skb_shinfo(skb)->gso_type;
-		int mss;
 
 		if (unlikely(type &
 			     ~(SKB_GSO_TCPV4 |
@@ -2196,7 +2199,6 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 			     !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
 			goto out;
 
-		mss = skb_shinfo(skb)->gso_size;
 		skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
 
 		segs = NULL;
@@ -2207,8 +2209,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 	if (IS_ERR(segs))
 		goto out;
 
-	len = skb_shinfo(skb)->gso_size;
-	delta = htonl(oldlen + (thlen + len));
+	delta = htonl(oldlen + (thlen + mss));
 
 	skb = segs;
 	th = skb->h.th;
@@ -2222,7 +2223,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 			th->check = csum_fold(csum_partial(skb->h.raw, thlen,
 							   skb->csum));
 
-		seq += len;
+		seq += mss;
 		skb = skb->next;
 		th = skb->h.th;