[linux] 03/04: rxrpc: Fix several cases where a padded len isn't checked in ticket decode (CVE-2017-7482)
debian-kernel at lists.debian.org
debian-kernel at lists.debian.org
Thu Jul 27 20:27:19 UTC 2017
This is an automated email from the git hooks/post-receive script.
carnil pushed a commit to branch jessie-security
in repository linux.
commit 8a86ffc5d60bc580d528389b57cd63792353144a
Author: Salvatore Bonaccorso <carnil at debian.org>
Date: Thu Jul 27 22:10:26 2017 +0200
rxrpc: Fix several cases where a padded len isn't checked in ticket decode (CVE-2017-7482)
---
debian/changelog | 2 +
...everal-cases-where-a-padded-len-isn-t-che.patch | 207 +++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 210 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index e0c29f9..a1d92cb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -4,6 +4,8 @@ linux (3.16.43-2+deb8u3) UNRELEASED; urgency=medium
freeing (CVE-2014-9940)
* [x86] drm/vmwgfx: limit the number of mip levels in
vmw_gb_surface_define_ioctl() (CVE-2017-7346)
+ * rxrpc: Fix several cases where a padded len isn't checked in ticket decode
+ (CVE-2017-7482)
-- Salvatore Bonaccorso <carnil at debian.org> Thu, 27 Jul 2017 22:02:24 +0200
diff --git a/debian/patches/bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch b/debian/patches/bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
new file mode 100644
index 0000000..2b01c55
--- /dev/null
+++ b/debian/patches/bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
@@ -0,0 +1,207 @@
+From: David Howells <dhowells at redhat.com>
+Date: Thu, 15 Jun 2017 00:12:24 +0100
+Subject: rxrpc: Fix several cases where a padded len isn't checked in ticket
+ decode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://git.kernel.org/linus/5f2f97656ada8d811d3c1bef503ced266fcd53a0
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-7482
+
+This fixes CVE-2017-7482.
+
+When a kerberos 5 ticket is being decoded so that it can be loaded into an
+rxrpc-type key, there are several places in which the length of a
+variable-length field is checked to make sure that it's not going to
+overrun the available data - but the data is padded to the nearest
+four-byte boundary and the code doesn't check for this extra. This could
+lead to the size-remaining variable wrapping and the data pointer going
+over the end of the buffer.
+
+Fix this by making the various variable-length data checks use the padded
+length.
+
+Reported-by: 石磊 <shilei-c at 360.cn>
+Signed-off-by: David Howells <dhowells at redhat.com>
+Reviewed-by: Marc Dionne <marc.c.dionne at auristor.com>
+Reviewed-by: Dan Carpenter <dan.carpenter at oracle.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+[bwh: Backported to 3.16: adjust filename, context]
+---
+ net/rxrpc/ar-key.c | 64 +++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 34 insertions(+), 30 deletions(-)
+
+diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
+index 0ad080790a32..99d5a5ff812e 100644
+--- a/net/rxrpc/ar-key.c
++++ b/net/rxrpc/ar-key.c
+@@ -213,7 +213,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
+ unsigned int *_toklen)
+ {
+ const __be32 *xdr = *_xdr;
+- unsigned int toklen = *_toklen, n_parts, loop, tmp;
++ unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen;
+
+ /* there must be at least one name, and at least #names+1 length
+ * words */
+@@ -243,16 +243,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
+ toklen -= 4;
+ if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
+ return -EINVAL;
+- if (tmp > toklen)
++ paddedlen = (tmp + 3) & ~3;
++ if (paddedlen > toklen)
+ return -EINVAL;
+ princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
+ if (!princ->name_parts[loop])
+ return -ENOMEM;
+ memcpy(princ->name_parts[loop], xdr, tmp);
+ princ->name_parts[loop][tmp] = 0;
+- tmp = (tmp + 3) & ~3;
+- toklen -= tmp;
+- xdr += tmp >> 2;
++ toklen -= paddedlen;
++ xdr += paddedlen >> 2;
+ }
+
+ if (toklen < 4)
+@@ -261,16 +261,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
+ toklen -= 4;
+ if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
+ return -EINVAL;
+- if (tmp > toklen)
++ paddedlen = (tmp + 3) & ~3;
++ if (paddedlen > toklen)
+ return -EINVAL;
+ princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
+ if (!princ->realm)
+ return -ENOMEM;
+ memcpy(princ->realm, xdr, tmp);
+ princ->realm[tmp] = 0;
+- tmp = (tmp + 3) & ~3;
+- toklen -= tmp;
+- xdr += tmp >> 2;
++ toklen -= paddedlen;
++ xdr += paddedlen >> 2;
+
+ _debug("%s/...@%s", princ->name_parts[0], princ->realm);
+
+@@ -289,7 +289,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
+ unsigned int *_toklen)
+ {
+ const __be32 *xdr = *_xdr;
+- unsigned int toklen = *_toklen, len;
++ unsigned int toklen = *_toklen, len, paddedlen;
+
+ /* there must be at least one tag and one length word */
+ if (toklen <= 8)
+@@ -303,15 +303,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
+ toklen -= 8;
+ if (len > max_data_size)
+ return -EINVAL;
++ paddedlen = (len + 3) & ~3;
++ if (paddedlen > toklen)
++ return -EINVAL;
+ td->data_len = len;
+
+ if (len > 0) {
+ td->data = kmemdup(xdr, len, GFP_KERNEL);
+ if (!td->data)
+ return -ENOMEM;
+- len = (len + 3) & ~3;
+- toklen -= len;
+- xdr += len >> 2;
++ toklen -= paddedlen;
++ xdr += paddedlen >> 2;
+ }
+
+ _debug("tag %x len %x", td->tag, td->data_len);
+@@ -383,7 +385,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
+ const __be32 **_xdr, unsigned int *_toklen)
+ {
+ const __be32 *xdr = *_xdr;
+- unsigned int toklen = *_toklen, len;
++ unsigned int toklen = *_toklen, len, paddedlen;
+
+ /* there must be at least one length word */
+ if (toklen <= 4)
+@@ -395,6 +397,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
+ toklen -= 4;
+ if (len > AFSTOKEN_K5_TIX_MAX)
+ return -EINVAL;
++ paddedlen = (len + 3) & ~3;
++ if (paddedlen > toklen)
++ return -EINVAL;
+ *_tktlen = len;
+
+ _debug("ticket len %u", len);
+@@ -403,9 +408,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
+ *_ticket = kmemdup(xdr, len, GFP_KERNEL);
+ if (!*_ticket)
+ return -ENOMEM;
+- len = (len + 3) & ~3;
+- toklen -= len;
+- xdr += len >> 2;
++ toklen -= paddedlen;
++ xdr += paddedlen >> 2;
+ }
+
+ *_xdr = xdr;
+@@ -549,7 +553,7 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal
+ {
+ const __be32 *xdr = data, *token;
+ const char *cp;
+- unsigned int len, tmp, loop, ntoken, toklen, sec_ix;
++ unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
+ int ret;
+
+ _enter(",{%x,%x,%x,%x},%zu",
+@@ -574,22 +578,21 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal
+ if (len < 1 || len > AFSTOKEN_CELL_MAX)
+ goto not_xdr;
+ datalen -= 4;
+- tmp = (len + 3) & ~3;
+- if (tmp > datalen)
++ paddedlen = (len + 3) & ~3;
++ if (paddedlen > datalen)
+ goto not_xdr;
+
+ cp = (const char *) xdr;
+ for (loop = 0; loop < len; loop++)
+ if (!isprint(cp[loop]))
+ goto not_xdr;
+- if (len < tmp)
+- for (; loop < tmp; loop++)
+- if (cp[loop])
+- goto not_xdr;
++ for (; loop < paddedlen; loop++)
++ if (cp[loop])
++ goto not_xdr;
+ _debug("cellname: [%u/%u] '%*.*s'",
+- len, tmp, len, len, (const char *) xdr);
+- datalen -= tmp;
+- xdr += tmp >> 2;
++ len, paddedlen, len, len, (const char *) xdr);
++ datalen -= paddedlen;
++ xdr += paddedlen >> 2;
+
+ /* get the token count */
+ if (datalen < 12)
+@@ -610,10 +613,11 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal
+ sec_ix = ntohl(*xdr);
+ datalen -= 4;
+ _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
+- if (toklen < 20 || toklen > datalen)
++ paddedlen = (toklen + 3) & ~3;
++ if (toklen < 20 || toklen > datalen || paddedlen > datalen)
+ goto not_xdr;
+- datalen -= (toklen + 3) & ~3;
+- xdr += (toklen + 3) >> 2;
++ datalen -= paddedlen;
++ xdr += paddedlen >> 2;
+
+ } while (--loop > 0);
+
+--
+2.11.0
+
diff --git a/debian/patches/series b/debian/patches/series
index f3df05f..55a0722 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -714,6 +714,7 @@ bugfix/all/mm-larger-stack-guard-gap-between-vmas.patch
bugfix/all/mm-fix-new-crash-in-unmapped_area_topdown.patch
bugfix/all/regulator-core-Fix-regualtor_ena_gpio_free-not-to-ac.patch
bugfix/x86/drm-vmwgfx-limit-the-number-of-mip-levels-in-vmw_gb_.patch
+bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
# Fix ABI changes
debian/of-fix-abi-changes.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