Skip to content

Commit 99d8258

Browse files
author
Al Viro
committed
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>
1 parent 6a480a7 commit 99d8258

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

Diff for: fs/isofs/rock.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ int get_rock_ridge_filename(struct iso_directory_record *de,
203203
int retnamlen = 0;
204204
int truncate = 0;
205205
int ret = 0;
206+
char *p;
207+
int len;
206208

207209
if (!ISOFS_SB(inode->i_sb)->s_rock)
208210
return 0;
@@ -267,12 +269,17 @@ int get_rock_ridge_filename(struct iso_directory_record *de,
267269
rr->u.NM.flags);
268270
break;
269271
}
270-
if ((strlen(retname) + rr->len - 5) >= 254) {
272+
len = rr->len - 5;
273+
if (retnamlen + len >= 254) {
271274
truncate = 1;
272275
break;
273276
}
274-
strncat(retname, rr->u.NM.name, rr->len - 5);
275-
retnamlen += rr->len - 5;
277+
p = memchr(rr->u.NM.name, '\0', len);
278+
if (unlikely(p))
279+
len = p - rr->u.NM.name;
280+
memcpy(retname + retnamlen, rr->u.NM.name, len);
281+
retnamlen += len;
282+
retname[retnamlen] = '\0';
276283
break;
277284
case SIG('R', 'E'):
278285
kfree(rs.buffer);

0 commit comments

Comments
 (0)