Patch "rxrpc: Fix several cases where a padded len isn't checked in ticket decode" has been added to the 4.9-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
rxrpc: Fix several cases where a padded len isn't checked in ticket decode
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
5f2f97656ada8d811d3c1bef503ced266fcd53a0Mon Sep 17 00:00:00 2001
From: David Howells <[email protected]>
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 <[email protected]>
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.
--- net/rxrpc/key.c | 64 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 30 deletions(-)
net/rxrpc/key.c +34 -30
@@ -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 keyif (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 );
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/rxrpc-fix-several-cases-where-a-padded-len-isn-t-checked-in-ticket-decode.patch