Commit 2e6d3045 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'remove-ksys-mount-dup' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/linux

Pull ksys_mount() and ksys_dup() removal from Dominik Brodowski:
 "This small series replaces all in-kernel calls to the
  userspace-focused ksys_mount() and ksys_dup() with calls to
  kernel-centric functions:

  For each replacement of ksys_mount() with do_mount(), one needs to
  verify that the first and third parameter (char *dev_name, char *type)
  are strings allocated in kernelspace and that the fifth parameter
  (void *data) is either NULL or refers to a full page (only occurence
  in init/do_mounts.c::do_mount_root()). The second and fourth
  parameters (char *dir_name, unsigned long flags) are passed by
  ksys_mount() to do_mount() unchanged, and therefore do not require
  particular care.

  Moreover, instead of pretending to be userspace, the opening of
  /dev/console as stdin/stdout/stderr can be implemented using in-kernel
  functions as well. Thereby, ksys_dup() can be removed for good"

[ This doesn't get rid of the special "kernel init runs with KERNEL_DS"
  case, but it at least removes _some_ of the users of "treat kernel
  pointers as user pointers for our magical init sequence".

  One day we'll hopefully be rid of it all, and can initialize our
  init_thread addr_limit to USER_DS.    - Linus ]

* 'remove-ksys-mount-dup' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/linux:
  fs: remove ksys_dup()
  init: unify opening /dev/console as stdin/stdout/stderr
  init: use do_mount() instead of ksys_mount()
  initrd: use do_mount() instead of ksys_mount()
  devtmpfs: use do_mount() instead of ksys_mount()
