Skip to content

Commit

Permalink
ipv6: fix out of bound writes in __ip6_append_data()
Browse files Browse the repository at this point in the history
commit 232cd35 upstream.

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>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
  • Loading branch information
Eric Dumazet authored and Ben Hutchings committed Jun 5, 2017
1 parent 0767192 commit e5238fc
Showing 1 changed file with 8 additions and 7 deletions.
15 changes: 8 additions & 7 deletions net/ipv6/ip6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,11 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
*/
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,
Expand Down Expand Up @@ -1467,13 +1472,9 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
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;
Expand Down

0 comments on commit e5238fc

Please sign in to comment.