ACK: [CVE-2016-4913][precise, trusty, lts-utopic, vivid, wily] get_rock_ridge_filename(): handle malformed NM entries

Christopher Arges chris.j.arges at canonical.com
Thu May 26 12:52:33 UTC 2016


On Wed, May 25, 2016 at 04:22:38PM +0100, Luis Henriques wrote:
> From: Al Viro <viro at zeniv.linux.org.uk>
> 
> Payloads of NM entries are not supposed to contain NUL.  When we run
> into such, only the part prior to the first NUL goes into the
> concatenation (i.e. the directory entry name being encoded by a bunch
> of NM entries).  We do stop when the amount collected so far + the
> claimed amount in the current NM entry exceed 254.  So far, so good,
> but what we return as the total length is the sum of *claimed*
> sizes, not the actual amount collected.  And that can grow pretty
> large - not unlimited, since you'd need to put CE entries in
> between to be able to get more than the maximum that could be
> contained in one isofs directory entry / continuation chunk and
> we are stop once we'd encountered 32 CEs, but you can get about 8Kb
> easily.  And that's what will be passed to readdir callback as the
> name length.  8Kb __copy_to_user() from a buffer allocated by
> __get_free_page()
> 
> Cc: stable at vger.kernel.org # 0.98pl6+ (yes, really)
> Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
> (cherry picked from commit 99d825822eade8d827a1817357cbf3f889a552d6)
> CVE-2016-4913
> BugLink: https://bugs.launchpad.net/bugs/1583962
> Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
> ---
>  fs/isofs/rock.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
> index 17809499c752..e52a1ac168ef 100644
> --- a/fs/isofs/rock.c
> +++ b/fs/isofs/rock.c
> @@ -203,6 +203,8 @@ int get_rock_ridge_filename(struct iso_directory_record *de,
>  	int retnamlen = 0;
>  	int truncate = 0;
>  	int ret = 0;
> +	char *p;
> +	int len;
>  
>  	if (!ISOFS_SB(inode->i_sb)->s_rock)
>  		return 0;
> @@ -267,12 +269,17 @@ repeat:
>  					rr->u.NM.flags);
>  				break;
>  			}
> -			if ((strlen(retname) + rr->len - 5) >= 254) {
> +			len = rr->len - 5;
> +			if (retnamlen + len >= 254) {
>  				truncate = 1;
>  				break;
>  			}
> -			strncat(retname, rr->u.NM.name, rr->len - 5);
> -			retnamlen += rr->len - 5;
> +			p = memchr(rr->u.NM.name, '\0', len);
> +			if (unlikely(p))
> +				len = p - rr->u.NM.name;
> +			memcpy(retname + retnamlen, rr->u.NM.name, len);
> +			retnamlen += len;
> +			retname[retnamlen] = '\0';
>  			break;
>  		case SIG('R', 'E'):
>  			kfree(rs.buffer);
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team




More information about the kernel-team mailing list