Commit a801695f authored by Linus Torvalds's avatar Linus Torvalds

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
parents e61b2ad3 40c8ee67
...@@ -338,20 +338,19 @@ __setup("rootflags=", root_data_setup); ...@@ -338,20 +338,19 @@ __setup("rootflags=", root_data_setup);
__setup("rootfstype=", fs_names_setup); __setup("rootfstype=", fs_names_setup);
__setup("rootdelay=", root_delay_setup); __setup("rootdelay=", root_delay_setup);
static int __init split_fs_names(char *page, char *names) /* This can return zero length strings. Caller should check */
static int __init split_fs_names(char *page, size_t size, char *names)
{ {
int count = 0; int count = 1;
char *p = page; char *p = page;
strcpy(p, root_fs_names); strlcpy(p, root_fs_names, size);
while (*p++) { while (*p++) {
if (p[-1] == ',') if (p[-1] == ',') {
p[-1] = '\0'; p[-1] = '\0';
count++;
}
} }
*p = '\0';
for (p = page; *p; p += strlen(p)+1)
count++;
return count; return count;
} }
...@@ -404,12 +403,16 @@ void __init mount_block_root(char *name, int flags) ...@@ -404,12 +403,16 @@ void __init mount_block_root(char *name, int flags)
scnprintf(b, BDEVNAME_SIZE, "unknown-block(%u,%u)", scnprintf(b, BDEVNAME_SIZE, "unknown-block(%u,%u)",
MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
if (root_fs_names) if (root_fs_names)
num_fs = split_fs_names(fs_names, root_fs_names); num_fs = split_fs_names(fs_names, PAGE_SIZE, root_fs_names);
else else
num_fs = list_bdev_fs_names(fs_names, PAGE_SIZE); num_fs = list_bdev_fs_names(fs_names, PAGE_SIZE);
retry: retry:
for (i = 0, p = fs_names; i < num_fs; i++, p += strlen(p)+1) { for (i = 0, p = fs_names; i < num_fs; i++, p += strlen(p)+1) {
int err = do_mount_root(name, p, flags, root_mount_data); int err;
if (!*p)
continue;
err = do_mount_root(name, p, flags, root_mount_data);
switch (err) { switch (err) {
case 0: case 0:
goto out; goto out;
...@@ -543,19 +546,18 @@ static int __init mount_nodev_root(void) ...@@ -543,19 +546,18 @@ static int __init mount_nodev_root(void)
fs_names = (void *)__get_free_page(GFP_KERNEL); fs_names = (void *)__get_free_page(GFP_KERNEL);
if (!fs_names) if (!fs_names)
return -EINVAL; return -EINVAL;
num_fs = split_fs_names(fs_names, root_fs_names); num_fs = split_fs_names(fs_names, PAGE_SIZE, root_fs_names);
for (i = 0, fstype = fs_names; i < num_fs; for (i = 0, fstype = fs_names; i < num_fs;
i++, fstype += strlen(fstype) + 1) { i++, fstype += strlen(fstype) + 1) {
if (!*fstype)
continue;
if (!fs_is_nodev(fstype)) if (!fs_is_nodev(fstype))
continue; continue;
err = do_mount_root(root_device_name, fstype, root_mountflags, err = do_mount_root(root_device_name, fstype, root_mountflags,
root_mount_data); root_mount_data);
if (!err) if (!err)
break; break;
if (err != -EACCES && err != -EINVAL)
panic("VFS: Unable to mount root \"%s\" (%s), err=%d\n",
root_device_name, fstype, err);
} }
free_page((unsigned long)fs_names); free_page((unsigned long)fs_names);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment