From: Greg Kroah-Hartman Date: Mon, 26 Jun 2017 12:44:54 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v3.18.59~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e88181e57f8aa3ecde0f17c87d77332fc07d037b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch --- diff --git a/queue-4.11/rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch b/queue-4.11/rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch new file mode 100644 index 00000000000..bb7c2e06184 --- /dev/null +++ b/queue-4.11/rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch @@ -0,0 +1,205 @@ +From 5f2f97656ada8d811d3c1bef503ced266fcd53a0 Mon Sep 17 00:00:00 2001 +From: David Howells +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 + +From: David Howells + +commit 5f2f97656ada8d811d3c1bef503ced266fcd53a0 upstream. + +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: 石磊 +Signed-off-by: David Howells +Reviewed-by: Marc Dionne +Reviewed-by: Dan Carpenter +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/rxrpc/key.c | 64 +++++++++++++++++++++++++++++--------------------------- + 1 file changed, 34 insertions(+), 30 deletions(-) + +--- a/net/rxrpc/key.c ++++ b/net/rxrpc/key.c +@@ -217,7 +217,7 @@ static int rxrpc_krb5_decode_principal(s + 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 */ +@@ -247,16 +247,16 @@ static int rxrpc_krb5_decode_principal(s + 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) +@@ -265,16 +265,16 @@ static int rxrpc_krb5_decode_principal(s + 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); + +@@ -293,7 +293,7 @@ static int rxrpc_krb5_decode_tagged_data + 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) +@@ -307,15 +307,17 @@ static int rxrpc_krb5_decode_tagged_data + 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); +@@ -387,7 +389,7 @@ static int rxrpc_krb5_decode_ticket(u8 * + 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) +@@ -399,6 +401,9 @@ static int rxrpc_krb5_decode_ticket(u8 * + 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); +@@ -407,9 +412,8 @@ static int rxrpc_krb5_decode_ticket(u8 * + *_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; +@@ -552,7 +556,7 @@ static int rxrpc_preparse_xdr(struct key + { + const __be32 *xdr = prep->data, *token; + const char *cp; +- unsigned int len, tmp, loop, ntoken, toklen, sec_ix; ++ unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix; + size_t datalen = prep->datalen; + int ret; + +@@ -578,22 +582,21 @@ static int rxrpc_preparse_xdr(struct key + 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) +@@ -614,10 +617,11 @@ static int rxrpc_preparse_xdr(struct key + 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); + diff --git a/queue-4.11/series b/queue-4.11/series index cfd3129ed0d..cd6d0e6139c 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -48,3 +48,4 @@ drm-amdgpu-adjust-default-display-clock.patch drm-amdgpu-add-polaris12-did.patch acpi-scan-apply-default-enumeration-to-devices-with-acpi-drivers.patch acpi-scan-fix-enumeration-for-special-spi-and-i2c-devices.patch +rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch