]>
Commit | Line | Data |
---|---|---|
0f831b3c FG |
1 | From 2bb2c56a2089211713a7b1fb379cce741f65ea9e Mon Sep 17 00:00:00 2001 |
2 | From: Eric Dumazet <edumazet@google.com> | |
3 | Date: Fri, 19 May 2017 14:17:48 -0700 | |
4 | Subject: [PATCH] ipv6: fix out of bound writes in __ip6_append_data() | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | Andrey Konovalov and idaifish@gmail.com reported crashes caused by | |
10 | one skb shared_info being overwritten from __ip6_append_data() | |
11 | ||
12 | Andrey program lead to following state : | |
13 | ||
14 | copy -4200 datalen 2000 fraglen 2040 | |
15 | maxfraglen 2040 alloclen 2048 transhdrlen 0 offset 0 fraggap 6200 | |
16 | ||
17 | The skb_copy_and_csum_bits(skb_prev, maxfraglen, data + transhdrlen, | |
18 | fraggap, 0); is overwriting skb->head and skb_shared_info | |
19 | ||
20 | Since we apparently detect this rare condition too late, move the | |
21 | code earlier to even avoid allocating skb and risking crashes. | |
22 | ||
23 | Once again, many thanks to Andrey and syzkaller team. | |
24 | ||
25 | Signed-off-by: Eric Dumazet <edumazet@google.com> | |
26 | Reported-by: Andrey Konovalov <andreyknvl@google.com> | |
27 | Tested-by: Andrey Konovalov <andreyknvl@google.com> | |
28 | Reported-by: <idaifish@gmail.com> | |
29 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
30 | ||
31 | CVE-2017-9242 | |
32 | ||
33 | (cherry-picked from 232cd35d0804cc241eb887bb8d4d9b3b9881c64a) | |
34 | Signed-off-by: Stefan Bader <stefan.bader@canonical.com> | |
35 | Acked-by: Colin King <colin.king@canonical.com> | |
36 | Acked-by: Andy Whitcroft <andy.whitcroft@canonical.com> | |
37 | Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
38 | ||
39 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
40 | --- | |
41 | net/ipv6/ip6_output.c | 15 ++++++++------- | |
42 | 1 file changed, 8 insertions(+), 7 deletions(-) | |
43 | ||
44 | diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c | |
45 | index 8f0814d301aa..135ee573eaef 100644 | |
46 | --- a/net/ipv6/ip6_output.c | |
47 | +++ b/net/ipv6/ip6_output.c | |
48 | @@ -1463,6 +1463,11 @@ static int __ip6_append_data(struct sock *sk, | |
49 | */ | |
50 | alloclen += sizeof(struct frag_hdr); | |
51 | ||
52 | + copy = datalen - transhdrlen - fraggap; | |
53 | + if (copy < 0) { | |
54 | + err = -EINVAL; | |
55 | + goto error; | |
56 | + } | |
57 | if (transhdrlen) { | |
58 | skb = sock_alloc_send_skb(sk, | |
59 | alloclen + hh_len, | |
60 | @@ -1512,13 +1517,9 @@ static int __ip6_append_data(struct sock *sk, | |
61 | data += fraggap; | |
62 | pskb_trim_unique(skb_prev, maxfraglen); | |
63 | } | |
64 | - copy = datalen - transhdrlen - fraggap; | |
65 | - | |
66 | - if (copy < 0) { | |
67 | - err = -EINVAL; | |
68 | - kfree_skb(skb); | |
69 | - goto error; | |
70 | - } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { | |
71 | + if (copy > 0 && | |
72 | + getfrag(from, data + transhdrlen, offset, | |
73 | + copy, fraggap, skb) < 0) { | |
74 | err = -EFAULT; | |
75 | kfree_skb(skb); | |
76 | goto error; | |
77 | -- | |
78 | 2.11.0 | |
79 |