]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: http://patchwork.ozlabs.org/patch/18346/ |
2 | Subject: gso: Ensure that the packet is long enough | |
3 | See also http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/d490aa798cc4 | |
4 | ||
5 | When we get a GSO packet from an untrusted source, we need to | |
6 | ensure that it is sufficiently long so that we don't end up | |
7 | crashing. | |
8 | ||
9 | Based on discovery and patch by Ian Campbell. | |
10 | ||
11 | Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> | |
12 | Tested-by: Ian Campbell <ian.campbell@citrix.com> | |
13 | Acked-by: jbeulich@novell.com | |
14 | ||
15 | --- | |
16 | net/ipv4/tcp.c | 13 +++++++------ | |
17 | 1 file changed, 7 insertions(+), 6 deletions(-) | |
18 | ||
19 | --- a/net/ipv4/tcp.c | |
20 | +++ b/net/ipv4/tcp.c | |
21 | @@ -2390,7 +2390,7 @@ struct sk_buff *tcp_tso_segment(struct s | |
22 | unsigned int seq; | |
23 | __be32 delta; | |
24 | unsigned int oldlen; | |
25 | - unsigned int len; | |
26 | + unsigned int mss; | |
27 | ||
28 | if (!pskb_may_pull(skb, sizeof(*th))) | |
29 | goto out; | |
30 | @@ -2406,10 +2406,13 @@ struct sk_buff *tcp_tso_segment(struct s | |
31 | oldlen = (u16)~skb->len; | |
32 | __skb_pull(skb, thlen); | |
33 | ||
34 | + mss = skb_shinfo(skb)->gso_size; | |
35 | + if (unlikely(skb->len <= mss)) | |
36 | + goto out; | |
37 | + | |
38 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { | |
39 | /* Packet is from an untrusted source, reset gso_segs. */ | |
40 | int type = skb_shinfo(skb)->gso_type; | |
41 | - int mss; | |
42 | ||
43 | if (unlikely(type & | |
44 | ~(SKB_GSO_TCPV4 | | |
45 | @@ -2420,7 +2423,6 @@ struct sk_buff *tcp_tso_segment(struct s | |
46 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) | |
47 | goto out; | |
48 | ||
49 | - mss = skb_shinfo(skb)->gso_size; | |
50 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); | |
51 | ||
52 | segs = NULL; | |
53 | @@ -2431,8 +2433,7 @@ struct sk_buff *tcp_tso_segment(struct s | |
54 | if (IS_ERR(segs)) | |
55 | goto out; | |
56 | ||
57 | - len = skb_shinfo(skb)->gso_size; | |
58 | - delta = htonl(oldlen + (thlen + len)); | |
59 | + delta = htonl(oldlen + (thlen + mss)); | |
60 | ||
61 | skb = segs; | |
62 | th = tcp_hdr(skb); | |
63 | @@ -2448,7 +2449,7 @@ struct sk_buff *tcp_tso_segment(struct s | |
64 | csum_fold(csum_partial(skb_transport_header(skb), | |
65 | thlen, skb->csum)); | |
66 | ||
67 | - seq += len; | |
68 | + seq += mss; | |
69 | skb = skb->next; | |
70 | th = tcp_hdr(skb); | |
71 |