diff mbox

[Z/Y/X/T,SRU] Fix CVE-2017-9242

Message ID 1496832727-15373-1-git-send-email-stefan.bader@canonical.com
State New
Headers show

Commit Message

Stefan Bader June 7, 2017, 10:52 a.m. UTC
Patch applies as cherry-pick to all releases. Build-tested on Trusty
amd64.

-Stefan

---

From 232cd35d0804cc241eb887bb8d4d9b3b9881c64a 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()

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>
---
 net/ipv6/ip6_output.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

Comments

Colin Ian King June 7, 2017, 10:56 a.m. UTC | #1
On 07/06/17 11:52, Stefan Bader wrote:
> Patch applies as cherry-pick to all releases. Build-tested on Trusty
> amd64.
> 
> -Stefan
> 
> ---
> 
> From 232cd35d0804cc241eb887bb8d4d9b3b9881c64a 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()
> 
> 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>
> ---
>  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 d4a31be..bf8a58a 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -1466,6 +1466,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,
> @@ -1515,13 +1520,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;
> 
Clean cherry pick, looks good to me. Thanks Stefan

Acked-by: Colin Ian King <colin.king@canonical.com>
Andy Whitcroft June 7, 2017, 12:03 p.m. UTC | #2
On Wed, Jun 07, 2017 at 12:52:07PM +0200, Stefan Bader wrote:
> Patch applies as cherry-pick to all releases. Build-tested on Trusty
> amd64.
> 
> -Stefan
> 
> ---
> 
> From 232cd35d0804cc241eb887bb8d4d9b3b9881c64a 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()
> 
> 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>
> ---
>  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 d4a31be..bf8a58a 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -1466,6 +1466,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,
> @@ -1515,13 +1520,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;

Looks to do what is claimed.  Clean cherry-pick.

Acked-by: Andy Whitcroft <apw@canonical.com>

-apw
Thadeu Lima de Souza Cascardo June 7, 2017, 2:22 p.m. UTC | #3
Applied to trusty, xenial, yakkety, zesty master-next branches.

Thanks.
Cascardo.
diff mbox

Patch

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index d4a31be..bf8a58a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1466,6 +1466,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,
@@ -1515,13 +1520,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;