[linux] 01/02: Add various security fixes

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Thu Jun 1 13:15:13 UTC 2017


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch sid
in repository linux.

commit ad62774819fc4b74554e6a407fea89c42301a201
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Thu Jun 1 00:30:04 2017 +0100

    Add various security fixes
---
 debian/changelog                                   |  11 +
 ...to-skcipher-add-missing-api-setkey-checks.patch |  73 +++++++
 ...cp-tcp-do-not-inherit-mc_list-from-parent.patch |  37 ++++
 ...p-do-not-inherit-ipv6_mc_list-from-parent.patch |  59 ++++++
 ...-out-of-bound-writes-in-__ip6_append_data.patch |  62 ++++++
 ...nt-overrun-when-parsing-v6-header-options.patch | 221 +++++++++++++++++++++
 .../all/nfsv4-fix-callback-server-shutdown.patch   | 147 ++++++++++++++
 ...-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch |  29 +++
 .../all/sunrpc-refactor-svc_set_num_threads.patch  | 154 ++++++++++++++
 ...-strlcpy-instead-of-strcpy-in-__trace_fin.patch |  34 ++++
 debian/patches/series                              |   9 +
 11 files changed, 836 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index ebc5af8..711829d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -408,6 +408,17 @@ linux (4.9.30-1) UNRELEASED; urgency=medium
   * Ignore ABI changes in ccp and hid-sensors
   * [mips*el/loongson-3] Revert "MIPS: Loongson-3: Select
     MIPS_L1_CACHE_SHIFT_6" to avoid ABI change
+  * tracing: Use strlcpy() instead of strcpy() in __trace_find_cmdline()
+    (CVE-2017-0605)
+  * dccp/tcp: do not inherit mc_list from parent (CVE-2017-8890)
+  * SUNRPC: Refactor svc_set_num_threads()
+  * NFSv4: Fix callback server shutdown (CVE-2017-9059)
+  * ipv6: Prevent overrun when parsing v6 header options (CVE-2017-9074)
+  * sctp: do not inherit ipv6_{mc|ac|fl}_list from parent (CVE-2017-9075)
+  * ipv6/dccp: do not inherit ipv6_mc_list from parent (CVE-2017-9076,
+    CVE-2017-9077)
+  * crypto: skcipher - Add missing API setkey checks (CVE-2017-9211)
+  * ipv6: fix out of bound writes in __ip6_append_data() (CVE-2017-9242)
 
  -- Ben Hutchings <ben at decadent.org.uk>  Mon, 08 May 2017 21:11:08 +0200
 