parents 510c9788 8243186f
...@@ -359,7 +359,7 @@ static int handle_remove(const char *nodename, struct device *dev) ...@@ -359,7 +359,7 @@ static int handle_remove(const char *nodename, struct device *dev)
* If configured, or requested by the commandline, devtmpfs will be * If configured, or requested by the commandline, devtmpfs will be
* auto-mounted after the kernel mounted the root filesystem. * auto-mounted after the kernel mounted the root filesystem.
*/ */
int devtmpfs_mount(const char *mntdir) int devtmpfs_mount(void)
{ {
int err; int err;
...@@ -369,7 +369,7 @@ int devtmpfs_mount(const char *mntdir) ...@@ -369,7 +369,7 @@ int devtmpfs_mount(const char *mntdir)
if (!thread) if (!thread)
return 0; return 0;
err = ksys_mount("devtmpfs", mntdir, "devtmpfs", MS_SILENT, NULL); err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
if (err) if (err)
printk(KERN_INFO "devtmpfs: error mounting %i\n", err); printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
else else
...@@ -394,7 +394,7 @@ static int devtmpfsd(void *p) ...@@ -394,7 +394,7 @@ static int devtmpfsd(void *p)
*err = ksys_unshare(CLONE_NEWNS); *err = ksys_unshare(CLONE_NEWNS);
if (*err) if (*err)
goto out; goto out;
*err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); *err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
if (*err) if (*err)
goto out; goto out;
ksys_chdir("/.."); /* will traverse into overmounted root */ ksys_chdir("/.."); /* will traverse into overmounted root */
......
...@@ -960,7 +960,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd) ...@@ -960,7 +960,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
return ksys_dup3(oldfd, newfd, 0); return ksys_dup3(oldfd, newfd, 0);
} }
int ksys_dup(unsigned int fildes) SYSCALL_DEFINE1(dup, unsigned int, fildes)
{ {
int ret = -EBADF; int ret = -EBADF;
struct file *file = fget_raw(fildes); struct file *file = fget_raw(fildes);
...@@ -975,11 +975,6 @@ int ksys_dup(unsigned int fildes) ...@@ -975,11 +975,6 @@ int ksys_dup(unsigned int fildes)
return ret; return ret;
} }
SYSCALL_DEFINE1(dup, unsigned int, fildes)
{
return ksys_dup(fildes);
}
int f_dupfd(unsigned int from, struct file *file, unsigned flags) int f_dupfd(unsigned int from, struct file *file, unsigned flags)
{ {
int err; int err;
......
...@@ -3325,8 +3325,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name) ...@@ -3325,8 +3325,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name)
} }
EXPORT_SYMBOL(mount_subtree); EXPORT_SYMBOL(mount_subtree);
int ksys_mount(const char __user *dev_name, const char __user *dir_name, SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
const char __user *type, unsigned long flags, void __user *data) char __user *, type, unsigned long, flags, void __user *, data)
{ {
int ret; int ret;
char *kernel_type; char *kernel_type;
...@@ -3359,12 +3359,6 @@ int ksys_mount(const char __user *dev_name, const char __user *dir_name, ...@@ -3359,12 +3359,6 @@ int ksys_mount(const char __user *dev_name, const char __user *dir_name,
return ret; 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);
}
/* /*
* Create a kernel mount representation for a new, prepared superblock * Create a kernel mount representation for a new, prepared superblock
* (specified by fs_fd) and attach to an open_tree-like file descriptor. * (specified by fs_fd) and attach to an open_tree-like file descriptor.
......
...@@ -1666,11 +1666,11 @@ extern bool kill_device(struct device *dev); ...@@ -1666,11 +1666,11 @@ extern bool kill_device(struct device *dev);
#ifdef CONFIG_DEVTMPFS #ifdef CONFIG_DEVTMPFS
extern int devtmpfs_create_node(struct device *dev); extern int devtmpfs_create_node(struct device *dev);
extern int devtmpfs_delete_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 #else
static inline int devtmpfs_create_node(struct device *dev) { return 0; } 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_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 #endif
/* drivers/base/power/shutdown.c */ /* drivers/base/power/shutdown.c */
......
...@@ -28,3 +28,5 @@ extern unsigned int real_root_dev; ...@@ -28,3 +28,5 @@ extern unsigned int real_root_dev;
extern char __initramfs_start[]; extern char __initramfs_start[];
extern unsigned long __initramfs_size; extern unsigned long __initramfs_size;
void console_on_rootfs(void);
...@@ -1231,10 +1231,7 @@ asmlinkage long sys_ni_syscall(void); ...@@ -1231,10 +1231,7 @@ asmlinkage long sys_ni_syscall(void);
* the ksys_xyzyyz() functions prototyped below. * the ksys_xyzyyz() functions prototyped below.
*/ */
int ksys_mount(const char __user *dev_name, const char __user *dir_name,
const char __user *type, unsigned long flags, void __user *data);
int ksys_umount(char __user *name, int flags); int ksys_umount(char __user *name, int flags);
int ksys_dup(unsigned int fildes);
int ksys_chroot(const char __user *filename); int ksys_chroot(const char __user *filename);
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
int ksys_chdir(const char __user *filename); int ksys_chdir(const char __user *filename);
......
...@@ -387,12 +387,25 @@ static void __init get_fs_names(char *page) ...@@ -387,12 +387,25 @@ static void __init get_fs_names(char *page)
*s = '\0'; *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; struct super_block *s;
int err = ksys_mount(name, "/root", fs, flags, data); char *data_page;
if (err) struct page *p;
return err; 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"); ksys_chdir("/root");
s = current->fs->pwd.dentry->d_sb; s = current->fs->pwd.dentry->d_sb;
...@@ -402,7 +415,10 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) ...@@ -402,7 +415,10 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
s->s_type->name, s->s_type->name,
sb_rdonly(s) ? " readonly" : "", sb_rdonly(s) ? " readonly" : "",
MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
return 0;
out:
put_page(p);
return ret;
} }
void __init mount_block_root(char *name, int flags) void __init mount_block_root(char *name, int flags)
...@@ -670,8 +686,8 @@ void __init prepare_namespace(void) ...@@ -670,8 +686,8 @@ void __init prepare_namespace(void)
mount_root(); mount_root();
out: out:
devtmpfs_mount("dev"); devtmpfs_mount();
ksys_mount(".", "/", NULL, MS_MOVE, NULL); do_mount(".", "/", NULL, MS_MOVE, NULL);
ksys_chroot("."); ksys_chroot(".");
} }
......
...@@ -48,13 +48,10 @@ early_param("initrd", early_initrd); ...@@ -48,13 +48,10 @@ early_param("initrd", early_initrd);
static int init_linuxrc(struct subprocess_info *info, struct cred *new) static int init_linuxrc(struct subprocess_info *info, struct cred *new)
{ {
ksys_unshare(CLONE_FS | CLONE_FILES); ksys_unshare(CLONE_FS | CLONE_FILES);
/* stdin/stdout/stderr for /linuxrc */ console_on_rootfs();
ksys_open("/dev/console", O_RDWR, 0);
ksys_dup(0);
ksys_dup(0);
/* move initrd over / and chdir/chroot in initrd root */ /* move initrd over / and chdir/chroot in initrd root */
ksys_chdir("/root"); ksys_chdir("/root");
ksys_mount(".", "/", NULL, MS_MOVE, NULL); do_mount(".", "/", NULL, MS_MOVE, NULL);
ksys_chroot("."); ksys_chroot(".");
ksys_setsid(); ksys_setsid();
return 0; return 0;
...@@ -89,7 +86,7 @@ static void __init handle_initrd(void) ...@@ -89,7 +86,7 @@ static void __init handle_initrd(void)
current->flags &= ~PF_FREEZER_SKIP; current->flags &= ~PF_FREEZER_SKIP;
/* move initrd to rootfs' /old */ /* 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 */ /* switch root and cwd back to / of rootfs */
ksys_chroot(".."); ksys_chroot("..");
...@@ -103,7 +100,7 @@ static void __init handle_initrd(void) ...@@ -103,7 +100,7 @@ static void __init handle_initrd(void)
mount_root(); mount_root();
printk(KERN_NOTICE "Trying to move old root to /initrd ... "); 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) if (!error)
printk("okay\n"); printk("okay\n");
else { else {
......
...@@ -93,6 +93,7 @@ ...@@ -93,6 +93,7 @@
#include <linux/rodata_test.h> #include <linux/rodata_test.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/mem_encrypt.h> #include <linux/mem_encrypt.h>
#include <linux/file.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/bugs.h> #include <asm/bugs.h>
...@@ -1155,6 +1156,30 @@ static int __ref kernel_init(void *unused) ...@@ -1155,6 +1156,30 @@ static int __ref kernel_init(void *unused)
"See Linux Documentation/admin-guide/init.rst for guidance."); "See Linux Documentation/admin-guide/init.rst for guidance.");
} }
void console_on_rootfs(void)
{
struct file *file;
unsigned int i;
/* Open /dev/console in kernelspace, this should never fail */
file = filp_open("/dev/console", O_RDWR, 0);
if (!file)
goto err_out;
/* create stdin/stdout/stderr, this should never fail */
for (i = 0; i < 3; i++) {
if (f_dupfd(i, file, 0) != i)
goto err_out;
}
return;
err_out:
/* no panic -- this might not be fatal */
pr_err("Warning: unable to open an initial console.\n");
return;
}
static noinline void __init kernel_init_freeable(void) static noinline void __init kernel_init_freeable(void)
{ {
/* /*
...@@ -1190,12 +1215,8 @@ static noinline void __init kernel_init_freeable(void) ...@@ -1190,12 +1215,8 @@ static noinline void __init kernel_init_freeable(void)
do_basic_setup(); do_basic_setup();
/* Open the /dev/console on the rootfs, this should never fail */ console_on_rootfs();
if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
pr_err("Warning: unable to open an initial console.\n");
(void) ksys_dup(0);
(void) ksys_dup(0);
/* /*
* check if there is an early userspace init. If yes, let it do all * check if there is an early userspace init. If yes, let it do all
* the work * the work
......
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