80 lines
2.6 KiB
Diff
80 lines
2.6 KiB
Diff
|
From 2bb2c56a2089211713a7b1fb379cce741f65ea9e Mon Sep 17 00:00:00 2001
|
||
|
From: Eric Dumazet <edumazet@google.com>
|
||
|
Date: Fri, 19 May 2017 14:17:48 -0700
|
||
|
Subject: [PATCH] ipv6: fix out of bound writes in __ip6_append_data()
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Andrey Konovalov and idaifish@gmail.com reported crashes caused by
|
||
|
one skb shared_info being overwritten from __ip6_append_data()
|
||
|
|
||
|
Andrey program lead to following state :
|
||
|
|
||
|
copy -4200 datalen 2000 fraglen 2040
|
||
|
maxfraglen 2040 alloclen 2048 transhdrlen 0 offset 0 fraggap 6200
|
||
|
|
||
|
The skb_copy_and_csum_bits(skb_prev, maxfraglen, data + transhdrlen,
|
||
|
fraggap, 0); is overwriting skb->head and skb_shared_info
|
||
|
|
||
|
Since we apparently detect this rare condition too late, move the
|
||
|
code earlier to even avoid allocating skb and risking crashes.
|
||
|
|
||
|
Once again, many thanks to Andrey and syzkaller team.
|
||
|
|
||
|
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||
|
Reported-by: Andrey Konovalov <andreyknvl@google.com>
|
||
|
Tested-by: Andrey Konovalov <andreyknvl@google.com>
|
||
|
Reported-by: <idaifish@gmail.com>
|
||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||
|
|
||
|
CVE-2017-9242
|
||
|
|
||
|
(cherry-picked from 232cd35d0804cc241eb887bb8d4d9b3b9881c64a)
|
||
|
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
|
||
|
Acked-by: Colin King <colin.king@canonical.com>
|
||
|
Acked-by: Andy Whitcroft <andy.whitcroft@canonical.com>
|
||
|
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
|
||
|
|
||
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
||
|
---
|
||
|
net/ipv6/ip6_output.c | 15 ++++++++-------
|
||
|
1 file changed, 8 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
||
|
index 8f0814d301aa..135ee573eaef 100644
|
||
|
--- a/net/ipv6/ip6_output.c
|
||
|
+++ b/net/ipv6/ip6_output.c
|
||
|
@@ -1463,6 +1463,11 @@ static int __ip6_append_data(struct sock *sk,
|
||
|
*/
|
||
|
alloclen += sizeof(struct frag_hdr);
|
||
|
|
||
|
+ copy = datalen - transhdrlen - fraggap;
|
||
|
+ if (copy < 0) {
|
||
|
+ err = -EINVAL;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
if (transhdrlen) {
|
||
|
skb = sock_alloc_send_skb(sk,
|
||
|
alloclen + hh_len,
|
||
|
@@ -1512,13 +1517,9 @@ static int __ip6_append_data(struct sock *sk,
|
||
|
data += fraggap;
|
||
|
pskb_trim_unique(skb_prev, maxfraglen);
|
||
|
}
|
||
|
- copy = datalen - transhdrlen - fraggap;
|
||
|
-
|
||
|
- if (copy < 0) {
|
||
|
- err = -EINVAL;
|
||
|
- kfree_skb(skb);
|
||
|
- goto error;
|
||
|
- } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
|
||
|
+ if (copy > 0 &&
|
||
|
+ getfrag(from, data + transhdrlen, offset,
|
||
|
+ copy, fraggap, skb) < 0) {
|
||
|
err = -EFAULT;
|
||
|
kfree_skb(skb);
|
||
|
goto error;
|
||
|
--
|
||
|
2.11.0
|
||
|
|