Skip to content

Commit 2e6d304

Browse files
committed
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()
2 parents 510c978 + 8243186 commit 2e6d304

File tree

9 files changed

+63
-41
lines changed

9 files changed

+63
-41
lines changed

drivers/base/devtmpfs.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ static int handle_remove(const char *nodename, struct device *dev)
359359
* If configured, or requested by the commandline, devtmpfs will be
360360
* auto-mounted after the kernel mounted the root filesystem.
361361
*/
362-
int devtmpfs_mount(const char *mntdir)
362+
int devtmpfs_mount(void)
363363
{
364364
int err;
365365

@@ -369,7 +369,7 @@ int devtmpfs_mount(const char *mntdir)
369369
if (!thread)
370370
return 0;
371371

372-
err = ksys_mount("devtmpfs", mntdir, "devtmpfs", MS_SILENT, NULL);
372+
err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
373373
if (err)
374374
printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
375375
else
@@ -394,7 +394,7 @@ static int devtmpfsd(void *p)
394394
*err = ksys_unshare(CLONE_NEWNS);
395395
if (*err)
396396
goto out;
397-
*err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
397+
*err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
398398
if (*err)
399399
goto out;
400400
ksys_chdir("/.."); /* will traverse into overmounted root */

fs/file.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
960960
return ksys_dup3(oldfd, newfd, 0);
961961
}
962962

963-
int ksys_dup(unsigned int fildes)
963+
SYSCALL_DEFINE1(dup, unsigned int, fildes)
964964
{
965965
int ret = -EBADF;
966966
struct file *file = fget_raw(fildes);
@@ -975,11 +975,6 @@ int ksys_dup(unsigned int fildes)
975975
return ret;
976976
}
977977

978-
SYSCALL_DEFINE1(dup, unsigned int, fildes)
979-
{
980-
return ksys_dup(fildes);
981-
}
982-
983978
int f_dupfd(unsigned int from, struct file *file, unsigned flags)
984979
{
985980
int err;

fs/namespace.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3325,8 +3325,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name)
33253325
}
33263326
EXPORT_SYMBOL(mount_subtree);
33273327

3328-
int ksys_mount(const char __user *dev_name, const char __user *dir_name,
3329-
const char __user *type, unsigned long flags, void __user *data)
3328+
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
3329+
char __user *, type, unsigned long, flags, void __user *, data)
33303330
{
33313331
int ret;
33323332
char *kernel_type;
@@ -3359,12 +3359,6 @@ int ksys_mount(const char __user *dev_name, const char __user *dir_name,
33593359
return ret;
33603360
}
33613361

3362-
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
3363-
char __user *, type, unsigned long, flags, void __user *, data)
3364-
{
3365-
return ksys_mount(dev_name, dir_name, type, flags, data);
3366-
}
3367-
33683362
/*
33693363
* Create a kernel mount representation for a new, prepared superblock
33703364
* (specified by fs_fd) and attach to an open_tree-like file descriptor.

include/linux/device.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,11 +1666,11 @@ extern bool kill_device(struct device *dev);
16661666
#ifdef CONFIG_DEVTMPFS
16671667
extern int devtmpfs_create_node(struct device *dev);
16681668
extern int devtmpfs_delete_node(struct device *dev);
1669-
extern int devtmpfs_mount(const char *mntdir);
1669+
extern int devtmpfs_mount(void);
16701670
#else
16711671
static inline int devtmpfs_create_node(struct device *dev) { return 0; }
16721672
static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
1673-
static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
1673+
static inline int devtmpfs_mount(void) { return 0; }
16741674
#endif
16751675

16761676
/* drivers/base/power/shutdown.c */

include/linux/initrd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ extern unsigned int real_root_dev;
2828

2929
extern char __initramfs_start[];
3030
extern unsigned long __initramfs_size;
31+
32+
void console_on_rootfs(void);

include/linux/syscalls.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,10 +1231,7 @@ asmlinkage long sys_ni_syscall(void);
12311231
* the ksys_xyzyyz() functions prototyped below.
12321232
*/
12331233

1234-
int ksys_mount(const char __user *dev_name, const char __user *dir_name,
1235-
const char __user *type, unsigned long flags, void __user *data);
12361234
int ksys_umount(char __user *name, int flags);
1237-
int ksys_dup(unsigned int fildes);
12381235
int ksys_chroot(const char __user *filename);
12391236
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
12401237
int ksys_chdir(const char __user *filename);

init/do_mounts.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,25 @@ static void __init get_fs_names(char *page)
387387
*s = '\0';
388388
}
389389