diff --git a/debian/patches/bugfix/all/crypto-skcipher-add-missing-api-setkey-checks.patch b/debian/patches/bugfix/all/crypto-skcipher-add-missing-api-setkey-checks.patch
new file mode 100644
index 0000000..4d49388
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-skcipher-add-missing-api-setkey-checks.patch
@@ -0,0 +1,73 @@
+From: Herbert Xu <herbert at gondor.apana.org.au>
+Date: Wed, 10 May 2017 03:48:23 +0800
+Subject: crypto: skcipher - Add missing API setkey checks
+Origin: https://git.kernel.org/linus/9933e113c2e87a9f46a40fde8dafbf801dca1ab9
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9211
+
+The API setkey checks for key sizes and alignment went AWOL during the
+skcipher conversion.  This patch restores them.
+
+Cc: <stable at vger.kernel.org>
+Fixes: 4e6c3df4d729 ("crypto: skcipher - Add low-level skcipher...")
+Reported-by: Baozeng <sploving1 at gmail.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/skcipher.c | 40 +++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 39 insertions(+), 1 deletion(-)
+
+--- a/crypto/skcipher.c
++++ b/crypto/skcipher.c
+@@ -221,6 +221,44 @@ static int crypto_init_skcipher_ops_ablk
+ 	return 0;
+ }
+ 
++static int skcipher_setkey_unaligned(struct crypto_skcipher *tfm,
++				     const u8 *key, unsigned int keylen)
++{
++	unsigned long alignmask = crypto_skcipher_alignmask(tfm);
++	struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
++	u8 *buffer, *alignbuffer;
++	unsigned long absize;
++	int ret;
++
++	absize = keylen + alignmask;
++	buffer = kmalloc(absize, GFP_ATOMIC);
++	if (!buffer)
++		return -ENOMEM;
++
++	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
++	memcpy(alignbuffer, key, keylen);
++	ret = cipher->setkey(tfm, alignbuffer, keylen);
++	kzfree(buffer);
++	return ret;
++}
++
++static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
++			   unsigned int keylen)
++{
++	struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
++	unsigned long alignmask = crypto_skcipher_alignmask(tfm);
++
++	if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
++		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
++		return -EINVAL;
++	}
++
++	if ((unsigned long)key & alignmask)
++		return skcipher_setkey_unaligned(tfm, key, keylen);
++
++	return cipher->setkey(tfm, key, keylen);
++}
++
+ static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm)
+ {
+ 	struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
+@@ -241,7 +279,7 @@ static int crypto_skcipher_init_tfm(stru
+ 	    tfm->__crt_alg->cra_type == &crypto_givcipher_type)
+ 		return crypto_init_skcipher_ops_ablkcipher(tfm);
+ 
+-	skcipher->setkey = alg->setkey;
++	skcipher->setkey = skcipher_setkey;
+ 	skcipher->encrypt = alg->encrypt;
+ 	skcipher->decrypt = alg->decrypt;
+ 	skcipher->ivsize = alg->ivsize;
diff --git a/debian/patches/bugfix/all/dccp-tcp-do-not-inherit-mc_list-from-parent.patch b/debian/patches/bugfix/all/dccp-tcp-do-not-inherit-mc_list-from-parent.patch
new file mode 100644
index 0000000..4811659
--- /dev/null
+++ b/debian/patches/bugfix/all/dccp-tcp-do-not-inherit-mc_list-from-parent.patch
@@ -0,0 +1,37 @@
+From: Eric Dumazet <edumazet at google.com>
+Date: Tue, 9 May 2017 06:29:19 -0700
+Subject: dccp/tcp: do not inherit mc_list from parent
+Origin: https://git.kernel.org/linus/657831ffc38e30092a2d5f03d385d710eb88b09a
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-8890
+
+syzkaller found a way to trigger double frees from ip_mc_drop_socket()
+
+It turns out that leave a copy of parent mc_list at accept() time,
+which is very bad.
+
+Very similar to commit 8b485ce69876 ("tcp: do not inherit
+fastopen_req from parent")
+
+Initial report from Pray3r, completed by Andrey one.
+Thanks a lot to them !
+
+Signed-off-by: Eric Dumazet <edumazet at google.com>
+Reported-by: Pray3r <pray3r.z at gmail.com>
+Reported-by: Andrey Konovalov <andreyknvl at google.com>
+Tested-by: Andrey Konovalov <andreyknvl at google.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/ipv4/inet_connection_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -665,6 +665,8 @@ struct sock *inet_csk_clone_lock(const s
+ 		/* listeners have SOCK_RCU_FREE, not the children */
+ 		sock_reset_flag(newsk, SOCK_RCU_FREE);
+ 
++		inet_sk(newsk)->mc_list = NULL;
++
+ 		newsk->sk_mark = inet_rsk(req)->ir_mark;
+ 		atomic64_set(&newsk->sk_cookie,
+ 			     atomic64_read(&inet_rsk(req)->ir_cookie));
diff --git a/debian/patches/bugfix/all/ipv6-dccp-do-not-inherit-ipv6_mc_list-from-parent.patch b/debian/patches/bugfix/all/ipv6-dccp-do-not-inherit-ipv6_mc_list-from-parent.patch
new file mode 100644
index 0000000..0c923db
--- /dev/null
+++ b/debian/patches/bugfix/all/ipv6-dccp-do-not-inherit-ipv6_mc_list-from-parent.patch
@@ -0,0 +1,59 @@
+From: WANG Cong <xiyou.wangcong at gmail.com>
+Date: Tue, 9 May 2017 16:59:54 -0700
+Subject: ipv6/dccp: do not inherit ipv6_mc_list from parent
+Origin: https://git.kernel.org/linus/83eaddab4378db256d00d295bda6ca997cd13a52
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9076
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9077
+
+Like commit 657831ffc38e ("dccp/tcp: do not inherit mc_list from parent")
+we should clear ipv6_mc_list etc. for IPv6 sockets too.
+
+Cc: Eric Dumazet <edumazet at google.com>
+Signed-off-by: Cong Wang <xiyou.wangcong at gmail.com>
+Acked-by: Eric Dumazet <edumazet at google.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/dccp/ipv6.c     | 6 ++++++
+ net/ipv6/tcp_ipv6.c | 2 ++
+ 2 files changed, 8 insertions(+)
+
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -426,6 +426,9 @@ static struct sock *dccp_v6_request_recv
+ 		newsk->sk_backlog_rcv = dccp_v4_do_rcv;
+ 		newnp->pktoptions  = NULL;
+ 		newnp->opt	   = NULL;
++		newnp->ipv6_mc_list = NULL;
++		newnp->ipv6_ac_list = NULL;
++		newnp->ipv6_fl_list = NULL;
+ 		newnp->mcast_oif   = inet6_iif(skb);
+ 		newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
+ 
+@@ -490,6 +493,9 @@ static struct sock *dccp_v6_request_recv
+ 	/* Clone RX bits */
+ 	newnp->rxopt.all = np->rxopt.all;
+ 
++	newnp->ipv6_mc_list = NULL;
++	newnp->ipv6_ac_list = NULL;
++	newnp->ipv6_fl_list = NULL;
+ 	newnp->pktoptions = NULL;
+ 	newnp->opt	  = NULL;
+ 	newnp->mcast_oif  = inet6_iif(skb);
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -1046,6 +1046,7 @@ static struct sock *tcp_v6_syn_recv_sock
+ 		newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
+ #endif
+ 
++		newnp->ipv6_mc_list = NULL;
+ 		newnp->ipv6_ac_list = NULL;
+ 		newnp->ipv6_fl_list = NULL;
+ 		newnp->pktoptions  = NULL;
+@@ -1115,6 +1116,7 @@ static struct sock *tcp_v6_syn_recv_sock
+ 	   First: no IPv4 options.
+ 	 */
+ 	newinet->inet_opt = NULL;
++	newnp->ipv6_mc_list = NULL;
+ 	newnp->ipv6_ac_list = NULL;
+ 	newnp->ipv6_fl_list = NULL;
+ 
diff --git a/debian/patches/bugfix/all/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch b/debian/patches/bugfix/all/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch
new file mode 100644
index 0000000..4ece85c
--- /dev/null
+++ b/debian/patches/bugfix/all/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch
@@ -0,0 +1,62 @@
+From: Eric Dumazet <edumazet at google.com>
+Date: Fri, 19 May 2017 14:17:48 -0700
+Subject: ipv6: fix out of bound writes in __ip6_append_data()
+Origin: https://git.kernel.org/linus/232cd35d0804cc241eb887bb8d4d9b3b9881c64a
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9242
+
+Andrey Konovalov and idaifish at 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 at google.com>
+Reported-by: Andrey Konovalov <andreyknvl at google.com>
+Tested-by: Andrey Konovalov <andreyknvl at google.com>
+Reported-by: <idaifish at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/ipv6/ip6_output.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1448,6 +1448,11 @@ alloc_new_skb:
+ 			 */
+ 			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,
+@@ -1497,13 +1502,9 @@ alloc_new_skb:
+ 				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;
diff --git a/debian/patches/bugfix/all/ipv6-prevent-overrun-when-parsing-v6-header-options.patch b/debian/patches/bugfix/all/ipv6-prevent-overrun-when-parsing-v6-header-options.patch
new file mode 100644
index 0000000..4137e70
--- /dev/null
+++ b/debian/patches/bugfix/all/ipv6-prevent-overrun-when-parsing-v6-header-options.patch
@@ -0,0 +1,221 @@
+From: Craig Gallek <kraig at google.com>
+Date: Tue, 16 May 2017 14:36:23 -0400
+Subject: ipv6: Prevent overrun when parsing v6 header options
+Origin: https://git.kernel.org/linus/2423496af35d94a87156b063ea5cedffc10a70a1
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9074
+
+The KASAN warning repoted below was discovered with a syzkaller
+program.  The reproducer is basically:
+  int s = socket(AF_INET6, SOCK_RAW, NEXTHDR_HOP);
+  send(s, &one_byte_of_data, 1, MSG_MORE);
+  send(s, &more_than_mtu_bytes_data, 2000, 0);
+
+The socket() call sets the nexthdr field of the v6 header to
+NEXTHDR_HOP, the first send call primes the payload with a non zero
+byte of data, and the second send call triggers the fragmentation path.
+
+The fragmentation code tries to parse the header options in order
+to figure out where to insert the fragment option.  Since nexthdr points
+to an invalid option, the calculation of the size of the network header
+can made to be much larger than the linear section of the skb and data
+is read outside of it.
+
+This fix makes ip6_find_1stfrag return an error if it detects
+running out-of-bounds.
+
+[   42.361487] ==================================================================
+[   42.364412] BUG: KASAN: slab-out-of-bounds in ip6_fragment+0x11c8/0x3730
+[   42.365471] Read of size 840 at addr ffff88000969e798 by task ip6_fragment-oo/3789
+[   42.366469]
+[   42.366696] CPU: 1 PID: 3789 Comm: ip6_fragment-oo Not tainted 4.11.0+ #41
+[   42.367628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014
+[   42.368824] Call Trace:
+[   42.369183]  dump_stack+0xb3/0x10b
+[   42.369664]  print_address_description+0x73/0x290
+[   42.370325]  kasan_report+0x252/0x370
+[   42.370839]  ? ip6_fragment+0x11c8/0x3730
+[   42.371396]  check_memory_region+0x13c/0x1a0
+[   42.371978]  memcpy+0x23/0x50
+[   42.372395]  ip6_fragment+0x11c8/0x3730
+[   42.372920]  ? nf_ct_expect_unregister_notifier+0x110/0x110
+[   42.373681]  ? ip6_copy_metadata+0x7f0/0x7f0
+[   42.374263]  ? ip6_forward+0x2e30/0x2e30
+[   42.374803]  ip6_finish_output+0x584/0x990
+[   42.375350]  ip6_output+0x1b7/0x690
+[   42.375836]  ? ip6_finish_output+0x990/0x990
+[   42.376411]  ? ip6_fragment+0x3730/0x3730
+[   42.376968]  ip6_local_out+0x95/0x160
+[   42.377471]  ip6_send_skb+0xa1/0x330
+[   42.377969]  ip6_push_pending_frames+0xb3/0xe0
+[   42.378589]  rawv6_sendmsg+0x2051/0x2db0
+[   42.379129]  ? rawv6_bind+0x8b0/0x8b0
+[   42.379633]  ? _copy_from_user+0x84/0xe0
+[   42.380193]  ? debug_check_no_locks_freed+0x290/0x290
+[   42.380878]  ? ___sys_sendmsg+0x162/0x930
+[   42.381427]  ? rcu_read_lock_sched_held+0xa3/0x120
+[   42.382074]  ? sock_has_perm+0x1f6/0x290
+[   42.382614]  ? ___sys_sendmsg+0x167/0x930
+[   42.383173]  ? lock_downgrade+0x660/0x660
+[   42.383727]  inet_sendmsg+0x123/0x500
+[   42.384226]  ? inet_sendmsg+0x123/0x500
+[   42.384748]  ? inet_recvmsg+0x540/0x540
+[   42.385263]  sock_sendmsg+0xca/0x110
+[   42.385758]  SYSC_sendto+0x217/0x380
+[   42.386249]  ? SYSC_connect+0x310/0x310
+[   42.386783]  ? __might_fault+0x110/0x1d0
+[   42.387324]  ? lock_downgrade+0x660/0x660
+[   42.387880]  ? __fget_light+0xa1/0x1f0
+[   42.388403]  ? __fdget+0x18/0x20
+[   42.388851]  ? sock_common_setsockopt+0x95/0xd0
+[   42.389472]  ? SyS_setsockopt+0x17f/0x260
+[   42.390021]  ? entry_SYSCALL_64_fastpath+0x5/0xbe
+[   42.390650]  SyS_sendto+0x40/0x50
+[   42.391103]  entry_SYSCALL_64_fastpath+0x1f/0xbe
+[   42.391731] RIP: 0033:0x7fbbb711e383
+[   42.392217] RSP: 002b:00007ffff4d34f28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+[   42.393235] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbbb711e383
+[   42.394195] RDX: 0000000000001000 RSI: 00007ffff4d34f60 RDI: 0000000000000003
+[   42.395145] RBP: 0000000000000046 R08: 00007ffff4d34f40 R09: 0000000000000018
+[   42.396056] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400aad
+[   42.396598] R13: 0000000000000066 R14: 00007ffff4d34ee0 R15: 00007fbbb717af00
+[   42.397257]
+[   42.397411] Allocated by task 3789:
+[   42.397702]  save_stack_trace+0x16/0x20
+[   42.398005]  save_stack+0x46/0xd0
+[   42.398267]  kasan_kmalloc+0xad/0xe0
+[   42.398548]  kasan_slab_alloc+0x12/0x20
+[   42.398848]  __kmalloc_node_track_caller+0xcb/0x380
+[   42.399224]  __kmalloc_reserve.isra.32+0x41/0xe0
+[   42.399654]  __alloc_skb+0xf8/0x580
+[   42.400003]  sock_wmalloc+0xab/0xf0
+[   42.400346]  __ip6_append_data.isra.41+0x2472/0x33d0
+[   42.400813]  ip6_append_data+0x1a8/0x2f0
+[   42.401122]  rawv6_sendmsg+0x11ee/0x2db0
+[   42.401505]  inet_sendmsg+0x123/0x500
+[   42.401860]  sock_sendmsg+0xca/0x110
+[   42.402209]  ___sys_sendmsg+0x7cb/0x930
+[   42.402582]  __sys_sendmsg+0xd9/0x190
+[   42.402941]  SyS_sendmsg+0x2d/0x50
+[   42.403273]  entry_SYSCALL_64_fastpath+0x1f/0xbe
+[   42.403718]
+[   42.403871] Freed by task 1794:
+[   42.404146]  save_stack_trace+0x16/0x20
+[   42.404515]  save_stack+0x46/0xd0
+[   42.404827]  kasan_slab_free+0x72/0xc0
+[   42.405167]  kfree+0xe8/0x2b0
+[   42.405462]  skb_free_head+0x74/0xb0
+[   42.405806]  skb_release_data+0x30e/0x3a0
+[   42.406198]  skb_release_all+0x4a/0x60
+[   42.406563]  consume_skb+0x113/0x2e0
+[   42.406910]  skb_free_datagram+0x1a/0xe0
+[   42.407288]  netlink_recvmsg+0x60d/0xe40
+[   42.407667]  sock_recvmsg+0xd7/0x110
+[   42.408022]  ___sys_recvmsg+0x25c/0x580
+[   42.408395]  __sys_recvmsg+0xd6/0x190
+[   42.408753]  SyS_recvmsg+0x2d/0x50
+[   42.409086]  entry_SYSCALL_64_fastpath+0x1f/0xbe
+[   42.409513]
+[   42.409665] The buggy address belongs to the object at ffff88000969e780
+[   42.409665]  which belongs to the cache kmalloc-512 of size 512
+[   42.410846] The buggy address is located 24 bytes inside of
+[   42.410846]  512-byte region [ffff88000969e780, ffff88000969e980)
+[   42.411941] The buggy address belongs to the page:
+[   42.412405] page:ffffea000025a780 count:1 mapcount:0 mapping:          (null) index:0x0 compound_mapcount: 0
+[   42.413298] flags: 0x100000000008100(slab|head)
+[   42.413729] raw: 0100000000008100 0000000000000000 0000000000000000 00000001800c000c
+[   42.414387] raw: ffffea00002a9500 0000000900000007 ffff88000c401280 0000000000000000
+[   42.415074] page dumped because: kasan: bad access detected
+[   42.415604]
+[   42.415757] Memory state around the buggy address:
+[   42.416222]  ffff88000969e880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[   42.416904]  ffff88000969e900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[   42.417591] >ffff88000969e980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+[   42.418273]                    ^
+[   42.418588]  ffff88000969ea00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[   42.419273]  ffff88000969ea80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[   42.419882] ==================================================================
+
+Reported-by: Andrey Konovalov <andreyknvl at google.com>
+Signed-off-by: Craig Gallek <kraig at google.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/ipv6/ip6_offload.c |  2 ++
+ net/ipv6/ip6_output.c  |  4 ++++
+ net/ipv6/output_core.c | 14 ++++++++------
+ net/ipv6/udp_offload.c |  2 ++
+ 4 files changed, 16 insertions(+), 6 deletions(-)
+
+--- a/net/ipv6/ip6_offload.c
++++ b/net/ipv6/ip6_offload.c
+@@ -117,6 +117,8 @@ static struct sk_buff *ipv6_gso_segment(
+ 
+ 		if (udpfrag) {
+ 			unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
++			if (unfrag_ip6hlen < 0)
++				return ERR_PTR(unfrag_ip6hlen);
+ 			fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
+ 			fptr->frag_off = htons(offset);
+ 			if (skb->next)
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -587,6 +587,10 @@ int ip6_fragment(struct net *net, struct
+ 	u8 *prevhdr, nexthdr = 0;
+ 
+ 	hlen = ip6_find_1stfragopt(skb, &prevhdr);
++	if (hlen < 0) {
++		err = hlen;
++		goto fail;
++	}
+ 	nexthdr = *prevhdr;
+ 
+ 	mtu = ip6_skb_dst_mtu(skb);
+--- a/net/ipv6/output_core.c
++++ b/net/ipv6/output_core.c
+@@ -79,14 +79,13 @@ EXPORT_SYMBOL(ipv6_select_ident);
+ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+ {
+ 	u16 offset = sizeof(struct ipv6hdr);
+-	struct ipv6_opt_hdr *exthdr =
+-				(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
+ 	unsigned int packet_len = skb_tail_pointer(skb) -
+ 		skb_network_header(skb);
+ 	int found_rhdr = 0;
+ 	*nexthdr = &ipv6_hdr(skb)->nexthdr;
+ 
+-	while (offset + 1 <= packet_len) {
++	while (offset <= packet_len) {
++		struct ipv6_opt_hdr *exthdr;
+ 
+ 		switch (**nexthdr) {
+ 
+@@ -107,13 +106,16 @@ int ip6_find_1stfragopt(struct sk_buff *
+ 			return offset;
+ 		}
+ 
+-		offset += ipv6_optlen(exthdr);
+-		*nexthdr = &exthdr->nexthdr;
++		if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
++			return -EINVAL;
++
+ 		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
+ 						 offset);
++		offset += ipv6_optlen(exthdr);
++		*nexthdr = &exthdr->nexthdr;
+ 	}
+ 
+-	return offset;
++	return -EINVAL;
+ }
+ EXPORT_SYMBOL(ip6_find_1stfragopt);
+ 
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -91,6 +91,8 @@ static struct sk_buff *udp6_ufo_fragment
+ 		 * bytes to insert fragment header.
+ 		 */
+ 		unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
++		if (unfrag_ip6hlen < 0)
++			return ERR_PTR(unfrag_ip6hlen);
+ 		nexthdr = *prevhdr;
+ 		*prevhdr = NEXTHDR_FRAGMENT;
+ 		unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
diff --git a/debian/patches/bugfix/all/nfsv4-fix-callback-server-shutdown.patch b/debian/patches/bugfix/all/nfsv4-fix-callback-server-shutdown.patch
new file mode 100644
index 0000000..8533317
--- /dev/null
+++ b/debian/patches/bugfix/all/nfsv4-fix-callback-server-shutdown.patch
@@ -0,0 +1,147 @@
+From: Trond Myklebust <trond.myklebust at primarydata.com>
+Date: Wed, 26 Apr 2017 11:55:27 -0400
+Subject: [2/2] NFSv4: Fix callback server shutdown
+Origin: https://git.kernel.org/linus/ed6473ddc704a2005b9900ca08e236ebb2d8540a
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9059
+
+We want to use kthread_stop() in order to ensure the threads are
+shut down before we tear down the nfs_callback_info in nfs_callback_down.
+
+Tested-and-reviewed-by: Kinglong Mee <kinglongmee at gmail.com>
+Reported-by: Kinglong Mee <kinglongmee at gmail.com>
+Fixes: bb6aeba736ba9 ("NFSv4.x: Switch to using svc_set_num_threads()...")
+Signed-off-by: Trond Myklebust <trond.myklebust at primarydata.com>
+Signed-off-by: J. Bruce Fields <bfields at redhat.com>
+---
+ fs/nfs/callback.c          | 24 ++++++++++++++++--------
+ include/linux/sunrpc/svc.h |  1 +
+ net/sunrpc/svc.c           | 38 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 55 insertions(+), 8 deletions(-)
+
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -75,7 +75,10 @@ nfs4_callback_svc(void *vrqstp)
+ 
+ 	set_freezable();
+ 
+-	while (!kthread_should_stop()) {
++	while (!kthread_freezable_should_stop(NULL)) {
++
++		if (signal_pending(current))
++			flush_signals(current);
+ 		/*
+ 		 * Listen for a request on the socket
+ 		 */
+@@ -84,6 +87,8 @@ nfs4_callback_svc(void *vrqstp)
+ 			continue;
+ 		svc_process(rqstp);
+ 	}
++	svc_exit_thread(rqstp);
++	module_put_and_exit(0);
+ 	return 0;
+ }
+ 
+@@ -102,9 +107,10 @@ nfs41_callback_svc(void *vrqstp)
+ 
+ 	set_freezable();
+ 
+-	while (!kthread_should_stop()) {
+-		if (try_to_freeze())
+-			continue;
++	while (!kthread_freezable_should_stop(NULL)) {
++
++		if (signal_pending(current))
++			flush_signals(current);
+ 
+ 		prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
+ 		spin_lock_bh(&serv->sv_cb_lock);
+@@ -120,11 +126,13 @@ nfs41_callback_svc(void *vrqstp)
+ 				error);
+ 		} else {
+ 			spin_unlock_bh(&serv->sv_cb_lock);
+-			schedule();
++			if (!kthread_should_stop())
++				schedule();
+ 			finish_wait(&serv->sv_cb_waitq, &wq);
+ 		}
+-		flush_signals(current);
+ 	}
++	svc_exit_thread(rqstp);
++	module_put_and_exit(0);
+ 	return 0;
+ }
+ 
+@@ -220,14 +228,14 @@ err_bind:
+ static struct svc_serv_ops nfs40_cb_sv_ops = {
+ 	.svo_function		= nfs4_callback_svc,
+ 	.svo_enqueue_xprt	= svc_xprt_do_enqueue,
+-	.svo_setup		= svc_set_num_threads,
++	.svo_setup		= svc_set_num_threads_sync,
+ 	.svo_module		= THIS_MODULE,
+ };
+ #if defined(CONFIG_NFS_V4_1)
+ static struct svc_serv_ops nfs41_cb_sv_ops = {
+ 	.svo_function		= nfs41_callback_svc,
+ 	.svo_enqueue_xprt	= svc_xprt_do_enqueue,
+-	.svo_setup		= svc_set_num_threads,
++	.svo_setup		= svc_set_num_threads_sync,
+ 	.svo_module		= THIS_MODULE,
+ };
+ 
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -470,6 +470,7 @@ void		   svc_pool_map_put(void);
+ struct svc_serv *  svc_create_pooled(struct svc_program *, unsigned int,
+ 			struct svc_serv_ops *);
+ int		   svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
++int		   svc_set_num_threads_sync(struct svc_serv *, struct svc_pool *, int);
+ int		   svc_pool_stats_open(struct svc_serv *serv, struct file *file);
+ void		   svc_destroy(struct svc_serv *);
+ void		   svc_shutdown_net(struct svc_serv *, struct net *);
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -795,6 +795,44 @@ svc_set_num_threads(struct svc_serv *ser
+ }
+ EXPORT_SYMBOL_GPL(svc_set_num_threads);
+ 
++/* destroy old threads */
++static int
++svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
++{
++	struct task_struct *task;
++	unsigned int state = serv->sv_nrthreads-1;
++
++	/* destroy old threads */
++	do {
++		task = choose_victim(serv, pool, &state);
++		if (task == NULL)
++			break;
++		kthread_stop(task);
++		nrservs++;
++	} while (nrservs < 0);
++	return 0;
++}
++
++int
++svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
++{
++	if (pool == NULL) {
++		/* The -1 assumes caller has done a svc_get() */
++		nrservs -= (serv->sv_nrthreads-1);
++	} else {
++		spin_lock_bh(&pool->sp_lock);
++		nrservs -= pool->sp_nrthreads;
++		spin_unlock_bh(&pool->sp_lock);
++	}
++
++	if (nrservs > 0)
++		return svc_start_kthreads(serv, pool, nrservs);
++	if (nrservs < 0)
++		return svc_stop_kthreads(serv, pool, nrservs);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(svc_set_num_threads_sync);
++
+ /*
+  * Called from a server thread as it's exiting. Caller must hold the "service
+  * mutex" for the service.
diff --git a/debian/patches/bugfix/all/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch b/debian/patches/bugfix/all/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch
new file mode 100644
index 0000000..7dd9425
--- /dev/null
+++ b/debian/patches/bugfix/all/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch
@@ -0,0 +1,29 @@
+From: Eric Dumazet <edumazet at google.com>
+Date: Wed, 17 May 2017 07:16:40 -0700
+Subject: sctp: do not inherit ipv6_{mc|ac|fl}_list from parent
+Origin: https://git.kernel.org/linus/fdcee2cbb8438702ea1b328fb6e0ac5e9a40c7f8
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9075
+
+SCTP needs fixes similar to 83eaddab4378 ("ipv6/dccp: do not inherit
+ipv6_mc_list from parent"), otherwise bad things can happen.
+
+Signed-off-by: Eric Dumazet <edumazet at google.com>
+Reported-by: Andrey Konovalov <andreyknvl at google.com>
+Tested-by: Andrey Konovalov <andreyknvl at google.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/sctp/ipv6.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -666,6 +666,9 @@ static struct sock *sctp_v6_create_accep
+ 	newnp = inet6_sk(newsk);
+ 
+ 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
++	newnp->ipv6_mc_list = NULL;
++	newnp->ipv6_ac_list = NULL;
++	newnp->ipv6_fl_list = NULL;
+ 
+ 	rcu_read_lock();
+ 	opt = rcu_dereference(np->opt);
diff --git a/debian/patches/bugfix/all/sunrpc-refactor-svc_set_num_threads.patch b/debian/patches/bugfix/all/sunrpc-refactor-svc_set_num_threads.patch
new file mode 100644
index 0000000..5fae928
--- /dev/null
+++ b/debian/patches/bugfix/all/sunrpc-refactor-svc_set_num_threads.patch
@@ -0,0 +1,154 @@
+From: Trond Myklebust <trond.myklebust at primarydata.com>
+Date: Wed, 26 Apr 2017 11:55:26 -0400
+Subject: [1/2] SUNRPC: Refactor svc_set_num_threads()
+Origin: https://git.kernel.org/linus/9e0d87680d689f1758185851c3da6eafb16e71e1
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-9059
+
+Refactor to separate out the functions of starting and stopping threads
+so that they can be used in other helpers.
+
+Signed-off-by: Trond Myklebust <trond.myklebust at primarydata.com>
+Tested-and-reviewed-by: Kinglong Mee <kinglongmee at gmail.com>
+Signed-off-by: J. Bruce Fields <bfields at redhat.com>
+---
+ net/sunrpc/svc.c | 96 ++++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 58 insertions(+), 38 deletions(-)
+
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index a08aeb56b8e4..98dc33ae738b 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -702,59 +702,32 @@ choose_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state)
+ 	return task;
+ }
+ 
+-/*
+- * Create or destroy enough new threads to make the number
+- * of threads the given number.  If `pool' is non-NULL, applies
+- * only to threads in that pool, otherwise round-robins between
+- * all pools.  Caller must ensure that mutual exclusion between this and
+- * server startup or shutdown.
+- *
+- * Destroying threads relies on the service threads filling in
+- * rqstp->rq_task, which only the nfs ones do.  Assumes the serv
+- * has been created using svc_create_pooled().
+- *
+- * Based on code that used to be in nfsd_svc() but tweaked
+- * to be pool-aware.
+- */
+-int
+-svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
++/* create new threads */
++static int
++svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+ {
+ 	struct svc_rqst	*rqstp;
+ 	struct task_struct *task;
+ 	struct svc_pool *chosen_pool;
+-	int error = 0;
+ 	unsigned int state = serv->sv_nrthreads-1;
+ 	int node;
+ 
+-	if (pool == NULL) {
+-		/* The -1 assumes caller has done a svc_get() */
+-		nrservs -= (serv->sv_nrthreads-1);
+-	} else {
+-		spin_lock_bh(&pool->sp_lock);
+-		nrservs -= pool->sp_nrthreads;
+-		spin_unlock_bh(&pool->sp_lock);
+-	}
+-
+-	/* create new threads */
+-	while (nrservs > 0) {
++	do {
+ 		nrservs--;
+ 		chosen_pool = choose_pool(serv, pool, &state);
+ 
+ 		node = svc_pool_map_get_node(chosen_pool->sp_id);
+ 		rqstp = svc_prepare_thread(serv, chosen_pool, node);
+-		if (IS_ERR(rqstp)) {
+-			error = PTR_ERR(rqstp);
+-			break;
+-		}
++		if (IS_ERR(rqstp))
++			return PTR_ERR(rqstp);
+ 
+ 		__module_get(serv->sv_ops->svo_module);
+ 		task = kthread_create_on_node(serv->sv_ops->svo_function, rqstp,
+ 					      node, "%s", serv->sv_name);
+ 		if (IS_ERR(task)) {
+-			error = PTR_ERR(task);
+ 			module_put(serv->sv_ops->svo_module);
+ 			svc_exit_thread(rqstp);
+-			break;
++			return PTR_ERR(task);
+ 		}
+ 
+ 		rqstp->rq_task = task;
+@@ -763,15 +736,62 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+ 
+ 		svc_sock_update_bufs(serv);
+ 		wake_up_process(task);
+-	}
++	} while (nrservs > 0);
++
++	return 0;
++}
++
++
++/* destroy old threads */
++static int
++svc_signal_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
++{
++	struct task_struct *task;
++	unsigned int state = serv->sv_nrthreads-1;
++
+ 	/* destroy old threads */
+-	while (nrservs < 0 &&
+-	       (task = choose_victim(serv, pool, &state)) != NULL) {
++	do {
++		task = choose_victim(serv, pool, &state);
++		if (task == NULL)
++			break;
+ 		send_sig(SIGINT, task, 1);
+ 		nrservs++;
++	} while (nrservs < 0);
++
++	return 0;
++}
++
++/*
++ * Create or destroy enough new threads to make the number
++ * of threads the given number.  If `pool' is non-NULL, applies
++ * only to threads in that pool, otherwise round-robins between
++ * all pools.  Caller must ensure that mutual exclusion between this and
++ * server startup or shutdown.
++ *
++ * Destroying threads relies on the service threads filling in
++ * rqstp->rq_task, which only the nfs ones do.  Assumes the serv
++ * has been created using svc_create_pooled().
++ *
++ * Based on code that used to be in nfsd_svc() but tweaked
++ * to be pool-aware.
++ */
++int
++svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
++{
++	if (pool == NULL) {
++		/* The -1 assumes caller has done a svc_get() */
++		nrservs -= (serv->sv_nrthreads-1);
++	} else {
++		spin_lock_bh(&pool->sp_lock);
++		nrservs -= pool->sp_nrthreads;
++		spin_unlock_bh(&pool->sp_lock);
+ 	}
+ 
+-	return error;
++	if (nrservs > 0)
++		return svc_start_kthreads(serv, pool, nrservs);
++	if (nrservs < 0)
++		return svc_signal_kthreads(serv, pool, nrservs);
++	return 0;
+ }
+ EXPORT_SYMBOL_GPL(svc_set_num_threads);
+ 
diff --git a/debian/patches/bugfix/all/tracing-Use-strlcpy-instead-of-strcpy-in-__trace_fin.patch b/debian/patches/bugfix/all/tracing-Use-strlcpy-instead-of-strcpy-in-__trace_fin.patch
new file mode 100644
index 0000000..2a97a2d
--- /dev/null
+++ b/debian/patches/bugfix/all/tracing-Use-strlcpy-instead-of-strcpy-in-__trace_fin.patch
@@ -0,0 +1,34 @@
+From: Amey Telawane <ameyt at codeaurora.org>
+Date: Wed, 3 May 2017 15:41:14 +0530
+Subject: tracing: Use strlcpy() instead of strcpy() in __trace_find_cmdline()
+Origin: https://git.kernel.org/linus/e09e28671cda63e6308b31798b997639120e2a21
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-0605
+
+Strcpy is inherently not safe, and strlcpy() should be used instead.
+__trace_find_cmdline() uses strcpy() because the comms saved must have a
+terminating nul character, but it doesn't hurt to add the extra protection
+of using strlcpy() instead of strcpy().
+
+Link: http://lkml.kernel.org/r/1493806274-13936-1-git-send-email-amit.pundir@linaro.org
+
+Signed-off-by: Amey Telawane <ameyt at codeaurora.org>
+[AmitP: Cherry-picked this commit from CodeAurora kernel/msm-3.10
+https://source.codeaurora.org/quic/la/kernel/msm-3.10/commit/?id=2161ae9a70b12cf18ac8e5952a20161ffbccb477]
+Signed-off-by: Amit Pundir <amit.pundir at linaro.org>
+[ Updated change log and removed the "- 1" from len parameter ]
+Signed-off-by: Steven Rostedt (VMware) <rostedt at goodmis.org>
+---
+ kernel/trace/trace.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -1862,7 +1862,7 @@ static void __trace_find_cmdline(int pid
+ 
+ 	map = savedcmd->map_pid_to_cmdline[pid];
+ 	if (map != NO_CMDLINE_MAP)
+-		strcpy(comm, get_saved_cmdlines(map));
++		strlcpy(comm, get_saved_cmdlines(map), TASK_COMM_LEN);
+ 	else
+ 		strcpy(comm, "<...>");
+ }
diff --git a/debian/patches/series b/debian/patches/series
index 05a210d..dafc118 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -104,6 +104,15 @@ features/all/securelevel/arm64-add-kernel-config-option-to-set-securelevel-wh.pa
 # Security fixes
 debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
 debian/time-mark-timer_stats-as-broken.patch
+bugfix/all/tracing-Use-strlcpy-instead-of-strcpy-in-__trace_fin.patch
+bugfix/all/dccp-tcp-do-not-inherit-mc_list-from-parent.patch
+bugfix/all/sunrpc-refactor-svc_set_num_threads.patch
+bugfix/all/nfsv4-fix-callback-server-shutdown.patch
+bugfix/all/ipv6-prevent-overrun-when-parsing-v6-header-options.patch
+bugfix/all/sctp-do-not-inherit-ipv6_-mc-ac-fl-_list-from-parent.patch
+bugfix/all/ipv6-dccp-do-not-inherit-ipv6_mc_list-from-parent.patch
+bugfix/all/crypto-skcipher-add-missing-api-setkey-checks.patch
+bugfix/all/ipv6-fix-out-of-bound-writes-in-__ip6_append_data.patch
 
 # Fix exported symbol versions
 bugfix/ia64/revert-ia64-move-exports-to-definitions.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list