Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

get_rock_ridge_filename(): handle malformed NM entries

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@vger.kernel.org # 0.98pl6+ (yes, really)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 99d82582 6a480a78

+10 -3
+10 -3
fs/isofs/rock.c
··· 203 203 int retnamlen = 0; 204 204 int truncate = 0; 205 205 int ret = 0; 206 + char *p; 207 + int len; 206 208 207 209 if (!ISOFS_SB(inode->i_sb)->s_rock) 208 210 return 0; ··· 269 267 rr->u.NM.flags); 270 268 break; 271 269 } 272 - if ((strlen(retname) + rr->len - 5) >= 254) { 270 + len = rr->len - 5; 271 + if (retnamlen + len >= 254) { 273 272 truncate = 1; 274 273 break; 275 274 } 276 - strncat(retname, rr->u.NM.name, rr->len - 5); 277 - retnamlen += rr->len - 5; 275 + p = memchr(rr->u.NM.name, '\0', len); 276 + if (unlikely(p)) 277 + len = p - rr->u.NM.name; 278 + memcpy(retname + retnamlen, rr->u.NM.name, len); 279 + retnamlen += len; 280 + retname[retnamlen] = '\0'; 278 281 break; 279 282 case SIG('R', 'E'): 280 283 kfree(rs.buffer);