[linux] 01/01: Add various security fixes
debian-kernel at lists.debian.org
debian-kernel at lists.debian.org
Fri Jan 5 17:18:40 UTC 2018
This is an automated email from the git hooks/post-receive script.
benh pushed a commit to branch wheezy-security
in repository linux.
commit c7f323201b9a46069d181137b44f1faef4845545
Author: Ben Hutchings <ben at decadent.org.uk>
Date: Fri Jan 5 17:18:19 2018 +0000
Add various security fixes
---
debian/changelog | 7 +
...-require-that-the-underlying-hash-algorit.patch | 148 +++++++++++++++++++
...ypto-salsa20-fix-blkcipher_walk-API-usage.patch | 88 ++++++++++++
...ssing-permission-check-for-request_key-de.patch | 158 +++++++++++++++++++++
...prevent-malicious-bnuminterfaces-overflow.patch | 46 ++++++
...ix-stack-out-of-bounds-read-in-write_mmio.patch | 132 +++++++++++++++++
debian/patches/series | 5 +
7 files changed, 584 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index d5105dc..901a537 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,6 +10,13 @@ linux (3.2.96-3) UNRELEASED; urgency=high
- libata: Align ata_device's id on a cacheline
- libata: Ignore spurious PHY event on LPM policy change
- net/ipv6: add sysctl option accept_ra_min_hop_limit
+ * USB: core: prevent malicious bNumInterfaces overflow (CVE-2017-17558)
+ * [x86] KVM: Fix stack-out-of-bounds read in write_mmio (CVE-2017-17741)
+ * crypto: salsa20 - fix blkcipher_walk API usage (CVE-2017-17805)
+ * crypto: hmac - require that the underlying hash algorithm is unkeyed
+ (CVE-2017-17806)
+ * KEYS: add missing permission check for request_key() destination
+ (CVE-2017-17807)
-- Ben Hutchings <ben at decadent.org.uk> Thu, 04 Jan 2018 05:01:25 +0000
diff --git a/debian/patches/bugfix/all/crypto-hmac-require-that-the-underlying-hash-algorit.patch b/debian/patches/bugfix/all/crypto-hmac-require-that-the-underlying-hash-algorit.patch
new file mode 100644
index 0000000..cf76e91
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-hmac-require-that-the-underlying-hash-algorit.patch
@@ -0,0 +1,148 @@
+From: Eric Biggers <ebiggers at google.com>
+Date: Tue, 28 Nov 2017 18:01:38 -0800
+Subject: crypto: hmac - require that the underlying hash algorithm is unkeyed
+Origin: https://git.kernel.org/linus/af3ff8045bbf3e32f1a448542e73abb4c8ceb6f1
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-17806
+
+Because the HMAC template didn't check that its underlying hash
+algorithm is unkeyed, trying to use "hmac(hmac(sha3-512-generic))"
+through AF_ALG or through KEYCTL_DH_COMPUTE resulted in the inner HMAC
+being used without having been keyed, resulting in sha3_update() being
+called without sha3_init(), causing a stack buffer overflow.
+
+This is a very old bug, but it seems to have only started causing real
+problems when SHA-3 support was added (requires CONFIG_CRYPTO_SHA3)
+because the innermost hash's state is ->import()ed from a zeroed buffer,
+and it just so happens that other hash algorithms are fine with that,
+but SHA-3 is not. However, there could be arch or hardware-dependent
+hash algorithms also affected; I couldn't test everything.
+
+Fix the bug by introducing a function crypto_shash_alg_has_setkey()
+which tests whether a shash algorithm is keyed. Then update the HMAC
+template to require that its underlying hash algorithm is unkeyed.
+
+Here is a reproducer:
+
+ #include <linux/if_alg.h>
+ #include <sys/socket.h>
+
+ int main()
+ {
+ int algfd;
+ struct sockaddr_alg addr = {
+ .salg_type = "hash",
+ .salg_name = "hmac(hmac(sha3-512-generic))",
+ };
+ char key[4096] = { 0 };
+
+ algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ bind(algfd, (const struct sockaddr *)&addr, sizeof(addr));
+ setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
+ }
+
+Here was the KASAN report from syzbot:
+
+ BUG: KASAN: stack-out-of-bounds in memcpy include/linux/string.h:341 [inline]
+ BUG: KASAN: stack-out-of-bounds in sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
+ Write of size 4096 at addr ffff8801cca07c40 by task syzkaller076574/3044
+
+ CPU: 1 PID: 3044 Comm: syzkaller076574 Not tainted 4.14.0-mm1+ #25
+ Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+ Call Trace:
+ __dump_stack lib/dump_stack.c:17 [inline]
+ dump_stack+0x194/0x257 lib/dump_stack.c:53
+ print_address_description+0x73/0x250 mm/kasan/report.c:252
+ kasan_report_error mm/kasan/report.c:351 [inline]
+ kasan_report+0x25b/0x340 mm/kasan/report.c:409
+ check_memory_region_inline mm/kasan/kasan.c:260 [inline]
+ check_memory_region+0x137/0x190 mm/kasan/kasan.c:267
+ memcpy+0x37/0x50 mm/kasan/kasan.c:303
+ memcpy include/linux/string.h:341 [inline]
+ sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
+ crypto_shash_update+0xcb/0x220 crypto/shash.c:109
+ shash_finup_unaligned+0x2a/0x60 crypto/shash.c:151
+ crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
+ hmac_finup+0x182/0x330 crypto/hmac.c:152
+ crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
+ shash_digest_unaligned+0x9e/0xd0 crypto/shash.c:172
+ crypto_shash_digest+0xc4/0x120 crypto/shash.c:186
+ hmac_setkey+0x36a/0x690 crypto/hmac.c:66
+ crypto_shash_setkey+0xad/0x190 crypto/shash.c:64
+ shash_async_setkey+0x47/0x60 crypto/shash.c:207
+ crypto_ahash_setkey+0xaf/0x180 crypto/ahash.c:200
+ hash_setkey+0x40/0x90 crypto/algif_hash.c:446
+ alg_setkey crypto/af_alg.c:221 [inline]
+ alg_setsockopt+0x2a1/0x350 crypto/af_alg.c:254
+ SYSC_setsockopt net/socket.c:1851 [inline]
+ SyS_setsockopt+0x189/0x360 net/socket.c:1830
+ entry_SYSCALL_64_fastpath+0x1f/0x96
+
+Reported-by: syzbot <syzkaller at googlegroups.com>
+Cc: <stable at vger.kernel.org>
+Signed-off-by: Eric Biggers <ebiggers at google.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/hmac.c | 6 +++++-
+ crypto/shash.c | 5 +++--
+ include/crypto/internal/hash.h | 8 ++++++++
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/crypto/hmac.c b/crypto/hmac.c
+index ade790b454e9..758688b4bc6b 100644
+--- a/crypto/hmac.c
++++ b/crypto/hmac.c
+@@ -197,11 +197,15 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
+ salg = shash_attr_alg(tb[1], 0, 0);
+ if (IS_ERR(salg))
+ return PTR_ERR(salg);
++ alg = &salg->base;
+
++ /* The underlying hash algorithm must be unkeyed */
+ err = -EINVAL;
++ if (crypto_shash_alg_has_setkey(salg))
++ goto out_put_alg;
++
+ ds = salg->digestsize;
+ ss = salg->statesize;
+- alg = &salg->base;
+ if (ds > alg->cra_blocksize ||
+ ss < alg->cra_blocksize)
+ goto out_put_alg;
+diff --git a/crypto/shash.c b/crypto/shash.c
+index 3e2c385ba6e2..0d66c2edc6d8 100644
+--- a/crypto/shash.c
++++ b/crypto/shash.c
+@@ -24,11 +24,12 @@
+
+ static const struct crypto_type crypto_shash_type;
+
+-static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
+- unsigned int keylen)
++int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
++ unsigned int keylen)
+ {
+ return -ENOSYS;
+ }
++EXPORT_SYMBOL_GPL(shash_no_setkey);
+
+ static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
+ unsigned int keylen)
+diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
+index 7bdb81267d44..b813ae921506 100644
+--- a/include/crypto/internal/hash.h
++++ b/include/crypto/internal/hash.h
+@@ -70,6 +70,14 @@ int ahash_register_instance(struct crypto_template *tmpl,
+ struct ahash_instance *inst);
+ void ahash_free_instance(struct crypto_instance *inst);
+
++int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
++ unsigned int keylen);
++
++static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
++{
++ return alg->setkey != shash_no_setkey;
++}
++
+ int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn,
+ struct hash_alg_common *alg,
+ struct crypto_instance *inst);
diff --git a/debian/patches/bugfix/all/crypto-salsa20-fix-blkcipher_walk-API-usage.patch b/debian/patches/bugfix/all/crypto-salsa20-fix-blkcipher_walk-API-usage.patch
new file mode 100644
index 0000000..7f573c9
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-salsa20-fix-blkcipher_walk-API-usage.patch
@@ -0,0 +1,88 @@
+From: Eric Biggers <ebiggers at google.com>
+Date: Tue, 28 Nov 2017 20:56:59 -0800
+Subject: crypto: salsa20 - fix blkcipher_walk API usage
+Origin: https://git.kernel.org/linus/ecaaab5649781c5a0effdaf298a925063020500e
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-17805
+
+When asked to encrypt or decrypt 0 bytes, both the generic and x86
+implementations of Salsa20 crash in blkcipher_walk_done(), either when
+doing 'kfree(walk->buffer)' or 'free_page((unsigned long)walk->page)',
+because walk->buffer and walk->page have not been initialized.
+
+The bug is that Salsa20 is calling blkcipher_walk_done() even when
+nothing is in 'walk.nbytes'. But blkcipher_walk_done() is only meant to
+be called when a nonzero number of bytes have been provided.
+
+The broken code is part of an optimization that tries to make only one
+call to salsa20_encrypt_bytes() to process inputs that are not evenly
+divisible by 64 bytes. To fix the bug, just remove this "optimization"
+and use the blkcipher_walk API the same way all the other users do.
+
+Reproducer:
+
+ #include <linux/if_alg.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+
+ int main()
+ {
+ int algfd, reqfd;
+ struct sockaddr_alg addr = {
+ .salg_type = "skcipher",
+ .salg_name = "salsa20",
+ };
+ char key[16] = { 0 };
+
+ algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ bind(algfd, (void *)&addr, sizeof(addr));
+ reqfd = accept(algfd, 0, 0);
+ setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
+ read(reqfd, key, sizeof(key));
+ }
+
+Reported-by: syzbot <syzkaller at googlegroups.com>
+Fixes: eb6f13eb9f81 ("[CRYPTO] salsa20_generic: Fix multi-page processing")
+Cc: <stable at vger.kernel.org> # v2.6.25+
+Signed-off-by: Eric Biggers <ebiggers at google.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ arch/x86/crypto/salsa20_glue.c | 7 -------
+ crypto/salsa20_generic.c | 7 -------
+ 2 files changed, 14 deletions(-)
+
+diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c
+index ae1ee37f925d..6d8c7a428cff 100644
+--- a/arch/x86/crypto/salsa20_glue.c
++++ b/arch/x86/crypto/salsa20_glue.c
+@@ -64,13 +64,6 @@ static int encrypt(struct blkcipher_desc *desc,
+
+ salsa20_ivsetup(ctx, walk.iv);
+
+- if (likely(walk.nbytes == nbytes))
+- {
+- salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+- walk.dst.virt.addr, nbytes);
+- return blkcipher_walk_done(desc, &walk, 0);
+- }
+-
+ while (walk.nbytes >= 64) {
+ salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+ walk.dst.virt.addr,
+diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
+index f5e5a3386c82..5d2d5483fe38 100644
+--- a/crypto/salsa20_generic.c
++++ b/crypto/salsa20_generic.c
+@@ -188,13 +188,6 @@ static int encrypt(struct blkcipher_desc *desc,
+
+ salsa20_ivsetup(ctx, walk.iv);
+
+- if (likely(walk.nbytes == nbytes))
+- {
+- salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+- walk.src.virt.addr, nbytes);
+- return blkcipher_walk_done(desc, &walk, 0);
+- }
+-
+ while (walk.nbytes >= 64) {
+ salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+ walk.src.virt.addr,
diff --git a/debian/patches/bugfix/all/keys-add-missing-permission-check-for-request_key-de.patch b/debian/patches/bugfix/all/keys-add-missing-permission-check-for-request_key-de.patch
new file mode 100644
index 0000000..7e266c2
--- /dev/null
+++ b/debian/patches/bugfix/all/keys-add-missing-permission-check-for-request_key-de.patch
@@ -0,0 +1,158 @@
+From: Eric Biggers <ebiggers at google.com>
+Date: Fri, 8 Dec 2017 15:13:27 +0000
+Subject: KEYS: add missing permission check for request_key() destination
+Origin: https://git.kernel.org/linus/4dca6ea1d9432052afb06baf2e3ae78188a4410b
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-17807
+
+When the request_key() syscall is not passed a destination keyring, it
+links the requested key (if constructed) into the "default" request-key
+keyring. This should require Write permission to the keyring. However,
+there is actually no permission check.
+
+This can be abused to add keys to any keyring to which only Search
+permission is granted. This is because Search permission allows joining
+the keyring. keyctl_set_reqkey_keyring(KEY_REQKEY_DEFL_SESSION_KEYRING)
+then will set the default request-key keyring to the session keyring.
+Then, request_key() can be used to add keys to the keyring.
+
+Both negatively and positively instantiated keys can be added using this
+method. Adding negative keys is trivial. Adding a positive key is a
+bit trickier. It requires that either /sbin/request-key positively
+instantiates the key, or that another thread adds the key to the process
+keyring at just the right time, such that request_key() misses it
+initially but then finds it in construct_alloc_key().
+
+Fix this bug by checking for Write permission to the keyring in
+construct_get_dest_keyring() when the default keyring is being used.
+
+We don't do the permission check for non-default keyrings because that
+was already done by the earlier call to lookup_user_key(). Also,
+request_key_and_link() is currently passed a 'struct key *' rather than
+a key_ref_t, so the "possessed" bit is unavailable.
+
+We also don't do the permission check for the "requestor keyring", to
+continue to support the use case described by commit 8bbf4976b59f
+("KEYS: Alter use of key instantiation link-to-keyring argument") where
+/sbin/request-key recursively calls request_key() to add keys to the
+original requestor's destination keyring. (I don't know of any users
+who actually do that, though...)
+
+Fixes: 3e30148c3d52 ("[PATCH] Keys: Make request-key create an authorisation key")
+Signed-off-by: Eric Biggers <ebiggers at google.com>
+Signed-off-by: David Howells <dhowells at redhat.com>
+[bwh: Backported to 3.2:
+ - s/KEY_NEED_WRITE/KEY_WRITE/
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ security/keys/request_key.c | 46 ++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 37 insertions(+), 9 deletions(-)
+
+--- a/security/keys/request_key.c
++++ b/security/keys/request_key.c
+@@ -267,11 +267,12 @@ static int construct_key(struct key *key
+ * The keyring selected is returned with an extra reference upon it which the
+ * caller must release.
+ */
+-static void construct_get_dest_keyring(struct key **_dest_keyring)
++static int construct_get_dest_keyring(struct key **_dest_keyring)
+ {
+ struct request_key_auth *rka;
+ const struct cred *cred = current_cred();
+ struct key *dest_keyring = *_dest_keyring, *authkey;
++ int ret;
+
+ kenter("%p", dest_keyring);
+
+@@ -280,6 +281,8 @@ static void construct_get_dest_keyring(s
+ /* the caller supplied one */
+ key_get(dest_keyring);
+ } else {
++ bool do_perm_check = true;
++
+ /* use a default keyring; falling through the cases until we
+ * find one that we actually have */
+ switch (cred->jit_keyring) {
+@@ -294,8 +297,10 @@ static void construct_get_dest_keyring(s
+ dest_keyring =
+ key_get(rka->dest_keyring);
+ up_read(&authkey->sem);
+- if (dest_keyring)
++ if (dest_keyring) {
++ do_perm_check = false;
+ break;
++ }
+ }
+
+ case KEY_REQKEY_DEFL_THREAD_KEYRING:
+@@ -330,11 +335,29 @@ static void construct_get_dest_keyring(s
+ default:
+ BUG();
+ }
++
++ /*
++ * Require Write permission on the keyring. This is essential
++ * because the default keyring may be the session keyring, and
++ * joining a keyring only requires Search permission.
++ *
++ * However, this check is skipped for the "requestor keyring" so
++ * that /sbin/request-key can itself use request_key() to add
++ * keys to the original requestor's destination keyring.
++ */
++ if (dest_keyring && do_perm_check) {
++ ret = key_permission(make_key_ref(dest_keyring, 1),
++ KEY_WRITE);
++ if (ret) {
++ key_put(dest_keyring);
++ return ret;
++ }
++ }
+ }
+
+ *_dest_keyring = dest_keyring;
+ kleave(" [dk %d]", key_serial(dest_keyring));
+- return;
++ return 0;
+ }
+
+ /*
+@@ -452,11 +475,15 @@ static struct key *construct_key_and_lin
+ if (type == &key_type_keyring)
+ return ERR_PTR(-EPERM);
+
+- user = key_user_lookup(current_fsuid(), current_user_ns());
+- if (!user)
+- return ERR_PTR(-ENOMEM);
++ ret = construct_get_dest_keyring(&dest_keyring);
++ if (ret)
++ goto error;
+
+- construct_get_dest_keyring(&dest_keyring);
++ user = key_user_lookup(current_fsuid(), current_user_ns());
++ if (!user) {
++ ret = -ENOMEM;
++ goto error_put_dest_keyring;
++ }
+
+ ret = construct_alloc_key(type, description, dest_keyring, flags, user,
+ &key);
+@@ -472,7 +499,7 @@ static struct key *construct_key_and_lin
+ } else if (ret == -EINPROGRESS) {
+ ret = 0;
+ } else {
+- goto couldnt_alloc_key;
++ goto error_put_dest_keyring;
+ }
+
+ key_put(dest_keyring);
+@@ -482,8 +509,9 @@ static struct key *construct_key_and_lin
+ construction_failed:
+ key_negate_and_link(key, key_negative_timeout, NULL, NULL);
+ key_put(key);
+-couldnt_alloc_key:
++error_put_dest_keyring:
+ key_put(dest_keyring);
++error:
+ kleave(" = %d", ret);
+ return ERR_PTR(ret);
+ }
diff --git a/debian/patches/bugfix/all/usb-core-prevent-malicious-bnuminterfaces-overflow.patch b/debian/patches/bugfix/all/usb-core-prevent-malicious-bnuminterfaces-overflow.patch
new file mode 100644
index 0000000..48498c5
--- /dev/null
+++ b/debian/patches/bugfix/all/usb-core-prevent-malicious-bnuminterfaces-overflow.patch
@@ -0,0 +1,46 @@
+From: Alan Stern <stern at rowland.harvard.edu>
+Date: Tue, 12 Dec 2017 14:25:13 -0500
+Subject: USB: core: prevent malicious bNumInterfaces overflow
+Origin: https://git.kernel.org/linus/48a4ff1c7bb5a32d2e396b03132d20d552c0eca7
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-17558
+
+A malicious USB device with crafted descriptors can cause the kernel
+to access unallocated memory by setting the bNumInterfaces value too
+high in a configuration descriptor. Although the value is adjusted
+during parsing, this adjustment is skipped in one of the error return
+paths.
+
+This patch prevents the problem by setting bNumInterfaces to 0
+initially. The existing code already sets it to the proper value
+after parsing is complete.
+
+Signed-off-by: Alan Stern <stern at rowland.harvard.edu>
+Reported-by: Andrey Konovalov <andreyknvl at google.com>
+CC: <stable at vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/usb/core/config.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 9e0c680f0922..0a80b5991773 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -521,6 +521,9 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ unsigned iad_num = 0;
+
+ memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
++ nintf = nintf_orig = config->desc.bNumInterfaces;
++ config->desc.bNumInterfaces = 0; // Adjusted later
++
+ if (config->desc.bDescriptorType != USB_DT_CONFIG ||
+ config->desc.bLength < USB_DT_CONFIG_SIZE ||
+ config->desc.bLength > size) {
+@@ -534,7 +537,6 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ buffer += config->desc.bLength;
+ size -= config->desc.bLength;
+
+- nintf = nintf_orig = config->desc.bNumInterfaces;
+ if (nintf > USB_MAXINTERFACES) {
+ dev_warn(ddev, "config %d has too many interfaces: %d, "
+ "using maximum allowed: %d\n",
diff --git a/debian/patches/bugfix/x86/kvm-fix-stack-out-of-bounds-read-in-write_mmio.patch b/debian/patches/bugfix/x86/kvm-fix-stack-out-of-bounds-read-in-write_mmio.patch
new file mode 100644
index 0000000..4fdf289
--- /dev/null
+++ b/debian/patches/bugfix/x86/kvm-fix-stack-out-of-bounds-read-in-write_mmio.patch
@@ -0,0 +1,132 @@
+From: Wanpeng Li <wanpeng.li at hotmail.com>
+Date: Thu, 14 Dec 2017 17:40:50 -0800
+Subject: KVM: Fix stack-out-of-bounds read in write_mmio
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://git.kernel.org/pub/scm/virt/kvm/kvm.git/commit?id=e39d200fa5bf5b94a0948db0dae44c1b73b84a56
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-17741
+
+Reported by syzkaller:
+
+ BUG: KASAN: stack-out-of-bounds in write_mmio+0x11e/0x270 [kvm]
+ Read of size 8 at addr ffff8803259df7f8 by task syz-executor/32298
+
+ CPU: 6 PID: 32298 Comm: syz-executor Tainted: G OE 4.15.0-rc2+ #18
+ Hardware name: LENOVO ThinkCentre M8500t-N000/SHARKBAY, BIOS FBKTC1AUS 02/16/2016
+ Call Trace:
+ dump_stack+0xab/0xe1
+ print_address_description+0x6b/0x290
+ kasan_report+0x28a/0x370
+ write_mmio+0x11e/0x270 [kvm]
+ emulator_read_write_onepage+0x311/0x600 [kvm]
+ emulator_read_write+0xef/0x240 [kvm]
+ emulator_fix_hypercall+0x105/0x150 [kvm]
+ em_hypercall+0x2b/0x80 [kvm]
+ x86_emulate_insn+0x2b1/0x1640 [kvm]
+ x86_emulate_instruction+0x39a/0xb90 [kvm]
+ handle_exception+0x1b4/0x4d0 [kvm_intel]
+ vcpu_enter_guest+0x15a0/0x2640 [kvm]
+ kvm_arch_vcpu_ioctl_run+0x549/0x7d0 [kvm]
+ kvm_vcpu_ioctl+0x479/0x880 [kvm]
+ do_vfs_ioctl+0x142/0x9a0
+ SyS_ioctl+0x74/0x80
+ entry_SYSCALL_64_fastpath+0x23/0x9a
+
+The path of patched vmmcall will patch 3 bytes opcode 0F 01 C1(vmcall)
+to the guest memory, however, write_mmio tracepoint always prints 8 bytes
+through *(u64 *)val since kvm splits the mmio access into 8 bytes. This
+leaks 5 bytes from the kernel stack (CVE-2017-17741). This patch fixes
+it by just accessing the bytes which we operate on.
+
+Before patch:
+
+syz-executor-5567 [007] .... 51370.561696: kvm_mmio: mmio write len 3 gpa 0x10 val 0x1ffff10077c1010f
+
+After patch:
+
+syz-executor-13416 [002] .... 51302.299573: kvm_mmio: mmio write len 3 gpa 0x10 val 0xc1010f
+
+Reported-by: Dmitry Vyukov <dvyukov at google.com>
+Reviewed-by: Darren Kenny <darren.kenny at oracle.com>
+Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
+Tested-by: Marc Zyngier <marc.zyngier at arm.com>
+Cc: Paolo Bonzini <pbonzini at redhat.com>
+Cc: Radim Krčmář <rkrcmar at redhat.com>
+Cc: Marc Zyngier <marc.zyngier at arm.com>
+Cc: Christoffer Dall <christoffer.dall at linaro.org>
+Signed-off-by: Wanpeng Li <wanpeng.li at hotmail.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+[bwh: Backported to 3.2:
+ - Drop ARM changes
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ arch/x86/kvm/x86.c | 8 ++++----
+ include/trace/events/kvm.h | 7 +++++--
+ 2 files changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 4baab231292f..7e6094b0308b 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3920,7 +3920,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
+ !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
+ && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+ break;
+- trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
++ trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, v);
+ handled += n;
+ addr += n;
+ len -= n;
+@@ -4152,7 +4152,7 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
+ if (vcpu->mmio_read_completed) {
+ memcpy(val, vcpu->mmio_data, bytes);
+ trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
+- vcpu->mmio_phys_addr, *(u64 *)val);
++ vcpu->mmio_phys_addr, val);
+ vcpu->mmio_read_completed = 0;
+ return 1;
+ }
+@@ -4174,14 +4174,14 @@ static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+
+ static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
+ {
+- trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
++ trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, val);
+ return vcpu_mmio_write(vcpu, gpa, bytes, val);
+ }
+
+ static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes)
+ {
+- trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
++ trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, NULL);
+ return X86EMUL_IO_NEEDED;
+ }
+
+diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
+index 46e3cd8e197a..215a904f5e41 100644
+--- a/include/trace/events/kvm.h
++++ b/include/trace/events/kvm.h
+@@ -152,7 +152,7 @@ TRACE_EVENT(kvm_ack_irq,
+ { KVM_TRACE_MMIO_WRITE, "write" }
+
+ TRACE_EVENT(kvm_mmio,
+- TP_PROTO(int type, int len, u64 gpa, u64 val),
++ TP_PROTO(int type, int len, u64 gpa, void *val),
+ TP_ARGS(type, len, gpa, val),
+
+ TP_STRUCT__entry(
+@@ -166,7 +166,10 @@ TRACE_EVENT(kvm_mmio,
+ __entry->type = type;
+ __entry->len = len;
+ __entry->gpa = gpa;
+- __entry->val = val;
++ __entry->val = 0;
++ if (val)
++ memcpy(&__entry->val, val,
++ min_t(u32, sizeof(__entry->val), len));
+ ),
+
+ TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx",
diff --git a/debian/patches/series b/debian/patches/series
index ea79657..518815e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1163,5 +1163,10 @@ bugfix/all/kpti/kaiser-disabled-on-xen-pv.patch
bugfix/all/kpti/x86-kaiser-move-feature-detection-up.patch
bugfix/all/kpti/kpti-rename-to-page_table_isolation.patch
bugfix/all/kpti/kpti-report-when-enabled.patch
+bugfix/all/usb-core-prevent-malicious-bnuminterfaces-overflow.patch
+bugfix/x86/kvm-fix-stack-out-of-bounds-read-in-write_mmio.patch
+bugfix/all/crypto-salsa20-fix-blkcipher_walk-API-usage.patch
+bugfix/all/keys-add-missing-permission-check-for-request_key-de.patch
+bugfix/all/crypto-hmac-require-that-the-underlying-hash-algorit.patch
# ABI maintenance
--
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