From: Greg Kroah-Hartman Date: Mon, 26 Jun 2017 12:44:51 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v3.18.59~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3d303e33b85e6fbf736f67e688fd0bd596ebb6cd;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch --- diff --git a/queue-3.18/rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch b/queue-3.18/rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch new file mode 100644 index 00000000000..3c4c29dad7d --- /dev/null +++ b/queue-3.18/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/ar-key.c | 64 ++++++++++++++++++++++++++++------------------------- + 1 file changed, 34 insertions(+), 30 deletions(-) + +--- a/net/rxrpc/ar-key.c ++++ b/net/rxrpc/ar-key.c +@@ -215,7 +215,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 */ +@@ -245,16 +245,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) +@@ -263,16 +263,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); + +@@ -291,7 +291,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) +@@ -305,15 +305,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); +@@ -385,7 +387,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) +@@ -397,6 +399,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); +@@ -405,9 +410,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; +@@ -550,7 +554,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; + +@@ -576,22 +580,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) +@@ -612,10 +615,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-3.18/series b/queue-3.18/series index aebae9786f2..29fdbc030e0 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -7,3 +7,4 @@ signal-only-reschedule-timers-on-signals-timers-have-sent.patch powerpc-kprobes-pause-function_graph-tracing-during-jprobes-handling.patch input-i8042-add-fujitsu-lifebook-ah544-to-notimeout-list.patch target-fix-kref-refcount-underflow-in-transport_cmd_finish_abort.patch +rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch