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;