Skip to content

Commit a801695

Browse files
committed
Merge branch 'work.init' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "Followups to nodev root stuff from this merge window" * 'work.init' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: init: don't panic if mount_nodev_root failed init/do_mounts.c: Harden split_fs_names() against buffer overflow
2 parents e61b2ad + 40c8ee6 commit a801695

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

init/do_mounts.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -338,20 +338,19 @@ __setup("rootflags=", root_data_setup);
338338
__setup("rootfstype=", fs_names_setup);
339339
__setup("rootdelay=", root_delay_setup);
340340

341-
static int __init split_fs_names(char *page, char *names)
341+
/* This can return zero length strings. Caller should check */
342+
static int __init split_fs_names(char *page, size_t size, char *names)
342343
{
343-
int count = 0;
344+
int count = 1;
344345
char *p = page;
345346

346-
strcpy(p, root_fs_names);
347+
strlcpy(p, root_fs_names, size);
347348
while (*p++) {
348-
if (p[-1] == ',')
349+
if (p[-1] == ',') {
349350
p[-1] = '\0';
351+
count++;
352+
}
350353
}
351-
*p = '\0';
352-
353-
for (p = page; *p; p += strlen(p)+1)
354-
count++;
355354

356355
return count;
357356
}
@@ -404,12 +403,16 @@ void __init mount_block_root(char *name, int flags)
404403
scnprintf(b, BDEVNAME_SIZE, "unknown-block(%u,%u)",
405404
MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
406405
if (root_fs_names)
407-
num_fs = split_fs_names(fs_names, root_fs_names);
406+
num_fs = split_fs_names(fs_names, PAGE_SIZE, root_fs_names);
408407
else
409408
num_fs = list_bdev_fs_names(fs_names, PAGE_SIZE);
410409
retry:
411410
for (i = 0, p = fs_names; i < num_fs; i++, p += strlen(p)+1) {
412-
int err = do_mount_root(name, p, flags, root_mount_data);
411+
int err;
412+
413+
if (!*p)
414+
continue;
415+
err = do_mount_root(name, p, flags, root_mount_data);
413416
switch (err) {
414417
case 0:
415418
goto out;
@@ -543,19 +546,18 @@ static int __init mount_nodev_root(void)
543546
fs_names = (void *)__get_free_page(GFP_KERNEL);
544547
if (!fs_names)
545548
return -EINVAL;
546-
num_fs = split_fs_names(fs_names, root_fs_names);
549+
num_fs = split_fs_names(fs_names, PAGE_SIZE, root_fs_names);
547550

548551
for (i = 0, fstype = fs_names; i < num_fs;
549552
i++, fstype += strlen(fstype) + 1) {
553+
if (!*fstype)
554+
continue;
550555
if (!fs_is_nodev(fstype))
551556
continue;
552557
err = do_mount_root(root_device_name, fstype, root_mountflags,
553558
root_mount_data);
554559
if (!err)
555560
break;
556-
if (err != -EACCES && err != -EINVAL)
557-
panic("VFS: Unable to mount root \"%s\" (%s), err=%d\n",
558-
root_device_name, fstype, err);
559561
}
560562

561563
free_page((unsigned long)fs_names);

0 commit comments

Comments
 (0)