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()
This commit is contained in:
Linus Torvalds 2019-12-15 11:36:12 -08:00
commit 2e6d304515
9 changed files with 63 additions and 41 deletions

View File

@ -359,7 +359,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;
@ -369,7 +369,7 @@ int devtmpfs_mount(const char *mntdir)
if (!thread)
return 0;
err = ksys_mount("devtmpfs", 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
@ -394,7 +394,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 */

View File

@ -960,7 +960,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
return ksys_dup3(oldfd, newfd, 0);
}
int ksys_dup(unsigned int fildes)
SYSCALL_DEFINE1(dup, unsigned int, fildes)
{
int ret = -EBADF;
struct file *file = fget_raw(fildes);
@ -975,11 +975,6 @@ int ksys_dup(unsigned int fildes)
return ret;
}
SYSCALL_DEFINE1(dup, unsigned int, fildes)
{
return ksys_dup(fildes);
}
int f_dupfd(unsigned int from, struct file *file, unsigned flags)
{
int err;

View File

@ -3325,8 +3325,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name)
}
EXPORT_SYMBOL(mount_subtree);
int ksys_mount(const char __user *dev_name, const char __user *dir_name,
const 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;
@ -3359,12 +3359,6 @@ out_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);
}
/*
* Create a kernel mount representation for a new, prepared superblock
* (specified by fs_fd) and attach to an open_tree-like file descriptor.

View File

@ -1666,11 +1666,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 */

View File

@ -28,3 +28,5 @@ extern unsigned int real_root_dev;
extern char __initramfs_start[];
extern unsigned long __initramfs_size;
void console_on_rootfs(void);

View File

@ -1231,10 +1231,7 @@ asmlinkage long sys_ni_syscall(void);
* 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_dup(unsigned int fildes);
int ksys_chroot(const char __user *filename);
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
int ksys_chdir(const char __user *filename);

View File

@ -387,12 +387,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;
@ -402,7 +415,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)
@ -670,8 +686,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(".");
}

View File

@ -48,13 +48,10 @@ early_param("initrd", early_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;
@ -89,7 +86,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("..");
@ -103,7 +100,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 {

View File

@ -93,6 +93,7 @@
#include <linux/rodata_test.h>
#include <linux/jump_label.h>
#include <linux/mem_encrypt.h>
#include <linux/file.h>
#include <asm/io.h>
#include <asm/bugs.h>
@ -1155,6 +1156,30 @@ static int __ref kernel_init(void *unused)
"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)
{
/*
@ -1190,12 +1215,8 @@ static noinline void __init kernel_init_freeable(void)
do_basic_setup();
/* 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