rxrpc: Fix several cases where a padded len isn't checked in ticket decode (CVE-2017-7482)
This commit is contained in:
parent
fe29debbce
commit
3aaf7fba55
|
@ -79,6 +79,10 @@ linux (4.11.7-1) UNRELEASED; urgency=medium
|
||||||
[ Vagrant Cascadian ]
|
[ Vagrant Cascadian ]
|
||||||
* [arm64] Enable support for Rockchip systems (Closes: #860976).
|
* [arm64] Enable support for Rockchip systems (Closes: #860976).
|
||||||
|
|
||||||
|
[ Salvatore Bonaccorso ]
|
||||||
|
* rxrpc: Fix several cases where a padded len isn't checked in ticket decode
|
||||||
|
(CVE-2017-7482)
|
||||||
|
|
||||||
-- Ben Hutchings <ben@decadent.org.uk> Tue, 20 Jun 2017 19:18:44 +0100
|
-- Ben Hutchings <ben@decadent.org.uk> Tue, 20 Jun 2017 19:18:44 +0100
|
||||||
|
|
||||||
linux (4.11.6-1) unstable; urgency=medium
|
linux (4.11.6-1) unstable; urgency=medium
|
||||||
|
|
206
debian/patches/bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
vendored
Normal file
206
debian/patches/bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
vendored
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
From: David Howells <dhowells@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@360.cn>
|
||||||
|
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||||
|
Reviewed-by: Marc Dionne <marc.c.dionne@auristor.com>
|
||||||
|
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||||
|
---
|
||||||
|
net/rxrpc/key.c | 64 ++++++++++++++++++++++++++++++---------------------------
|
||||||
|
1 file changed, 34 insertions(+), 30 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
|
||||||
|
index 0a4e28477ad9..54369225766e 100644
|
||||||
|
--- a/net/rxrpc/key.c
|
||||||
|
+++ b/net/rxrpc/key.c
|
||||||
|
@@ -217,7 +217,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 */
|
||||||
|
@@ -247,16 +247,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)
|
||||||
|
@@ -265,16 +265,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);
|
||||||
|
|
||||||
|
@@ -293,7 +293,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)
|
||||||
|
@@ -307,15 +307,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);
|
||||||
|
@@ -387,7 +389,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)
|
||||||
|
@@ -399,6 +401,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);
|
||||||
|
@@ -407,9 +412,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;
|
||||||
|
@@ -552,7 +556,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
|
||||||
|
{
|
||||||
|
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_preparsed_payload *prep)
|
||||||
|
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_preparsed_payload *prep)
|
||||||
|
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
|
||||||
|
|
|
@ -145,6 +145,7 @@ bugfix/all/tracing-Use-strlcpy-instead-of-strcpy-in-__trace_fin.patch
|
||||||
bugfix/all/sunrpc-refactor-svc_set_num_threads.patch
|
bugfix/all/sunrpc-refactor-svc_set_num_threads.patch
|
||||||
bugfix/all/nfsv4-fix-callback-server-shutdown.patch
|
bugfix/all/nfsv4-fix-callback-server-shutdown.patch
|
||||||
bugfix/all/nfsv4.x-callback-create-the-callback-service-through.patch
|
bugfix/all/nfsv4.x-callback-create-the-callback-service-through.patch
|
||||||
|
bugfix/all/rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
|
||||||
|
|
||||||
# Fix exported symbol versions
|
# Fix exported symbol versions
|
||||||
bugfix/sparc/revert-sparc-move-exports-to-definitions.patch
|
bugfix/sparc/revert-sparc-move-exports-to-definitions.patch
|
||||||
|
|
Loading…
Reference in New Issue