390-
static int __init do_mount_root(char *name, char *fs, int flags, void *data)
390+
static int __init do_mount_root(const char *name, const char *fs,
391+
const int flags, const void *data)
391392
{
392393
struct super_block *s;
393-
int err = ksys_mount(name, "/root", fs, flags, data);
394-
if (err)
395-
return err;
394+
char *data_page;
395+
struct page *p;
396+
int ret;
397+
398+
/* do_mount() requires a full page as fifth argument */
399+
p = alloc_page(GFP_KERNEL);
400+
if (!p)
401+
return -ENOMEM;
402+
403+
data_page = page_address(p);
404+
strncpy(data_page, data, PAGE_SIZE - 1);
405+
406+
ret = do_mount(name, "/root", fs, flags, data_page);
407+
if (ret)
408+
goto out;
396409

397410
ksys_chdir("/root");
398411
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)
402415
s->s_type->name,
403416
sb_rdonly(s) ? " readonly" : "",
404417
MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
405-
return 0;
418+
419+
out:
420+
put_page(p);
421+
return ret;
406422
}
407423

408424
void __init mount_block_root(char *name, int flags)
@@ -670,8 +686,8 @@ void __init prepare_namespace(void)
670686

671687
mount_root();
672688
out:
673-
devtmpfs_mount("dev");
674-
ksys_mount(".", "/", NULL, MS_MOVE, NULL);
689+
devtmpfs_mount();
690+
do_mount(".", "/", NULL, MS_MOVE, NULL);
675691
ksys_chroot(".");
676692
}
677693

init/do_mounts_initrd.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,10 @@ early_param("initrd", early_initrd);
4848
static int init_linuxrc(struct subprocess_info *info, struct cred *new)
4949
{
5050
ksys_unshare(CLONE_FS | CLONE_FILES);
51-
/* stdin/stdout/stderr for /linuxrc */
52-
ksys_open("/dev/console", O_RDWR, 0);
53-
ksys_dup(0);
54-
ksys_dup(0);
51+
console_on_rootfs();
5552
/* move initrd over / and chdir/chroot in initrd root */
5653
ksys_chdir("/root");
57-
ksys_mount(".", "/", NULL, MS_MOVE, NULL);
54+
do_mount(".", "/", NULL, MS_MOVE, NULL);
5855
ksys_chroot(".");
5956
ksys_setsid();
6057
return 0;
@@ -89,7 +86,7 @@ static void __init handle_initrd(void)
8986
current->flags &= ~PF_FREEZER_SKIP;
9087

9188
/* move initrd to rootfs' /old */
92-
ksys_mount("..", ".", NULL, MS_MOVE, NULL);
89+
do_mount("..", ".", NULL, MS_MOVE, NULL);
9390
/* switch root and cwd back to / of rootfs */
9491
ksys_chroot("..");
9592

@@ -103,7 +100,7 @@ static void __init handle_initrd(void)
103100
mount_root();
104101

105102
printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
106-
error = ksys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
103+
error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
107104
if (!error)
108105
printk("okay\n");
109106
else {

init/main.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#include <linux/rodata_test.h>
9494
#include <linux/jump_label.h>
9595
#include <linux/mem_encrypt.h>
96+
#include <linux/file.h>
9697

9798
#include <asm/io.h>
9899
#include <asm/bugs.h>
@@ -1155,6 +1156,30 @@ static int __ref kernel_init(void *unused)
11551156
"See Linux Documentation/admin-guide/init.rst for guidance.");
11561157
}
11571158

1159+
void console_on_rootfs(void)
1160+
{
1161+
struct file *file;
1162+
unsigned int i;
1163+
1164+
/* Open /dev/console in kernelspace, this should never fail */
1165+
file = filp_open("/dev/console", O_RDWR, 0);
1166+
if (!file)
1167+
goto err_out;
1168+
1169+
/* create stdin/stdout/stderr, this should never fail */
1170+
for (i = 0; i < 3; i++) {
1171+
if (f_dupfd(i, file, 0) != i)
1172+
goto err_out;
1173+
}
1174+
1175+
return;
1176+
1177+
err_out:
1178+
/* no panic -- this might not be fatal */
1179+
pr_err("Warning: unable to open an initial console.\n");
1180+
return;
1181+
}
1182+
11581183
static noinline void __init kernel_init_freeable(void)
11591184
{
11601185
/*
@@ -1190,12 +1215,8 @@ static noinline void __init kernel_init_freeable(void)
11901215

11911216
do_basic_setup();
11921217

1193-
/* Open the /dev/console on the rootfs, this should never fail */
1194-
if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
1195-
pr_err("Warning: unable to open an initial console.\n");
1218+
console_on_rootfs();
11961219

1197-
(void) ksys_dup(0);
1198-
(void) ksys_dup(0);
11991220
/*
12001221
* check if there is an early userspace init. If yes, let it do all
12011222
* the work

0 commit comments

Comments
 (0)