diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index aaf5f416deb85be5a80ce04a61176b73efec541c..7aec727bb812956fd726b78a57bdb0c99f4a03c3 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -362,7 +362,7 @@ static int handle_remove(const char *nodename, struct device *dev) * If configured, or requested by the commandline, devtmpfs will be * auto-mounted after the kernel mounted the root filesystem. */ -int devtmpfs_mount(const char *mntdir) +int devtmpfs_mount(void) { int err; @@ -372,8 +372,7 @@ int devtmpfs_mount(const char *mntdir) if (!thread) return 0; - err = ksys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, - NULL); + err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL); if (err) printk(KERN_INFO "devtmpfs: error mounting %i\n", err); else @@ -398,7 +397,7 @@ static int devtmpfsd(void *p) *err = ksys_unshare(CLONE_NEWNS); if (*err) goto out; - *err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); + *err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); if (*err) goto out; ksys_chdir("/.."); /* will traverse into overmounted root */ diff --git a/fs/namespace.c b/fs/namespace.c index 48f675938c345761e1646f2386d56973cb8317b7..fb9746b62f82d82220b19434cff3c0e8ec726d4f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3165,8 +3165,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name) } EXPORT_SYMBOL(mount_subtree); -int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type, - unsigned long flags, void __user *data) +SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, + char __user *, type, unsigned long, flags, void __user *, data) { int ret; char *kernel_type; @@ -3199,12 +3199,6 @@ int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type, return ret; } -SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, - char __user *, type, unsigned long, flags, void __user *, data) -{ - return ksys_mount(dev_name, dir_name, type, flags, data); -} - /* * Move a mount from one place to another. * In combination with open_tree(OPEN_TREE_CLONE [| AT_RECURSIVE]) it can be diff --git a/include/linux/device.h b/include/linux/device.h index c86a40f6b7451421cfe2c8d01340bebe71fb33c5..9e4678fd99b28b017c32a3a70d74bda1082b095c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1340,11 +1340,11 @@ extern bool kill_device(struct device *dev); #ifdef CONFIG_DEVTMPFS extern int devtmpfs_create_node(struct device *dev); extern int devtmpfs_delete_node(struct device *dev); -extern int devtmpfs_mount(const char *mntdir); +extern int devtmpfs_mount(void); #else static inline int devtmpfs_create_node(struct device *dev) { return 0; } static inline int devtmpfs_delete_node(struct device *dev) { return 0; } -static inline int devtmpfs_mount(const char *mountpoint) { return 0; } +static inline int devtmpfs_mount(void) { return 0; } #endif /* drivers/base/power/shutdown.c */ diff --git a/include/linux/initrd.h b/include/linux/initrd.h index 84b423044088728feeccd7d1e468ac747f91cede..02625c850b7658d6f9713726ec3050ef14965a00 100644 --- a/include/linux/initrd.h +++ b/include/linux/initrd.h @@ -22,3 +22,5 @@ extern unsigned long initrd_start, initrd_end; extern void free_initrd_mem(unsigned long, unsigned long); extern unsigned int real_root_dev; + +void console_on_rootfs(void); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index ca6fa5e07866f960e35b479278dc297e90a2c592..a26f74036855523b08329e6611db88f9728200e5 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1142,8 +1142,6 @@ asmlinkage long sys_ni_syscall(void); * the ksys_xyzyyz() functions prototyped below. */ -int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type, - unsigned long flags, void __user *data); int ksys_umount(char __user *name, int flags); int ksys_dup(unsigned int fildes); int ksys_chroot(const char __user *filename); diff --git a/init/do_mounts.c b/init/do_mounts.c index e1c9afa9d8c9103fa1463a45a425c9468e4c1628..16a567f6862d53966d361638df85a37457775161 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -350,12 +350,25 @@ static void __init get_fs_names(char *page) *s = '\0'; } -static int __init do_mount_root(char *name, char *fs, int flags, void *data) +static int __init do_mount_root(const char *name, const char *fs, + const int flags, const void *data) { struct super_block *s; - int err = ksys_mount(name, "/root", fs, flags, data); - if (err) - return err; + char *data_page; + struct page *p; + int ret; + + /* do_mount() requires a full page as fifth argument */ + p = alloc_page(GFP_KERNEL); + if (!p) + return -ENOMEM; + + data_page = page_address(p); + strncpy(data_page, data, PAGE_SIZE - 1); + + ret = do_mount(name, "/root", fs, flags, data_page); + if (ret) + goto out; ksys_chdir("/root"); s = current->fs->pwd.dentry->d_sb; @@ -365,7 +378,10 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) s->s_type->name, sb_rdonly(s) ? " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); - return 0; + +out: + put_page(p); + return ret; } void __init mount_block_root(char *name, int flags) @@ -588,8 +604,8 @@ void __init prepare_namespace(void) mount_root(); out: - devtmpfs_mount("dev"); - ksys_mount(".", "/", NULL, MS_MOVE, NULL); + devtmpfs_mount(); + do_mount(".", "/", NULL, MS_MOVE, NULL); ksys_chroot("."); } diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index d1a5d885ce13eb566667b5d32de782c6c4694944..68ab321cf9ab674569715f3e88506f6724b17308 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -27,13 +27,10 @@ __setup("noinitrd", no_initrd); static int init_linuxrc(struct subprocess_info *info, struct cred *new) { ksys_unshare(CLONE_FS | CLONE_FILES); - /* stdin/stdout/stderr for /linuxrc */ - ksys_open("/dev/console", O_RDWR, 0); - ksys_dup(0); - ksys_dup(0); + console_on_rootfs(); /* move initrd over / and chdir/chroot in initrd root */ ksys_chdir("/root"); - ksys_mount(".", "/", NULL, MS_MOVE, NULL); + do_mount(".", "/", NULL, MS_MOVE, NULL); ksys_chroot("."); ksys_setsid(); return 0; @@ -71,7 +68,7 @@ static void __init handle_initrd(void) current->flags &= ~PF_FREEZER_SKIP; /* move initrd to rootfs' /old */ - ksys_mount("..", ".", NULL, MS_MOVE, NULL); + do_mount("..", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ ksys_chroot(".."); @@ -85,7 +82,7 @@ static void __init handle_initrd(void) mount_root(); printk(KERN_NOTICE "Trying to move old root to /initrd ... "); - error = ksys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); + error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); if (!error) printk("okay\n"); else { diff --git a/init/main.c b/init/main.c index c11aed805ef58cbcadf07ec643b7d80623e28679..35a42c105eb960c5db99128692051d47c1e95b94 100644 --- a/init/main.c +++ b/init/main.c @@ -1116,6 +1116,17 @@ static int __ref kernel_init(void *unused) "See Linux Documentation/admin-guide/init.rst for guidance."); } +void console_on_rootfs(void) +{ + /* Open the /dev/console as stdin, this should never fail */ + if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) + pr_err("Warning: unable to open an initial console.\n"); + + /* create stdout/stderr */ + (void) ksys_dup(0); + (void) ksys_dup(0); +} + static noinline void __init kernel_init_freeable(void) { /* @@ -1152,12 +1163,8 @@ static noinline void __init kernel_init_freeable(void) lockup_detector_init(); - /* Open the /dev/console on the rootfs, this should never fail */ - if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) - pr_err("Warning: unable to open an initial console.\n"); + console_on_rootfs(); - (void) ksys_dup(0); - (void) ksys_dup(0); /* * check if there is an early userspace init. If yes, let it do all * the work