linux-api.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* add file system helpers that take kernel pointers for the init code v2
@ 2020-07-21 16:27 Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 01/24] fs: refactor do_mount Christoph Hellwig
                   ` (23 more replies)
  0 siblings, 24 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:27 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Hi Al and Linus,

currently a lot of the file system calls in the early in code (and the
devtmpfs kthread) rely on the implicit set_fs(KERNEL_DS) during boot.
This is one of the few last remaining places we need to deal with to kill
off set_fs entirely, so this series adds new helpers that take kernel
pointers.  These helpers are in init/ and marked __init and thus will
be discarded after bootup.  A few also need to be duplicated in devtmpfs,
though unfortunately.

The series sits on top of my previous

  "decruft the early init / initrd / initramfs code v2"

series.


Git tree:

    git://git.infradead.org/users/hch/misc.git init_path

Gitweb:

    http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/init_path


Changes since v1:
 - avoid most core VFS changes
 - renamed the functions and move them to init/ and devtmpfs
 - drop a bunch of cleanups that can be submitted independently now


Diffstat:

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 01/24] fs: refactor do_mount
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
@ 2020-07-21 16:27 ` Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 02/24] fs: refactor ksys_umount Christoph Hellwig
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:27 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Factor out a path_mount helper that takes a struct path * instead of the
actual file name.  This will allow to convert the init and devtmpfs code
to properly mount based on a kernel pointer instead of relying on the
implicit set_fs(KERNEL_DS) during early init.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/namespace.c | 67 ++++++++++++++++++++++++++------------------------
 1 file changed, 35 insertions(+), 32 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index f30ed401cc6d7a..6f8234f74bed90 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3115,12 +3115,11 @@ char *copy_mount_string(const void __user *data)
  * Therefore, if this magic number is present, it carries no information
  * and must be discarded.
  */
-long do_mount(const char *dev_name, const char __user *dir_name,
+static int path_mount(const char *dev_name, struct path *path,
 		const char *type_page, unsigned long flags, void *data_page)
 {
-	struct path path;
 	unsigned int mnt_flags = 0, sb_flags;
-	int retval = 0;
+	int ret;
 
 	/* Discard magic */
 	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
@@ -3133,19 +3132,13 @@ long do_mount(const char *dev_name, const char __user *dir_name,
 	if (flags & MS_NOUSER)
 		return -EINVAL;
 
-	/* ... and get the mountpoint */
-	retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
-	if (retval)
-		return retval;
-
-	retval = security_sb_mount(dev_name, &path,
-				   type_page, flags, data_page);
-	if (!retval && !may_mount())
-		retval = -EPERM;
-	if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
-		retval = -EPERM;
-	if (retval)
-		goto dput_out;
+	ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
+	if (ret)
+		return ret;
+	if (!may_mount())
+		return -EPERM;
+	if ((flags & SB_MANDLOCK) && !may_mandlock())
+		return -EPERM;
 
 	/* Default to relatime unless overriden */
 	if (!(flags & MS_NOATIME))
@@ -3172,7 +3165,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
 	    ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
 		       MS_STRICTATIME)) == 0)) {
 		mnt_flags &= ~MNT_ATIME_MASK;
-		mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
+		mnt_flags |= path->mnt->mnt_flags & MNT_ATIME_MASK;
 	}
 
 	sb_flags = flags & (SB_RDONLY |
@@ -3185,22 +3178,32 @@ long do_mount(const char *dev_name, const char __user *dir_name,
 			    SB_I_VERSION);
 
 	if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
-		retval = do_reconfigure_mnt(&path, mnt_flags);
-	else if (flags & MS_REMOUNT)
-		retval = do_remount(&path, flags, sb_flags, mnt_flags,
-				    data_page);
-	else if (flags & MS_BIND)
-		retval = do_loopback(&path, dev_name, flags & MS_REC);
-	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
-		retval = do_change_type(&path, flags);
-	else if (flags & MS_MOVE)
-		retval = do_move_mount_old(&path, dev_name);
-	else
-		retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
-				      dev_name, data_page);
-dput_out:
+		return do_reconfigure_mnt(path, mnt_flags);
+	if (flags & MS_REMOUNT)
+		return do_remount(path, flags, sb_flags, mnt_flags, data_page);
+	if (flags & MS_BIND)
+		return do_loopback(path, dev_name, flags & MS_REC);
+	if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+		return do_change_type(path, flags);
+	if (flags & MS_MOVE)
+		return do_move_mount_old(path, dev_name);
+
+	return do_new_mount(path, type_page, sb_flags, mnt_flags, dev_name,
+			    data_page);
+}
+
+long do_mount(const char *dev_name, const char __user *dir_name,
+		const char *type_page, unsigned long flags, void *data_page)
+{
+	struct path path;
+	int ret;
+
+	ret = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
+	if (ret)
+		return ret;
+	ret = path_mount(dev_name, &path, type_page, flags, data_page);
 	path_put(&path);
-	return retval;
+	return ret;
 }
 
 static struct ucounts *inc_mnt_namespaces(struct user_namespace *ns)
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 02/24] fs: refactor ksys_umount
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 01/24] fs: refactor do_mount Christoph Hellwig
@ 2020-07-21 16:27 ` Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 03/24] fs: push the getname from do_rmdir into the callers Christoph Hellwig
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:27 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Factor out a path_umount helper that takes a struct path * instead of the
actual file name.  This will allow to convert the init and devtmpfs code
to properly mount based on a kernel pointer instead of relying on the
implicit set_fs(KERNEL_DS) during early init.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/namespace.c | 40 ++++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index 6f8234f74bed90..43834b59eff6c3 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1706,36 +1706,19 @@ static inline bool may_mandlock(void)
 }
 #endif
 
-/*
- * Now umount can handle mount points as well as block devices.
- * This is important for filesystems which use unnamed block devices.
- *
- * We now support a flag for forced unmount like the other 'big iron'
- * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
- */
-
-int ksys_umount(char __user *name, int flags)
+static int path_umount(struct path *path, int flags)
 {
-	struct path path;
 	struct mount *mnt;
 	int retval;
-	int lookup_flags = LOOKUP_MOUNTPOINT;
 
 	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
 		return -EINVAL;
-
 	if (!may_mount())
 		return -EPERM;
 
-	if (!(flags & UMOUNT_NOFOLLOW))
-		lookup_flags |= LOOKUP_FOLLOW;
-
-	retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
-	if (retval)
-		goto out;
-	mnt = real_mount(path.mnt);
+	mnt = real_mount(path->mnt);
 	retval = -EINVAL;
-	if (path.dentry != path.mnt->mnt_root)
+	if (path->dentry != path->mnt->mnt_root)
 		goto dput_and_out;
 	if (!check_mnt(mnt))
 		goto dput_and_out;
@@ -1748,12 +1731,25 @@ int ksys_umount(char __user *name, int flags)
 	retval = do_umount(mnt, flags);
 dput_and_out:
 	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
-	dput(path.dentry);
+	dput(path->dentry);
 	mntput_no_expire(mnt);
-out:
 	return retval;
 }
 
+int ksys_umount(char __user *name, int flags)
+{
+	int lookup_flags = LOOKUP_MOUNTPOINT;
+	struct path path;
+	int ret;
+
+	if (!(flags & UMOUNT_NOFOLLOW))
+		lookup_flags |= LOOKUP_FOLLOW;
+	ret = user_path_at(AT_FDCWD, name, lookup_flags, &path);
+	if (ret)
+		return ret;
+	return path_umount(&path, flags);
+}
+
 SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 {
 	return ksys_umount(name, flags);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 03/24] fs: push the getname from do_rmdir into the callers
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 01/24] fs: refactor do_mount Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 02/24] fs: refactor ksys_umount Christoph Hellwig
@ 2020-07-21 16:27 ` Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 04/24] devtmpfs: open code do_mount Christoph Hellwig
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:27 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

This mirrors do_unlinkat and will make life a little easier for
the init code to reuse the whole function with a kernel filename.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h            |  2 +-
 fs/namei.c               | 10 ++++------
 include/linux/syscalls.h |  4 ++--
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 9b863a7bd70892..e903d5aae139a2 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -65,7 +65,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 long do_mknodat(int dfd, const char __user *filename, umode_t mode,
 		unsigned int dev);
 long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
-long do_rmdir(int dfd, const char __user *pathname);
+long do_rmdir(int dfd, struct filename *name);
 long do_unlinkat(int dfd, struct filename *name);
 long do_symlinkat(const char __user *oldname, int newdfd,
 		  const char __user *newname);
diff --git a/fs/namei.c b/fs/namei.c
index 72d4219c93acb7..d75a6039ae3966 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3720,17 +3720,16 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 }
 EXPORT_SYMBOL(vfs_rmdir);
 
-long do_rmdir(int dfd, const char __user *pathname)
+long do_rmdir(int dfd, struct filename *name)
 {
 	int error = 0;
-	struct filename *name;
 	struct dentry *dentry;
 	struct path path;
 	struct qstr last;
 	int type;
 	unsigned int lookup_flags = 0;
 retry:
-	name = filename_parentat(dfd, getname(pathname), lookup_flags,
+	name = filename_parentat(dfd, name, lookup_flags,
 				&path, &last, &type);
 	if (IS_ERR(name))
 		return PTR_ERR(name);
@@ -3781,7 +3780,7 @@ long do_rmdir(int dfd, const char __user *pathname)
 
 SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
 {
-	return do_rmdir(AT_FDCWD, pathname);
+	return do_rmdir(AT_FDCWD, getname(pathname));
 }
 
 /**
@@ -3926,8 +3925,7 @@ SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
 		return -EINVAL;
 
 	if (flag & AT_REMOVEDIR)
-		return do_rmdir(dfd, pathname);
-
+		return do_rmdir(dfd, getname(pathname));
 	return do_unlinkat(dfd, getname(pathname));
 }
 
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 5b0f1fca4cfb9d..e43816198e6001 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1281,11 +1281,11 @@ static inline long ksys_unlink(const char __user *pathname)
 	return do_unlinkat(AT_FDCWD, getname(pathname));
 }
 
-extern long do_rmdir(int dfd, const char __user *pathname);
+long do_rmdir(int dfd, struct filename *name);
 
 static inline long ksys_rmdir(const char __user *pathname)
 {
-	return do_rmdir(AT_FDCWD, pathname);
+	return do_rmdir(AT_FDCWD, getname(pathname));
 }
 
 extern long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 04/24] devtmpfs: open code do_mount
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (2 preceding siblings ...)
  2020-07-21 16:27 ` [PATCH 03/24] fs: push the getname from do_rmdir into the callers Christoph Hellwig
@ 2020-07-21 16:27 ` Christoph Hellwig
  2020-07-21 16:27 ` [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot Christoph Hellwig
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:27 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Replace do_umount with an open coded version that takes the proper
kernel pointer instead of relying on the implicit set_fs(KERNEL_DS)
during early init.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/base/devtmpfs.c | 17 +++++++++++++++--
 fs/namespace.c          |  2 +-
 include/linux/mount.h   |  3 +++
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index c9017e0584c003..5e8d677ee783bc 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -345,6 +345,19 @@ static int handle_remove(const char *nodename, struct device *dev)
 	return err;
 }
 
+static int devtmpfs_do_mount(const char __user *dir_name)
+{
+	struct path p;
+	int ret;
+
+	ret = kern_path(dir_name, LOOKUP_FOLLOW, &p);
+	if (ret)
+		return ret;
+	ret = path_mount("devtmpfs", &p, "devtmpfs", MS_SILENT, NULL);
+	path_put(&p);
+	return ret;
+}
+
 /*
  * If configured, or requested by the commandline, devtmpfs will be
  * auto-mounted after the kernel mounted the root filesystem.
@@ -359,7 +372,7 @@ int __init devtmpfs_mount(void)
 	if (!thread)
 		return 0;
 
-	err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
+	err = devtmpfs_do_mount("dev");
 	if (err)
 		printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
 	else
@@ -385,7 +398,7 @@ static int devtmpfs_setup(void *p)
 	err = ksys_unshare(CLONE_NEWNS);
 	if (err)
 		goto out;
-	err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
+	err = devtmpfs_do_mount("/");
 	if (err)
 		goto out;
 	ksys_chdir("/.."); /* will traverse into overmounted root */
diff --git a/fs/namespace.c b/fs/namespace.c
index 43834b59eff6c3..2c4d7592097485 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3111,7 +3111,7 @@ char *copy_mount_string(const void __user *data)
  * Therefore, if this magic number is present, it carries no information
  * and must be discarded.
  */
-static int path_mount(const char *dev_name, struct path *path,
+int path_mount(const char *dev_name, struct path *path,
 		const char *type_page, unsigned long flags, void *data_page)
 {
 	unsigned int mnt_flags = 0, sb_flags;
diff --git a/include/linux/mount.h b/include/linux/mount.h
index de657bd211fa64..bf9896f86a48f4 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -113,4 +113,7 @@ extern bool path_is_mountpoint(const struct path *path);
 
 extern void kern_unmount_array(struct vfsmount *mnt[], unsigned int num);
 
+int path_mount(const char *dev_name, struct path *path, const char *type_page,
+		unsigned long flags, void *data_page);
+
 #endif /* _LINUX_MOUNT_H */
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (3 preceding siblings ...)
  2020-07-21 16:27 ` [PATCH 04/24] devtmpfs: open code do_mount Christoph Hellwig
@ 2020-07-21 16:27 ` Christoph Hellwig
  2020-07-21 16:49   ` Linus Torvalds
  2020-07-21 16:28 ` [PATCH 06/24] md: open code vfs_stat in md_setup_drive Christoph Hellwig
                   ` (18 subsequent siblings)
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:27 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

devtmpfs is the only non-early init caller of ksys_chdir and ksys_chroot
with kernel pointers.  Just open code the two operations which only
really need a single path lookup anyway in devtmpfs_setup instead.
The open coded verson doesn't need any of the stale dentry revalidation
logic from the full blown version as those can't happen on tmpfs and
ramfs.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/base/devtmpfs.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 5e8d677ee783bc..f798d3976b4052 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
+#include <linux/fs_struct.h>
 #include <uapi/linux/mount.h>
 #include "base.h"
 
@@ -393,6 +394,7 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid,
 
 static int devtmpfs_setup(void *p)
 {
+	struct path path;
 	int err;
 
 	err = ksys_unshare(CLONE_NEWNS);
@@ -401,8 +403,16 @@ static int devtmpfs_setup(void *p)
 	err = devtmpfs_do_mount("/");
 	if (err)
 		goto out;
-	ksys_chdir("/.."); /* will traverse into overmounted root */
-	ksys_chroot(".");
+
+	/* traverse into overmounted root and then chroot to it */
+	if (!kern_path("/..", LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path) &&
+	    !inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR) &&
+	    ns_capable(current_user_ns(), CAP_SYS_CHROOT) &&
+	    !security_path_chroot(&path)) {
+		set_fs_pwd(current->fs, &path);
+		set_fs_root(current->fs, &path);
+	}
+	path_put(&path);
 out:
 	*(int *)p = err;
 	complete(&setup_done);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 06/24] md: open code vfs_stat in md_setup_drive
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (4 preceding siblings ...)
  2020-07-21 16:27 ` [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:55   ` Al Viro
  2020-07-21 16:28 ` [PATCH 07/24] init: initialize ramdisk_execute_command at compile time Christoph Hellwig
                   ` (17 subsequent siblings)
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Instead of passing a kernel pointer to vfs_stat by relying on the
implicit set_fs(KERNEL_DS) in md_setup_drive, just open code the
trivial getattr, and use the opportunity to move a little bit more
code from the caller into the new helper.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/md/md-autodetect.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c
index 14b6e86814c061..1e8f1df257a112 100644
--- a/drivers/md/md-autodetect.c
+++ b/drivers/md/md-autodetect.c
@@ -8,6 +8,7 @@
 #include <linux/raid/detect.h>
 #include <linux/raid/md_u.h>
 #include <linux/raid/md_p.h>
+#include <linux/namei.h>
 #include "md.h"
 
 /*
@@ -119,6 +120,23 @@ static int __init md_setup(char *str)
 	return 1;
 }
 
+static void __init md_lookup_dev(const char *devname, dev_t *dev)
+{
+	struct kstat stat;
+	struct path path;
+	char filename[64];
+
+	if (strncmp(devname, "/dev/", 5) == 0)
+		devname += 5;
+	snprintf(filename, 63, "/dev/%s", devname);
+
+	if (!kern_path(filename, LOOKUP_FOLLOW, &path) &&
+	    !vfs_getattr(&path, &stat, STATX_BASIC_STATS, AT_NO_AUTOMOUNT) &&
+	    S_ISBLK(stat.mode))
+		*dev = new_decode_dev(stat.rdev);
+	path_put(&path);
+}
+
 static void __init md_setup_drive(struct md_setup_args *args)
 {
 	char *devname = args->device_names;
@@ -138,21 +156,14 @@ static void __init md_setup_drive(struct md_setup_args *args)
 	}
 
 	for (i = 0; i < MD_SB_DISKS && devname != NULL; i++) {
-		struct kstat stat;
-		char *p;
-		char comp_name[64];
 		dev_t dev;
+		char *p;
 
 		p = strchr(devname, ',');
 		if (p)
 			*p++ = 0;
-
 		dev = name_to_dev_t(devname);
-		if (strncmp(devname, "/dev/", 5) == 0)
-			devname += 5;
-		snprintf(comp_name, 63, "/dev/%s", devname);
-		if (vfs_stat(comp_name, &stat) == 0 && S_ISBLK(stat.mode))
-			dev = new_decode_dev(stat.rdev);
+		md_lookup_dev(devname, &dev);
 		if (!dev) {
 			pr_warn("md: Unknown device name: %s\n", devname);
 			break;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 07/24] init: initialize ramdisk_execute_command at compile time
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (5 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 06/24] md: open code vfs_stat in md_setup_drive Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 08/24] init: move the prepare_namespace prototype to init/do_mounts.h Christoph Hellwig
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Set ramdisk_execute_command to "/init" at compile time.  The command
line can still override it, but this saves a few instructions and
removes a NULL check.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 init/main.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/init/main.c b/init/main.c
index db0621dfbb0468..c2c9143db96795 100644
--- a/init/main.c
+++ b/init/main.c
@@ -154,7 +154,7 @@ static bool initargs_found;
 #endif
 
 static char *execute_command;
-static char *ramdisk_execute_command;
+static char *ramdisk_execute_command = "/init";
 
 /*
  * Used to generate warnings if static_key manipulation functions are used
@@ -1514,10 +1514,6 @@ static noinline void __init kernel_init_freeable(void)
 	 * check if there is an early userspace init.  If yes, let it do all
 	 * the work
 	 */
-
-	if (!ramdisk_execute_command)
-		ramdisk_execute_command = "/init";
-
 	if (ksys_access((const char __user *)
 			ramdisk_execute_command, 0) != 0) {
 		ramdisk_execute_command = NULL;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 08/24] init: move the prepare_namespace prototype to init/do_mounts.h
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (6 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 07/24] init: initialize ramdisk_execute_command at compile time Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 09/24] init: mark create_dev as __init Christoph Hellwig
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

No need to have this prototype in a global header included by
every driver.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 include/linux/init.h | 1 -
 init/do_mounts.h     | 1 +
 init/main.c          | 2 ++
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 212fc9e2f691a1..7de54fcad39431 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -147,7 +147,6 @@ extern unsigned int reset_devices;
 
 /* used by init/main.c */
 void setup_arch(char **);
-void prepare_namespace(void);
 void __init init_rootfs(void);
 extern struct file_system_type rootfs_fs_type;
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index c855b3f0e06d19..853da3cc4a3586 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -11,6 +11,7 @@
 
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
+void prepare_namespace(void);
 extern int root_mountflags;
 
 static inline int create_dev(char *name, dev_t dev)
diff --git a/init/main.c b/init/main.c
index c2c9143db96795..b952e4cd685af4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -103,6 +103,8 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 
+#include "do_mounts.h"
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/initcall.h>
 
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 09/24] init: mark create_dev as __init
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (7 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 08/24] init: move the prepare_namespace prototype to init/do_mounts.h Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 10/24] init: open code ksys_umount in handle_initrd Christoph Hellwig
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

The helper is only used for the early init code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 init/do_mounts.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/init/do_mounts.h b/init/do_mounts.h
index 853da3cc4a3586..15d256658a3093 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -14,7 +14,7 @@ void  mount_root(void);
 void prepare_namespace(void);
 extern int root_mountflags;
 
-static inline int create_dev(char *name, dev_t dev)
+static inline __init int create_dev(char *name, dev_t dev)
 {
 	ksys_unlink(name);
 	return ksys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 10/24] init: open code ksys_umount in handle_initrd
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (8 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 09/24] init: mark create_dev as __init Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 11/24] init: open code do_utimes in do_utime Christoph Hellwig
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Replace ksys_umount with an open coded version that takes the proper
kernel pointer instead of relying on the implicit set_fs(KERNEL_DS)
during early init.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/namespace.c           | 4 ++--
 include/linux/mount.h    | 1 +
 include/linux/syscalls.h | 1 -
 init/do_mounts_initrd.c  | 6 +++++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index 2c4d7592097485..a7301790abb211 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1706,7 +1706,7 @@ static inline bool may_mandlock(void)
 }
 #endif
 
-static int path_umount(struct path *path, int flags)
+int path_umount(struct path *path, int flags)
 {
 	struct mount *mnt;
 	int retval;
@@ -1736,7 +1736,7 @@ static int path_umount(struct path *path, int flags)
 	return retval;
 }
 
-int ksys_umount(char __user *name, int flags)
+static int ksys_umount(char __user *name, int flags)
 {
 	int lookup_flags = LOOKUP_MOUNTPOINT;
 	struct path path;
diff --git a/include/linux/mount.h b/include/linux/mount.h
index bf9896f86a48f4..e868b1ac7af90c 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -115,5 +115,6 @@ extern void kern_unmount_array(struct vfsmount *mnt[], unsigned int num);
 
 int path_mount(const char *dev_name, struct path *path, const char *type_page,
 		unsigned long flags, void *data_page);
+int path_umount(struct path *path, int flags);
 
 #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index e43816198e6001..1a4f5d8ee7044b 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1236,7 +1236,6 @@ asmlinkage long sys_ni_syscall(void);
  * the ksys_xyzyyz() functions prototyped below.
  */
 
-int ksys_umount(char __user *name, int flags);
 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);
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index e08669187d63be..3fabbc82513506 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -9,6 +9,7 @@
 #include <linux/freezer.h>
 #include <linux/kmod.h>
 #include <uapi/linux/mount.h>
+#include <linux/namei.h>
 
 #include "do_mounts.h"
 
@@ -117,12 +118,15 @@ static void __init handle_initrd(void)
 	if (!error)
 		printk("okay\n");
 	else {
+		struct path path;
+
 		if (error == -ENOENT)
 			printk("/initrd does not exist. Ignored.\n");
 		else
 			printk("failed\n");
 		printk(KERN_NOTICE "Unmounting old root\n");
-		ksys_umount("/old", MNT_DETACH);
+		if (!kern_path("/old", LOOKUP_MOUNTPOINT, &path))
+			path_umount(&path, MNT_DETACH);
 	}
 }
 
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 11/24] init: open code do_utimes in do_utime
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (9 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 10/24] init: open code ksys_umount in handle_initrd Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 12/24] init: add an init_mount helper Christoph Hellwig
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Open code the trivial utimes case in a version that takes proper kernel
pointers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 init/initramfs.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/init/initramfs.c b/init/initramfs.c
index 3823d15e5d2619..6135b55286fc35 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -104,13 +104,20 @@ static void __init free_hash(void)
 static long __init do_utime(char *filename, time64_t mtime)
 {
 	struct timespec64 t[2];
+	struct path path;
+	int error;
 
 	t[0].tv_sec = mtime;
 	t[0].tv_nsec = 0;
 	t[1].tv_sec = mtime;
 	t[1].tv_nsec = 0;
 
-	return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW);
+	error = kern_path(filename, 0, &path);
+	if (error)
+		return error;
+	error = vfs_utimes(&path, t);
+	path_put(&path);
+	return error;
 }
 
 static __initdata LIST_HEAD(dir_list);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 12/24] init: add an init_mount helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (10 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 11/24] init: open code do_utimes in do_utime Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:58   ` Al Viro
  2020-07-21 16:28 ` [PATCH 13/24] init: add an init_unlink helper Christoph Hellwig
                   ` (11 subsequent siblings)
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Like do_mount, but takes a kernel pointer for the destination path.
Switch over the mounts in the init code and devtmpfs to it, which
just happen to work due to the implicit set_fs(KERNEL_DS) during early
init right now.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 init/Makefile           |  2 +-
 init/do_mounts.c        |  8 ++++----
 init/do_mounts.h        |  3 +++
 init/do_mounts_initrd.c |  6 +++---
 init/fs.c               | 20 ++++++++++++++++++++
 5 files changed, 31 insertions(+), 8 deletions(-)
 create mode 100644 init/fs.c

diff --git a/init/Makefile b/init/Makefile
index 6bc37f64b3617c..7d4b57d3cf7eac 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -5,7 +5,7 @@
 
 ccflags-y := -fno-function-sections -fno-data-sections
 
-obj-y                          := main.o version.o mounts.o
+obj-y                          := main.o version.o fs.o mounts.o
 ifneq ($(CONFIG_BLK_DEV_INITRD),y)
 obj-y                          += noinitramfs.o
 else
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 4f4ceb35805503..4812e21d149cab 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -395,16 +395,16 @@ static int __init do_mount_root(const char *name, const char *fs,
 	int ret;
 
 	if (data) {
-		/* do_mount() requires a full page as fifth argument */
+		/* init_mount() requires a full page as fifth argument */
 		p = alloc_page(GFP_KERNEL);
 		if (!p)
 			return -ENOMEM;
 		data_page = page_address(p);
-		/* zero-pad. do_mount() will make sure it's terminated */
+		/* zero-pad. init_mount() will make sure it's terminated */
 		strncpy(data_page, data, PAGE_SIZE);
 	}
 
-	ret = do_mount(name, "/root", fs, flags, data_page);
+	ret = init_mount(name, "/root", fs, flags, data_page);
 	if (ret)
 		goto out;
 
@@ -628,7 +628,7 @@ void __init prepare_namespace(void)
 	mount_root();
 out:
 	devtmpfs_mount();
-	do_mount(".", "/", NULL, MS_MOVE, NULL);
+	init_mount(".", "/", NULL, MS_MOVE, NULL);
 	ksys_chroot(".");
 }
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index 15d256658a3093..ce4f95fff6bc16 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -9,6 +9,9 @@
 #include <linux/major.h>
 #include <linux/root_dev.h>
 
+int __init init_mount(const char *dev_name, const char *dir_name,
+		const char *type_page, unsigned long flags, void *data_page);
+
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
 void prepare_namespace(void);
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 3fabbc82513506..63a3eebd36e76b 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -63,7 +63,7 @@ static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
 	console_on_rootfs();
 	/* move initrd over / and chdir/chroot in initrd root */
 	ksys_chdir("/root");
-	do_mount(".", "/", NULL, MS_MOVE, NULL);
+	init_mount(".", "/", NULL, MS_MOVE, NULL);
 	ksys_chroot(".");
 	ksys_setsid();
 	return 0;
@@ -100,7 +100,7 @@ static void __init handle_initrd(void)
 	current->flags &= ~PF_FREEZER_SKIP;
 
 	/* move initrd to rootfs' /old */
-	do_mount("..", ".", NULL, MS_MOVE, NULL);
+	init_mount("..", ".", NULL, MS_MOVE, NULL);
 	/* switch root and cwd back to / of rootfs */
 	ksys_chroot("..");
 
@@ -114,7 +114,7 @@ static void __init handle_initrd(void)
 	mount_root();
 
 	printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
-	error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
+	error = init_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
 	if (!error)
 		printk("okay\n");
 	else {
diff --git a/init/fs.c b/init/fs.c
new file mode 100644
index 00000000000000..73423f5461f934
--- /dev/null
+++ b/init/fs.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/fs.h>
+#include "do_mounts.h"
+
+int __init init_mount(const char *dev_name, const char *dir_name,
+		const char *type_page, unsigned long flags, void *data_page)
+{
+	struct path path;
+	int ret;
+
+	ret = kern_path(dir_name, LOOKUP_FOLLOW, &path);
+	if (ret)
+		return ret;
+	ret = path_mount(dev_name, &path, type_page, flags, data_page);
+	path_put(&path);
+	return ret;
+}
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 13/24] init: add an init_unlink helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (11 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 12/24] init: add an init_mount helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 17:12   ` Al Viro
  2020-07-21 16:28 ` [PATCH 14/24] init: add an init_rmdir helper Christoph Hellwig
                   ` (10 subsequent siblings)
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to unlink with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_unlink.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 include/linux/syscalls.h | 7 -------
 init/do_mounts.h         | 3 ++-
 init/do_mounts_initrd.c  | 4 ++--
 init/do_mounts_rd.c      | 2 +-
 init/fs.c                | 6 ++++++
 init/initramfs.c         | 3 ++-
 6 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 1a4f5d8ee7044b..26f9738e5ab861 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1273,13 +1273,6 @@ int compat_ksys_ipc(u32 call, int first, int second,
  * The following kernel syscall equivalents are just wrappers to fs-internal
  * functions. Therefore, provide stubs to be inlined at the callsites.
  */
-extern long do_unlinkat(int dfd, struct filename *name);
-
-static inline long ksys_unlink(const char __user *pathname)
-{
-	return do_unlinkat(AT_FDCWD, getname(pathname));
-}
-
 long do_rmdir(int dfd, struct filename *name);
 
 static inline long ksys_rmdir(const char __user *pathname)
diff --git a/init/do_mounts.h b/init/do_mounts.h
index ce4f95fff6bc16..d2f1f335b5b5b9 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -11,6 +11,7 @@
 
 int __init init_mount(const char *dev_name, const char *dir_name,
 		const char *type_page, unsigned long flags, void *data_page);
+int __init init_unlink(const char *pathname);
 
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
@@ -19,7 +20,7 @@ extern int root_mountflags;
 
 static inline __init int create_dev(char *name, dev_t dev)
 {
-	ksys_unlink(name);
+	init_unlink(name);
 	return ksys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
 }
 
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 63a3eebd36e76b..dd4680c8ac762e 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -141,11 +141,11 @@ bool __init initrd_load(void)
 		 * mounted in the normal path.
 		 */
 		if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
-			ksys_unlink("/initrd.image");
+			init_unlink("/initrd.image");
 			handle_initrd();
 			return true;
 		}
 	}
-	ksys_unlink("/initrd.image");
+	init_unlink("/initrd.image");
 	return false;
 }
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index 7b64390c075043..b062f8b028ce7c 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -271,7 +271,7 @@ int __init rd_load_image(char *from)
 	fput(out_file);
 out:
 	kfree(buf);
-	ksys_unlink("/dev/ram");
+	init_unlink("/dev/ram");
 	return res;
 }
 
diff --git a/init/fs.c b/init/fs.c
index 73423f5461f934..1bdb5dc5ec12ba 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -3,6 +3,7 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/fs.h>
+#include <../fs/internal.h>
 #include "do_mounts.h"
 
 int __init init_mount(const char *dev_name, const char *dir_name,
@@ -18,3 +19,8 @@ int __init init_mount(const char *dev_name, const char *dir_name,
 	path_put(&path);
 	return ret;
 }
+
+int __init init_unlink(const char *pathname)
+{
+	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
+}
diff --git a/init/initramfs.c b/init/initramfs.c
index 6135b55286fc35..664be397c6b41e 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -12,6 +12,7 @@
 #include <linux/file.h>
 #include <linux/memblock.h>
 #include <linux/namei.h>
+#include "do_mounts.h"
 
 static ssize_t __init xwrite(struct file *file, const char *p, size_t count)
 {
@@ -307,7 +308,7 @@ static void __init clean_path(char *path, umode_t fmode)
 		if (S_ISDIR(st.mode))
 			ksys_rmdir(path);
 		else
-			ksys_unlink(path);
+			init_unlink(path);
 	}
 }
 
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 14/24] init: add an init_rmdir helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (12 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 13/24] init: add an init_unlink helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 15/24] init: add an init_chdir helper Christoph Hellwig
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to rmdir with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_rmdir.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 include/linux/syscalls.h | 7 -------
 init/do_mounts.h         | 1 +
 init/fs.c                | 5 +++++
 init/initramfs.c         | 2 +-
 4 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 26f9738e5ab861..a7b14258d245e2 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1273,13 +1273,6 @@ int compat_ksys_ipc(u32 call, int first, int second,
  * The following kernel syscall equivalents are just wrappers to fs-internal
  * functions. Therefore, provide stubs to be inlined at the callsites.
  */
-long do_rmdir(int dfd, struct filename *name);
-
-static inline long ksys_rmdir(const char __user *pathname)
-{
-	return do_rmdir(AT_FDCWD, getname(pathname));
-}
-
 extern long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
 
 static inline long ksys_mkdir(const char __user *pathname, umode_t mode)
diff --git a/init/do_mounts.h b/init/do_mounts.h
index d2f1f335b5b5b9..58605396d358d7 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -12,6 +12,7 @@
 int __init init_mount(const char *dev_name, const char *dir_name,
 		const char *type_page, unsigned long flags, void *data_page);
 int __init init_unlink(const char *pathname);
+int __init init_rmdir(const char *pathname);
 
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
diff --git a/init/fs.c b/init/fs.c
index 1bdb5dc5ec12ba..b69b2f949b6132 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -24,3 +24,8 @@ int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
 }
+
+int __init init_rmdir(const char *pathname)
+{
+	return do_rmdir(AT_FDCWD, getname_kernel(pathname));
+}
diff --git a/init/initramfs.c b/init/initramfs.c
index 664be397c6b41e..41491149fb1f29 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -306,7 +306,7 @@ static void __init clean_path(char *path, umode_t fmode)
 
 	if (!vfs_lstat(path, &st) && (st.mode ^ fmode) & S_IFMT) {
 		if (S_ISDIR(st.mode))
-			ksys_rmdir(path);
+			init_rmdir(path);
 		else
 			init_unlink(path);
 	}
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 15/24] init: add an init_chdir helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (13 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 14/24] init: add an init_rmdir helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 16/24] init: add an init_chroot helper Christoph Hellwig
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to chdir with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_chdir.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/open.c                |  7 +------
 include/linux/syscalls.h |  1 -
 init/do_mounts.c         |  2 +-
 init/do_mounts.h         |  1 +
 init/do_mounts_initrd.c  |  8 ++++----
 init/fs.c                | 16 ++++++++++++++++
 6 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/fs/open.c b/fs/open.c
index b316dd6a86a8b9..723e0ac898935e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -482,7 +482,7 @@ SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
 	return do_faccessat(AT_FDCWD, filename, mode, 0);
 }
 
-int ksys_chdir(const char __user *filename)
+SYSCALL_DEFINE1(chdir, const char __user *, filename)
 {
 	struct path path;
 	int error;
@@ -508,11 +508,6 @@ int ksys_chdir(const char __user *filename)
 	return error;
 }
 
-SYSCALL_DEFINE1(chdir, const char __user *, filename)
-{
-	return ksys_chdir(filename);
-}
-
 SYSCALL_DEFINE1(fchdir, unsigned int, fd)
 {
 	struct fd f = fdget_raw(fd);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a7b14258d245e2..31fa67fb9894b3 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1238,7 +1238,6 @@ asmlinkage long sys_ni_syscall(void);
 
 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);
 int ksys_fchown(unsigned int fd, uid_t user, gid_t group);
 ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count);
 void ksys_sync(void);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 4812e21d149cab..cc08ed7b44e764 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -408,7 +408,7 @@ static int __init do_mount_root(const char *name, const char *fs,
 	if (ret)
 		goto out;
 
-	ksys_chdir("/root");
+	init_chdir("/root");
 	s = current->fs->pwd.dentry->d_sb;
 	ROOT_DEV = s->s_dev;
 	printk(KERN_INFO
diff --git a/init/do_mounts.h b/init/do_mounts.h
index 58605396d358d7..c82fcb27575877 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -11,6 +11,7 @@
 
 int __init init_mount(const char *dev_name, const char *dir_name,
 		const char *type_page, unsigned long flags, void *data_page);
+int __init init_chdir(const char *filename);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index dd4680c8ac762e..ef214a78e7ee49 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -62,7 +62,7 @@ static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
 	ksys_unshare(CLONE_FS | CLONE_FILES);
 	console_on_rootfs();
 	/* move initrd over / and chdir/chroot in initrd root */
-	ksys_chdir("/root");
+	init_chdir("/root");
 	init_mount(".", "/", NULL, MS_MOVE, NULL);
 	ksys_chroot(".");
 	ksys_setsid();
@@ -83,7 +83,7 @@ static void __init handle_initrd(void)
 	/* mount initrd on rootfs' /root */
 	mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
 	ksys_mkdir("/old", 0700);
-	ksys_chdir("/old");
+	init_chdir("/old");
 
 	/*
 	 * In case that a resume from disk is carried out by linuxrc or one of
@@ -105,11 +105,11 @@ static void __init handle_initrd(void)
 	ksys_chroot("..");
 
 	if (new_decode_dev(real_root_dev) == Root_RAM0) {
-		ksys_chdir("/old");
+		init_chdir("/old");
 		return;
 	}
 
-	ksys_chdir("/");
+	init_chdir("/");
 	ROOT_DEV = new_decode_dev(real_root_dev);
 	mount_root();
 
diff --git a/init/fs.c b/init/fs.c
index b69b2f949b6132..f3d8da00662572 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -3,6 +3,7 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/fs.h>
+#include <linux/fs_struct.h>
 #include <../fs/internal.h>
 #include "do_mounts.h"
 
@@ -20,6 +21,21 @@ int __init init_mount(const char *dev_name, const char *dir_name,
 	return ret;
 }
 
+int __init init_chdir(const char *filename)
+{
+	struct path path;
+	int error;
+
+	error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
+	if (error)
+		return error;
+	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
+	if (!error)
+		set_fs_pwd(current->fs, &path);
+	path_put(&path);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 16/24] init: add an init_chroot helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (14 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 15/24] init: add an init_chdir helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 17:10   ` Al Viro
  2020-07-21 16:28 ` [PATCH 17/24] init: add an init_chown helper Christoph Hellwig
                   ` (7 subsequent siblings)
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to chroot with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_chroot.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/open.c                |  7 +------
 include/linux/syscalls.h |  2 --
 init/do_mounts.c         |  2 +-
 init/do_mounts.h         |  1 +
 init/do_mounts_initrd.c  |  4 ++--
 init/fs.c                | 23 +++++++++++++++++++++++
 6 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/fs/open.c b/fs/open.c
index 723e0ac898935e..f62f4752bb436d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -530,7 +530,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
 	return error;
 }
 
-int ksys_chroot(const char __user *filename)
+SYSCALL_DEFINE1(chroot, const char __user *, filename)
 {
 	struct path path;
 	int error;
@@ -563,11 +563,6 @@ int ksys_chroot(const char __user *filename)
 	return error;
 }
 
-SYSCALL_DEFINE1(chroot, const char __user *, filename)
-{
-	return ksys_chroot(filename);
-}
-
 static int chmod_common(const struct path *path, umode_t mode)
 {
 	struct inode *inode = path->dentry->d_inode;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 31fa67fb9894b3..e89d62e944dc0e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1235,8 +1235,6 @@ asmlinkage long sys_ni_syscall(void);
  * Instead, use one of the functions which work equivalently, such as
  * the ksys_xyzyyz() functions prototyped below.
  */
-
-int ksys_chroot(const char __user *filename);
 ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
 int ksys_fchown(unsigned int fd, uid_t user, gid_t group);
 ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index cc08ed7b44e764..c8ccdc80ffcdd5 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -629,7 +629,7 @@ void __init prepare_namespace(void)
 out:
 	devtmpfs_mount();
 	init_mount(".", "/", NULL, MS_MOVE, NULL);
-	ksys_chroot(".");
+	init_chroot(".");
 }
 
 static bool is_tmpfs;
diff --git a/init/do_mounts.h b/init/do_mounts.h
index c82fcb27575877..810b37ce1db882 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -12,6 +12,7 @@
 int __init init_mount(const char *dev_name, const char *dir_name,
 		const char *type_page, unsigned long flags, void *data_page);
 int __init init_chdir(const char *filename);
+int __init init_chroot(const char *filename);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index ef214a78e7ee49..697d45e4aa8c87 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -64,7 +64,7 @@ static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
 	/* move initrd over / and chdir/chroot in initrd root */
 	init_chdir("/root");
 	init_mount(".", "/", NULL, MS_MOVE, NULL);
-	ksys_chroot(".");
+	init_chroot(".");
 	ksys_setsid();
 	return 0;
 }
@@ -102,7 +102,7 @@ static void __init handle_initrd(void)
 	/* move initrd to rootfs' /old */
 	init_mount("..", ".", NULL, MS_MOVE, NULL);
 	/* switch root and cwd back to / of rootfs */
-	ksys_chroot("..");
+	init_chroot("..");
 
 	if (new_decode_dev(real_root_dev) == Root_RAM0) {
 		init_chdir("/old");
diff --git a/init/fs.c b/init/fs.c
index f3d8da00662572..af55e6d40357dc 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -36,6 +36,29 @@ int __init init_chdir(const char *filename)
 	return error;
 }
 
+int __init init_chroot(const char *filename)
+{
+	struct path path;
+	int error;
+
+	error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
+	if (error)
+		return error;
+	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
+	if (error)
+		goto dput_and_out;
+	error = -EPERM;
+	if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
+		goto dput_and_out;
+	error = security_path_chroot(&path);
+	if (error)
+		goto dput_and_out;
+	set_fs_root(current->fs, &path);
+dput_and_out:
+	path_put(&path);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 17/24] init: add an init_chown helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (15 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 16/24] init: add an init_chroot helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 18/24] init: add an init_chmod helper Christoph Hellwig
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to chown with a kernel space file name and switch
the early init code over to it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h    |  2 +-
 fs/open.c        |  2 +-
 init/do_mounts.h |  1 +
 init/fs.c        | 18 ++++++++++++++++++
 init/initramfs.c |  6 +++---
 5 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index e903d5aae139a2..4a66730fabefa7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -129,7 +129,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small);
 int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
 int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
 		int flag);
-
+int chown_common(const struct path *path, uid_t user, gid_t group);
 extern int vfs_open(const struct path *, struct file *);
 
 /*
diff --git a/fs/open.c b/fs/open.c
index f62f4752bb436d..49960a1248f14b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -639,7 +639,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
 	return do_fchmodat(AT_FDCWD, filename, mode);
 }
 
-static int chown_common(const struct path *path, uid_t user, gid_t group)
+int chown_common(const struct path *path, uid_t user, gid_t group)
 {
 	struct inode *inode = path->dentry->d_inode;
 	struct inode *delegated_inode = NULL;
diff --git a/init/do_mounts.h b/init/do_mounts.h
index 810b37ce1db882..db42564080a2f9 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -13,6 +13,7 @@ int __init init_mount(const char *dev_name, const char *dir_name,
 		const char *type_page, unsigned long flags, void *data_page);
 int __init init_chdir(const char *filename);
 int __init init_chroot(const char *filename);
+int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/fs.c b/init/fs.c
index af55e6d40357dc..30000b7097b9f0 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -59,6 +59,24 @@ int __init init_chroot(const char *filename)
 	return error;
 }
 
+int __init init_chown(const char *filename, uid_t user, gid_t group, int flags)
+{
+	int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+	struct path path;
+	int error;
+
+	error = kern_path(filename, lookup_flags, &path);
+	if (error)
+		return error;
+	error = mnt_want_write(path.mnt);
+	if (!error) {
+		error = chown_common(&path, user, group);
+		mnt_drop_write(path.mnt);
+	}
+	path_put(&path);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
diff --git a/init/initramfs.c b/init/initramfs.c
index 41491149fb1f29..076413dbe8bcf3 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -353,14 +353,14 @@ static int __init do_name(void)
 		}
 	} else if (S_ISDIR(mode)) {
 		ksys_mkdir(collected, mode);
-		ksys_chown(collected, uid, gid);
+		init_chown(collected, uid, gid, 0);
 		ksys_chmod(collected, mode);
 		dir_add(collected, mtime);
 	} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
 		   S_ISFIFO(mode) || S_ISSOCK(mode)) {
 		if (maybe_link() == 0) {
 			ksys_mknod(collected, mode, rdev);
-			ksys_chown(collected, uid, gid);
+			init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
 			ksys_chmod(collected, mode);
 			do_utime(collected, mtime);
 		}
@@ -398,7 +398,7 @@ static int __init do_symlink(void)
 	collected[N_ALIGN(name_len) + body_len] = '\0';
 	clean_path(collected, 0);
 	ksys_symlink(collected + N_ALIGN(name_len), collected);
-	ksys_lchown(collected, uid, gid);
+	init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
 	do_utime(collected, mtime);
 	state = SkipIt;
 	next_state = Reset;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 18/24] init: add an init_chmod helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (16 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 17/24] init: add an init_chown helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 19/24] init: add an init_eaccess helper Christoph Hellwig
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to chmod with a kernel space file name and switch
the early init code over to it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h            |  2 +-
 fs/open.c                |  4 ++--
 include/linux/syscalls.h |  7 -------
 init/do_mounts.h         |  1 +
 init/fs.c                | 13 +++++++++++++
 init/initramfs.c         |  4 ++--
 6 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 4a66730fabefa7..585968c0286cf7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -126,7 +126,7 @@ extern struct open_how build_open_how(int flags, umode_t mode);
 extern int build_open_flags(const struct open_how *how, struct open_flags *op);
 
 long do_sys_ftruncate(unsigned int fd, loff_t length, int small);
-int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
+int chmod_common(const struct path *path, umode_t mode);
 int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
 		int flag);
 int chown_common(const struct path *path, uid_t user, gid_t group);
diff --git a/fs/open.c b/fs/open.c
index 49960a1248f14b..7ba89eae46c560 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -563,7 +563,7 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 	return error;
 }
 
-static int chmod_common(const struct path *path, umode_t mode)
+int chmod_common(const struct path *path, umode_t mode)
 {
 	struct inode *inode = path->dentry->d_inode;
 	struct inode *delegated_inode = NULL;
@@ -610,7 +610,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
 	return err;
 }
 
-int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
+static int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
 {
 	struct path path;
 	int error;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index e89d62e944dc0e..8b71fa321ca20c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1304,13 +1304,6 @@ static inline long ksys_link(const char __user *oldname,
 	return do_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
 }
 
-extern int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
-
-static inline int ksys_chmod(const char __user *filename, umode_t mode)
-{
-	return do_fchmodat(AT_FDCWD, filename, mode);
-}
-
 long do_faccessat(int dfd, const char __user *filename, int mode, int flags);
 
 static inline long ksys_access(const char __user *filename, int mode)
diff --git a/init/do_mounts.h b/init/do_mounts.h
index db42564080a2f9..b323d9755d7e5e 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -14,6 +14,7 @@ int __init init_mount(const char *dev_name, const char *dir_name,
 int __init init_chdir(const char *filename);
 int __init init_chroot(const char *filename);
 int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
+int __init init_chmod(const char *filename, umode_t mode);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/fs.c b/init/fs.c
index 30000b7097b9f0..c636f25c9a6d69 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -77,6 +77,19 @@ int __init init_chown(const char *filename, uid_t user, gid_t group, int flags)
 	return error;
 }
 
+int __init init_chmod(const char *filename, umode_t mode)
+{
+	struct path path;
+	int error;
+
+	error = kern_path(filename, LOOKUP_FOLLOW, &path);
+	if (error)
+		return error;
+	error = chmod_common(&path, mode);
+	path_put(&path);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
diff --git a/init/initramfs.c b/init/initramfs.c
index 076413dbe8bcf3..771da27e87afa1 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -354,14 +354,14 @@ static int __init do_name(void)
 	} else if (S_ISDIR(mode)) {
 		ksys_mkdir(collected, mode);
 		init_chown(collected, uid, gid, 0);
-		ksys_chmod(collected, mode);
+		init_chmod(collected, mode);
 		dir_add(collected, mtime);
 	} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
 		   S_ISFIFO(mode) || S_ISSOCK(mode)) {
 		if (maybe_link() == 0) {
 			ksys_mknod(collected, mode, rdev);
 			init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
-			ksys_chmod(collected, mode);
+			init_chmod(collected, mode);
 			do_utime(collected, mtime);
 		}
 	}
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 19/24] init: add an init_eaccess helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (17 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 18/24] init: add an init_chmod helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 20/24] init: add an init_link helper Christoph Hellwig
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to check if a file exists based on kernel space file
name and switch the early init code over to it.  Note that this
theoretically changes behavior as it always is based on the effective
permissions.  But during early init that doesn't make a difference.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/open.c                |  2 +-
 include/linux/syscalls.h |  7 -------
 init/do_mounts.h         |  1 +
 init/fs.c                | 13 +++++++++++++
 init/main.c              |  3 +--
 5 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/fs/open.c b/fs/open.c
index 7ba89eae46c560..aafecd1f7ba1a5 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -394,7 +394,7 @@ static const struct cred *access_override_creds(void)
 	return old_cred;
 }
 
-long do_faccessat(int dfd, const char __user *filename, int mode, int flags)
+static long do_faccessat(int dfd, const char __user *filename, int mode, int flags)
 {
 	struct path path;
 	struct inode *inode;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 8b71fa321ca20c..a2779638e41445 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1304,13 +1304,6 @@ static inline long ksys_link(const char __user *oldname,
 	return do_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
 }
 
-long do_faccessat(int dfd, const char __user *filename, int mode, int flags);
-
-static inline long ksys_access(const char __user *filename, int mode)
-{
-	return do_faccessat(AT_FDCWD, filename, mode, 0);
-}
-
 extern int do_fchownat(int dfd, const char __user *filename, uid_t user,
 		       gid_t group, int flag);
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index b323d9755d7e5e..b886aaa0d09716 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -15,6 +15,7 @@ int __init init_chdir(const char *filename);
 int __init init_chroot(const char *filename);
 int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
 int __init init_chmod(const char *filename, umode_t mode);
+int __init init_eaccess(const char *filename);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/fs.c b/init/fs.c
index c636f25c9a6d69..9929cdd19affbe 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -90,6 +90,19 @@ int __init init_chmod(const char *filename, umode_t mode)
 	return error;
 }
 
+int __init init_eaccess(const char *filename)
+{
+	struct path path;
+	int error;
+
+	error = kern_path(filename, LOOKUP_FOLLOW, &path);
+	if (error)
+		return error;
+	error = inode_permission(d_inode(path.dentry), MAY_ACCESS);
+	path_put(&path);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
diff --git a/init/main.c b/init/main.c
index b952e4cd685af4..227e206b9ffee2 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1516,8 +1516,7 @@ static noinline void __init kernel_init_freeable(void)
 	 * check if there is an early userspace init.  If yes, let it do all
 	 * the work
 	 */
-	if (ksys_access((const char __user *)
-			ramdisk_execute_command, 0) != 0) {
+	if (init_eaccess(ramdisk_execute_command) != 0) {
 		ramdisk_execute_command = NULL;
 		prepare_namespace();
 	}
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 20/24] init: add an init_link helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (18 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 19/24] init: add an init_eaccess helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 21/24] init: add an init_symlink helper Christoph Hellwig
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to link with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_link.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h            |  3 +--
 fs/namei.c               |  4 ++--
 include/linux/syscalls.h |  9 ---------
 init/do_mounts.h         |  1 +
 init/fs.c                | 33 +++++++++++++++++++++++++++++++++
 init/initramfs.c         |  2 +-
 6 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 585968c0286cf7..9a1e937e484647 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -69,8 +69,7 @@ long do_rmdir(int dfd, struct filename *name);
 long do_unlinkat(int dfd, struct filename *name);
 long do_symlinkat(const char __user *oldname, int newdfd,
 		  const char __user *newname);
-int do_linkat(int olddfd, const char __user *oldname, int newdfd,
-	      const char __user *newname, int flags);
+int may_linkat(struct path *link);
 
 /*
  * namespace.c
diff --git a/fs/namei.c b/fs/namei.c
index d75a6039ae3966..13de64c6be7640 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1024,7 +1024,7 @@ static bool safe_hardlink_source(struct inode *inode)
  *
  * Returns 0 if successful, -ve on error.
  */
-static int may_linkat(struct path *link)
+int may_linkat(struct path *link)
 {
 	struct inode *inode = link->dentry->d_inode;
 
@@ -4086,7 +4086,7 @@ EXPORT_SYMBOL(vfs_link);
  * with linux 2.0, and to avoid hard-linking to directories
  * and other special files.  --ADM
  */
-int do_linkat(int olddfd, const char __user *oldname, int newdfd,
+static int do_linkat(int olddfd, const char __user *oldname, int newdfd,
 	      const char __user *newname, int flags)
 {
 	struct dentry *new_dentry;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a2779638e41445..4b18b91ce46573 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1295,15 +1295,6 @@ static inline long ksys_mknod(const char __user *filename, umode_t mode,
 	return do_mknodat(AT_FDCWD, filename, mode, dev);
 }
 
-extern int do_linkat(int olddfd, const char __user *oldname, int newdfd,
-		     const char __user *newname, int flags);
-
-static inline long ksys_link(const char __user *oldname,
-			     const char __user *newname)
-{
-	return do_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
-}
-
 extern int do_fchownat(int dfd, const char __user *filename, uid_t user,
 		       gid_t group, int flag);
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index b886aaa0d09716..c80105e47a8e66 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -16,6 +16,7 @@ int __init init_chroot(const char *filename);
 int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
 int __init init_chmod(const char *filename, umode_t mode);
 int __init init_eaccess(const char *filename);
+int __init init_link(const char *oldname, const char *newname);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/fs.c b/init/fs.c
index 9929cdd19affbe..fb5fb7aa498485 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -103,6 +103,39 @@ int __init init_eaccess(const char *filename)
 	return error;
 }
 
+int __init init_link(const char *oldname, const char *newname)
+{
+	struct dentry *new_dentry;
+	struct path old_path, new_path;
+	int error;
+
+	error = kern_path(oldname, 0, &old_path);
+	if (error)
+		return error;
+
+	new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0);
+	error = PTR_ERR(new_dentry);
+	if (IS_ERR(new_dentry))
+		goto out;
+
+	error = -EXDEV;
+	if (old_path.mnt != new_path.mnt)
+		goto out_dput;
+	error = may_linkat(&old_path);
+	if (unlikely(error))
+		goto out_dput;
+	error = security_path_link(old_path.dentry, &new_path, new_dentry);
+	if (error)
+		goto out_dput;
+	error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry,
+			 NULL);
+out_dput:
+	done_path_create(&new_path, new_dentry);
+out:
+	path_put(&old_path);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
diff --git a/init/initramfs.c b/init/initramfs.c
index 771da27e87afa1..bdc3c0ec5a6c31 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -318,7 +318,7 @@ static int __init maybe_link(void)
 		char *old = find_link(major, minor, ino, mode, collected);
 		if (old) {
 			clean_path(collected, 0);
-			return (ksys_link(old, collected) < 0) ? -1 : 1;
+			return (init_link(old, collected) < 0) ? -1 : 1;
 		}
 	}
 	return 0;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 21/24] init: add an init_symlink helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (19 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 20/24] init: add an init_link helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 17:00   ` Al Viro
  2020-07-21 16:28 ` [PATCH 22/24] init: add an init_mkdir helper Christoph Hellwig
                   ` (2 subsequent siblings)
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to symlink with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_symlink.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h            |  2 --
 fs/namei.c               |  2 +-
 include/linux/syscalls.h |  9 ---------
 init/do_mounts.h         |  1 +
 init/fs.c                | 22 ++++++++++++++++++++++
 init/initramfs.c         |  2 +-
 6 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 9a1e937e484647..ad89db759513c4 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -67,8 +67,6 @@ long do_mknodat(int dfd, const char __user *filename, umode_t mode,
 long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
 long do_rmdir(int dfd, struct filename *name);
 long do_unlinkat(int dfd, struct filename *name);
-long do_symlinkat(const char __user *oldname, int newdfd,
-		  const char __user *newname);
 int may_linkat(struct path *link);
 
 /*
diff --git a/fs/namei.c b/fs/namei.c
index 13de64c6be7640..2f6fa53eb3da28 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3955,7 +3955,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 }
 EXPORT_SYMBOL(vfs_symlink);
 
-long do_symlinkat(const char __user *oldname, int newdfd,
+static long do_symlinkat(const char __user *oldname, int newdfd,
 		  const char __user *newname)
 {
 	int error;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 4b18b91ce46573..7cdc0d749a049f 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1277,15 +1277,6 @@ static inline long ksys_mkdir(const char __user *pathname, umode_t mode)
 	return do_mkdirat(AT_FDCWD, pathname, mode);
 }
 
-extern long do_symlinkat(const char __user *oldname, int newdfd,
-			 const char __user *newname);
-
-static inline long ksys_symlink(const char __user *oldname,
-				const char __user *newname)
-{
-	return do_symlinkat(oldname, AT_FDCWD, newname);
-}
-
 extern long do_mknodat(int dfd, const char __user *filename, umode_t mode,
 		       unsigned int dev);
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index c80105e47a8e66..30287ac3106dba 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -17,6 +17,7 @@ int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
 int __init init_chmod(const char *filename, umode_t mode);
 int __init init_eaccess(const char *filename);
 int __init init_link(const char *oldname, const char *newname);
+int __init init_symlink(const char *oldname, const char *newname);
 int __init init_unlink(const char *pathname);
 int __init init_rmdir(const char *pathname);
 
diff --git a/init/fs.c b/init/fs.c
index fb5fb7aa498485..8ffca538a8133f 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -136,6 +136,28 @@ int __init init_link(const char *oldname, const char *newname)
 	return error;
 }
 
+int __init init_symlink(const char *oldname, const char *newname)
+{
+	struct filename *from = getname_kernel(oldname);
+	struct dentry *dentry;
+	struct path path;
+	int error;
+
+	if (IS_ERR(from))
+		return PTR_ERR(from);
+	dentry = kern_path_create(AT_FDCWD, newname, &path, 0);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		goto out_putname;
+	error = security_path_symlink(&path, dentry, from->name);
+	if (!error)
+		error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
+	done_path_create(&path, dentry);
+out_putname:
+	putname(from);
+	return error;
+}
+
 int __init init_unlink(const char *pathname)
 {
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
diff --git a/init/initramfs.c b/init/initramfs.c
index bdc3c0ec5a6c31..5dd234cd2ecf12 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -397,7 +397,7 @@ static int __init do_symlink(void)
 {
 	collected[N_ALIGN(name_len) + body_len] = '\0';
 	clean_path(collected, 0);
-	ksys_symlink(collected + N_ALIGN(name_len), collected);
+	init_symlink(collected + N_ALIGN(name_len), collected);
 	init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
 	do_utime(collected, mtime);
 	state = SkipIt;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 22/24] init: add an init_mkdir helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (20 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 21/24] init: add an init_symlink helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 23/24] init: add an init_mknod helper Christoph Hellwig
  2020-07-21 16:28 ` [PATCH 24/24] init: add an init_lstat helper Christoph Hellwig
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to mkdir with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_mkdir.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h            |  1 -
 fs/namei.c               |  2 +-
 include/linux/syscalls.h |  7 -------
 init/do_mounts.h         |  1 +
 init/do_mounts_initrd.c  |  2 +-
 init/fs.c                | 18 ++++++++++++++++++
 init/initramfs.c         |  2 +-
 init/noinitramfs.c       |  5 +++--
 8 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index ad89db759513c4..54cf897bd0c18f 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -64,7 +64,6 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 			   const char *, unsigned int, struct path *);
 long do_mknodat(int dfd, const char __user *filename, umode_t mode,
 		unsigned int dev);
-long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
 long do_rmdir(int dfd, struct filename *name);
 long do_unlinkat(int dfd, struct filename *name);
 int may_linkat(struct path *link);
diff --git a/fs/namei.c b/fs/namei.c
index 2f6fa53eb3da28..d6b25dd32f4d50 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3645,7 +3645,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 EXPORT_SYMBOL(vfs_mkdir);
 
-long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
+static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
 {
 	struct dentry *dentry;
 	struct path path;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 7cdc0d749a049f..5ef77a91382aa5 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1270,13 +1270,6 @@ int compat_ksys_ipc(u32 call, int first, int second,
  * The following kernel syscall equivalents are just wrappers to fs-internal
  * functions. Therefore, provide stubs to be inlined at the callsites.
  */
-extern long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
-
-static inline long ksys_mkdir(const char __user *pathname, umode_t mode)
-{
-	return do_mkdirat(AT_FDCWD, pathname, mode);
-}
-
 extern long do_mknodat(int dfd, const char __user *filename, umode_t mode,
 		       unsigned int dev);
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index 30287ac3106dba..62ae09b96be025 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -19,6 +19,7 @@ int __init init_eaccess(const char *filename);
 int __init init_link(const char *oldname, const char *newname);
 int __init init_symlink(const char *oldname, const char *newname);
 int __init init_unlink(const char *pathname);
+int __init init_mkdir(const char *pathname, umode_t mode);
 int __init init_rmdir(const char *pathname);
 
 void  mount_block_root(char *name, int flags);
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 697d45e4aa8c87..1be66f7d70d709 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -82,7 +82,7 @@ static void __init handle_initrd(void)
 	create_dev("/dev/root.old", Root_RAM0);
 	/* mount initrd on rootfs' /root */
 	mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
-	ksys_mkdir("/old", 0700);
+	init_mkdir("/old", 0700);
 	init_chdir("/old");
 
 	/*
diff --git a/init/fs.c b/init/fs.c
index 8ffca538a8133f..0793a6872d0e33 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -163,6 +163,24 @@ int __init init_unlink(const char *pathname)
 	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
 }
 
+int __init init_mkdir(const char *pathname, umode_t mode)
+{
+	struct dentry *dentry;
+	struct path path;
+	int error;
+
+	dentry = kern_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+	if (!IS_POSIXACL(path.dentry->d_inode))
+		mode &= ~current_umask();
+	error = security_path_mkdir(&path, dentry, mode);
+	if (!error)
+		error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+	done_path_create(&path, dentry);
+	return error;
+}
+
 int __init init_rmdir(const char *pathname)
 {
 	return do_rmdir(AT_FDCWD, getname_kernel(pathname));
diff --git a/init/initramfs.c b/init/initramfs.c
index 5dd234cd2ecf12..b1a0a1d5c3c135 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -352,7 +352,7 @@ static int __init do_name(void)
 			state = CopyFile;
 		}
 	} else if (S_ISDIR(mode)) {
-		ksys_mkdir(collected, mode);
+		init_mkdir(collected, mode);
 		init_chown(collected, uid, gid, 0);
 		init_chmod(collected, mode);
 		dir_add(collected, mtime);
diff --git a/init/noinitramfs.c b/init/noinitramfs.c
index fa9cdfa7101d3c..b8bdba1c949cf9 100644
--- a/init/noinitramfs.c
+++ b/init/noinitramfs.c
@@ -9,6 +9,7 @@
 #include <linux/stat.h>
 #include <linux/kdev_t.h>
 #include <linux/syscalls.h>
+#include "do_mounts.h"
 
 /*
  * Create a simple rootfs that is similar to the default initramfs
@@ -17,7 +18,7 @@ static int __init default_rootfs(void)
 {
 	int err;
 
-	err = ksys_mkdir((const char __user __force *) "/dev", 0755);
+	err = init_mkdir("/dev", 0755);
 	if (err < 0)
 		goto out;
 
@@ -27,7 +28,7 @@ static int __init default_rootfs(void)
 	if (err < 0)
 		goto out;
 
-	err = ksys_mkdir((const char __user __force *) "/root", 0700);
+	err = init_mkdir("/root", 0700);
 	if (err < 0)
 		goto out;
 
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 23/24] init: add an init_mknod helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (21 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 22/24] init: add an init_mkdir helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  2020-07-21 17:02   ` Al Viro
  2020-07-21 16:28 ` [PATCH 24/24] init: add an init_lstat helper Christoph Hellwig
  23 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to mknod with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_mknod.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/internal.h            |  2 --
 fs/namei.c               |  2 +-
 include/linux/syscalls.h |  9 ---------
 init/do_mounts.h         |  3 ++-
 init/fs.c                | 25 +++++++++++++++++++++++++
 init/initramfs.c         |  2 +-
 init/noinitramfs.c       |  3 +--
 7 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 54cf897bd0c18f..490cf426ec9f67 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -62,8 +62,6 @@ extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
 			   struct path *path, struct path *root);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 			   const char *, unsigned int, struct path *);
-long do_mknodat(int dfd, const char __user *filename, umode_t mode,
-		unsigned int dev);
 long do_rmdir(int dfd, struct filename *name);
 long do_unlinkat(int dfd, struct filename *name);
 int may_linkat(struct path *link);
diff --git a/fs/namei.c b/fs/namei.c
index d6b25dd32f4d50..fde8fe086c090d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3564,7 +3564,7 @@ static int may_mknod(umode_t mode)
 	}
 }
 
-long do_mknodat(int dfd, const char __user *filename, umode_t mode,
+static long do_mknodat(int dfd, const char __user *filename, umode_t mode,
 		unsigned int dev)
 {
 	struct dentry *dentry;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 5ef77a91382aa5..63046c5e9fc5d4 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1270,15 +1270,6 @@ int compat_ksys_ipc(u32 call, int first, int second,
  * The following kernel syscall equivalents are just wrappers to fs-internal
  * functions. Therefore, provide stubs to be inlined at the callsites.
  */
-extern long do_mknodat(int dfd, const char __user *filename, umode_t mode,
-		       unsigned int dev);
-
-static inline long ksys_mknod(const char __user *filename, umode_t mode,
-			      unsigned int dev)
-{
-	return do_mknodat(AT_FDCWD, filename, mode, dev);
-}
-
 extern int do_fchownat(int dfd, const char __user *filename, uid_t user,
 		       gid_t group, int flag);
 
diff --git a/init/do_mounts.h b/init/do_mounts.h
index 62ae09b96be025..a793bafc6c6f2b 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -16,6 +16,7 @@ int __init init_chroot(const char *filename);
 int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
 int __init init_chmod(const char *filename, umode_t mode);
 int __init init_eaccess(const char *filename);
+int __init init_mknod(const char *filename, umode_t mode, unsigned int dev);
 int __init init_link(const char *oldname, const char *newname);
 int __init init_symlink(const char *oldname, const char *newname);
 int __init init_unlink(const char *pathname);
@@ -30,7 +31,7 @@ extern int root_mountflags;
 static inline __init int create_dev(char *name, dev_t dev)
 {
 	init_unlink(name);
-	return ksys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
+	return init_mknod(name, S_IFBLK | 0600, new_encode_dev(dev));
 }
 
 #ifdef CONFIG_BLK_DEV_RAM
diff --git a/init/fs.c b/init/fs.c
index 0793a6872d0e33..7f0e50a877fc98 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -103,6 +103,31 @@ int __init init_eaccess(const char *filename)
 	return error;
 }
 
+int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
+{
+	struct dentry *dentry;
+	struct path path;
+	int error;
+
+	if (S_ISFIFO(mode) || S_ISSOCK(mode))
+		dev = 0;
+	else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
+		return -EINVAL;
+
+	dentry = user_path_create(AT_FDCWD, filename, &path, 0);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
+	if (!IS_POSIXACL(path.dentry->d_inode))
+		mode &= ~current_umask();
+	error = security_path_mknod(&path, dentry, mode, dev);
+	if (!error)
+		error = vfs_mknod(path.dentry->d_inode, dentry, mode,
+				  new_decode_dev(dev));
+	done_path_create(&path, dentry);
+	return error;
+}
+
 int __init init_link(const char *oldname, const char *newname)
 {
 	struct dentry *new_dentry;
diff --git a/init/initramfs.c b/init/initramfs.c
index b1a0a1d5c3c135..bd685fdb5840f3 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -359,7 +359,7 @@ static int __init do_name(void)
 	} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
 		   S_ISFIFO(mode) || S_ISSOCK(mode)) {
 		if (maybe_link() == 0) {
-			ksys_mknod(collected, mode, rdev);
+			init_mknod(collected, mode, rdev);
 			init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
 			init_chmod(collected, mode);
 			do_utime(collected, mtime);
diff --git a/init/noinitramfs.c b/init/noinitramfs.c
index b8bdba1c949cf9..490f2bd2b49979 100644
--- a/init/noinitramfs.c
+++ b/init/noinitramfs.c
@@ -22,8 +22,7 @@ static int __init default_rootfs(void)
 	if (err < 0)
 		goto out;
 
-	err = ksys_mknod((const char __user __force *) "/dev/console",
-			S_IFCHR | S_IRUSR | S_IWUSR,
+	err = init_mknod("/dev/console", S_IFCHR | S_IRUSR | S_IWUSR,
 			new_encode_dev(MKDEV(5, 1)));
 	if (err < 0)
 		goto out;
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 24/24] init: add an init_lstat helper
  2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
                   ` (22 preceding siblings ...)
  2020-07-21 16:28 ` [PATCH 23/24] init: add an init_mknod helper Christoph Hellwig
@ 2020-07-21 16:28 ` Christoph Hellwig
  23 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 16:28 UTC (permalink / raw)
  To: Al Viro, Linus Torvalds
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel, linux-raid,
	linux-fsdevel, linux-api

Add a simple helper to lstat with a kernel space file name and switch
the early init code over to it.  Remove the now unused ksys_lstat.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 init/do_mounts.h |  1 +
 init/fs.c        | 14 ++++++++++++++
 init/initramfs.c |  2 +-
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/init/do_mounts.h b/init/do_mounts.h
index a793bafc6c6f2b..20766cfe549b48 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -16,6 +16,7 @@ int __init init_chroot(const char *filename);
 int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
 int __init init_chmod(const char *filename, umode_t mode);
 int __init init_eaccess(const char *filename);
+int __init init_lstat(const char *filename, struct kstat *stat);
 int __init init_mknod(const char *filename, umode_t mode, unsigned int dev);
 int __init init_link(const char *oldname, const char *newname);
 int __init init_symlink(const char *oldname, const char *newname);
diff --git a/init/fs.c b/init/fs.c
index 7f0e50a877fc98..b387ff67f365db 100644
--- a/init/fs.c
+++ b/init/fs.c
@@ -103,6 +103,20 @@ int __init init_eaccess(const char *filename)
 	return error;
 }
 
+int __init init_lstat(const char *filename, struct kstat *stat)
+{
+	struct path path;
+	int error;
+
+	error = kern_path(filename, 0, &path);
+	if (error)
+		return error;
+	error = vfs_getattr(&path, stat, STATX_BASIC_STATS,
+			    AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT);
+	path_put(&path);
+	return error;
+}
+
 int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
 {
 	struct dentry *dentry;
diff --git a/init/initramfs.c b/init/initramfs.c
index bd685fdb5840f3..8c9f92f1660b96 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -304,7 +304,7 @@ static void __init clean_path(char *path, umode_t fmode)
 {
 	struct kstat st;
 
-	if (!vfs_lstat(path, &st) && (st.mode ^ fmode) & S_IFMT) {
+	if (!init_lstat(path, &st) && (st.mode ^ fmode) & S_IFMT) {
 		if (S_ISDIR(st.mode))
 			init_rmdir(path);
 		else
-- 
2.27.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot
  2020-07-21 16:27 ` [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot Christoph Hellwig
@ 2020-07-21 16:49   ` Linus Torvalds
  2020-07-21 17:16     ` Al Viro
  0 siblings, 1 reply; 37+ messages in thread
From: Linus Torvalds @ 2020-07-21 16:49 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Al Viro, Greg Kroah-Hartman, Rafael J. Wysocki,
	Linux Kernel Mailing List, linux-raid, linux-fsdevel, Linux API

On Tue, Jul 21, 2020 at 9:28 AM Christoph Hellwig <hch@lst.de> wrote:
>
> +
> +       /* traverse into overmounted root and then chroot to it */
> +       if (!kern_path("/..", LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path) &&
> +           !inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR) &&
> +           ns_capable(current_user_ns(), CAP_SYS_CHROOT) &&
> +           !security_path_chroot(&path)) {
> +               set_fs_pwd(current->fs, &path);
> +               set_fs_root(current->fs, &path);
> +       }
> +       path_put(&path);

This looks wrong.

You're doing "path_put()" even if kern_path() didn't succeed.

As far as I can tell, that will either put some uninitialized garbage
and cause an oops, or put something that has already been released by
the failure path.

Maybe that doesn't happen in practice in this case, but it's still
very very wrong.

Plus you shouldn't have those kinds of insanely complex if-statements
in the first place. That was what caused the bug - trying to be
clever, instead of writing clear code.

I'm not liking how I'm finding fundamental mistakes in patches that
_should_ be trivial conversions with no semantic changes.

               Linus

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 06/24] md: open code vfs_stat in md_setup_drive
  2020-07-21 16:28 ` [PATCH 06/24] md: open code vfs_stat in md_setup_drive Christoph Hellwig
@ 2020-07-21 16:55   ` Al Viro
  2020-07-21 18:27     ` Christoph Hellwig
  0 siblings, 1 reply; 37+ messages in thread
From: Al Viro @ 2020-07-21 16:55 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 06:28:00PM +0200, Christoph Hellwig wrote:
> Instead of passing a kernel pointer to vfs_stat by relying on the
> implicit set_fs(KERNEL_DS) in md_setup_drive, just open code the
> trivial getattr, and use the opportunity to move a little bit more
> code from the caller into the new helper.

Ugh...

> +static void __init md_lookup_dev(const char *devname, dev_t *dev)
> +{
> +	struct kstat stat;
> +	struct path path;
> +	char filename[64];
> +
> +	if (strncmp(devname, "/dev/", 5) == 0)
> +		devname += 5;
> +	snprintf(filename, 63, "/dev/%s", devname);
> +
> +	if (!kern_path(filename, LOOKUP_FOLLOW, &path) &&
> +	    !vfs_getattr(&path, &stat, STATX_BASIC_STATS, AT_NO_AUTOMOUNT) &&
> +	    S_ISBLK(stat.mode))
> +		*dev = new_decode_dev(stat.rdev);
> +	path_put(&path);
> +}

How about fs/for_init.c and putting the damn helpers there?  With
calling conventions as close to syscalls as possible, and a fat
comment regarding their intended use being _ONLY_ the setup
in should-have-been-done-in-userland parts of init?

I really want to keep the surface as small as possible - we had
fun shite several releases ago when somebody tried that kind of
crap (with open(), IIRC).  Let's not go there again...

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 12/24] init: add an init_mount helper
  2020-07-21 16:28 ` [PATCH 12/24] init: add an init_mount helper Christoph Hellwig
@ 2020-07-21 16:58   ` Al Viro
  0 siblings, 0 replies; 37+ messages in thread
From: Al Viro @ 2020-07-21 16:58 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 06:28:06PM +0200, Christoph Hellwig wrote:
> Like do_mount, but takes a kernel pointer for the destination path.
> Switch over the mounts in the init code and devtmpfs to it, which
> just happen to work due to the implicit set_fs(KERNEL_DS) during early
> init right now.

>  init/fs.c               | 20 ++++++++++++++++++++

fs/for_init.c, please.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/24] init: add an init_symlink helper
  2020-07-21 16:28 ` [PATCH 21/24] init: add an init_symlink helper Christoph Hellwig
@ 2020-07-21 17:00   ` Al Viro
  0 siblings, 0 replies; 37+ messages in thread
From: Al Viro @ 2020-07-21 17:00 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 06:28:15PM +0200, Christoph Hellwig wrote:
> Add a simple helper to symlink with a kernel space file name and switch
> the early init code over to it.  Remove the now unused ksys_symlink.

> +int __init init_symlink(const char *oldname, const char *newname)
> +{
> +	struct filename *from = getname_kernel(oldname);

What the hell for?  You are only using from ->name later.

> +	struct dentry *dentry;
> +	struct path path;
> +	int error;
> +
> +	if (IS_ERR(from))
> +		return PTR_ERR(from);
> +	dentry = kern_path_create(AT_FDCWD, newname, &path, 0);
> +	error = PTR_ERR(dentry);
> +	if (IS_ERR(dentry))
> +		goto out_putname;
> +	error = security_path_symlink(&path, dentry, from->name);
> +	if (!error)
> +		error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
> +	done_path_create(&path, dentry);
> +out_putname:
> +	putname(from);
> +	return error;
> +}

And again, the same comment regarding the location of file.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 23/24] init: add an init_mknod helper
  2020-07-21 16:28 ` [PATCH 23/24] init: add an init_mknod helper Christoph Hellwig
@ 2020-07-21 17:02   ` Al Viro
  0 siblings, 0 replies; 37+ messages in thread
From: Al Viro @ 2020-07-21 17:02 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 06:28:17PM +0200, Christoph Hellwig wrote:

> +int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
> +{
> +	struct dentry *dentry;
> +	struct path path;
> +	int error;
> +
> +	if (S_ISFIFO(mode) || S_ISSOCK(mode))
> +		dev = 0;
> +	else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
> +		return -EINVAL;
> +
> +	dentry = user_path_create(AT_FDCWD, filename, &path, 0);
> +	if (IS_ERR(dentry))
> +		return PTR_ERR(dentry);

user_path_create() is wrong here.

> +
> +	if (!IS_POSIXACL(path.dentry->d_inode))
> +		mode &= ~current_umask();
> +	error = security_path_mknod(&path, dentry, mode, dev);
> +	if (!error)
> +		error = vfs_mknod(path.dentry->d_inode, dentry, mode,
> +				  new_decode_dev(dev));
> +	done_path_create(&path, dentry);
> +	return error;
> +}
> +
>  int __init init_link(const char *oldname, const char *newname)
>  {
>  	struct dentry *new_dentry;
> diff --git a/init/initramfs.c b/init/initramfs.c
> index b1a0a1d5c3c135..bd685fdb5840f3 100644
> --- a/init/initramfs.c
> +++ b/init/initramfs.c
> @@ -359,7 +359,7 @@ static int __init do_name(void)
>  	} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
>  		   S_ISFIFO(mode) || S_ISSOCK(mode)) {
>  		if (maybe_link() == 0) {
> -			ksys_mknod(collected, mode, rdev);
> +			init_mknod(collected, mode, rdev);
>  			init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
>  			init_chmod(collected, mode);
>  			do_utime(collected, mtime);
> diff --git a/init/noinitramfs.c b/init/noinitramfs.c
> index b8bdba1c949cf9..490f2bd2b49979 100644
> --- a/init/noinitramfs.c
> +++ b/init/noinitramfs.c
> @@ -22,8 +22,7 @@ static int __init default_rootfs(void)
>  	if (err < 0)
>  		goto out;
>  
> -	err = ksys_mknod((const char __user __force *) "/dev/console",
> -			S_IFCHR | S_IRUSR | S_IWUSR,
> +	err = init_mknod("/dev/console", S_IFCHR | S_IRUSR | S_IWUSR,
>  			new_encode_dev(MKDEV(5, 1)));
>  	if (err < 0)
>  		goto out;
> -- 
> 2.27.0
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 16/24] init: add an init_chroot helper
  2020-07-21 16:28 ` [PATCH 16/24] init: add an init_chroot helper Christoph Hellwig
@ 2020-07-21 17:10   ` Al Viro
  0 siblings, 0 replies; 37+ messages in thread
From: Al Viro @ 2020-07-21 17:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 06:28:10PM +0200, Christoph Hellwig wrote:

> +int __init init_chroot(const char *filename)
> +{
> +	struct path path;
> +	int error;
> +
> +	error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
> +	if (error)
> +		return error;
> +	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);

Matter of taste, but if we do that, I wonder if we would be better off with
	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
	if (!error && !ns_capable(current_user_ns(), CAP_SYS_CHROOT))
		error = -EPERM;
	if (!error)
		error = security_path_chroot(&path);
	if (!error)
		set_fs_root(current->fs, &path);
	path_put(&path);
	return error;


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 13/24] init: add an init_unlink helper
  2020-07-21 16:28 ` [PATCH 13/24] init: add an init_unlink helper Christoph Hellwig
@ 2020-07-21 17:12   ` Al Viro
  0 siblings, 0 replies; 37+ messages in thread
From: Al Viro @ 2020-07-21 17:12 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 06:28:07PM +0200, Christoph Hellwig wrote:
> diff --git a/init/fs.c b/init/fs.c
> index 73423f5461f934..1bdb5dc5ec12ba 100644
> --- a/init/fs.c
> +++ b/init/fs.c
> @@ -3,6 +3,7 @@
>  #include <linux/mount.h>
>  #include <linux/namei.h>
>  #include <linux/fs.h>
> +#include <../fs/internal.h>

... and that is why the damn thing would be better off in fs/

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot
  2020-07-21 16:49   ` Linus Torvalds
@ 2020-07-21 17:16     ` Al Viro
  2020-07-21 18:26       ` Christoph Hellwig
  0 siblings, 1 reply; 37+ messages in thread
From: Al Viro @ 2020-07-21 17:16 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Christoph Hellwig, Greg Kroah-Hartman, Rafael J. Wysocki,
	Linux Kernel Mailing List, linux-raid, linux-fsdevel, Linux API

On Tue, Jul 21, 2020 at 09:49:17AM -0700, Linus Torvalds wrote:
> On Tue, Jul 21, 2020 at 9:28 AM Christoph Hellwig <hch@lst.de> wrote:
> >
> > +
> > +       /* traverse into overmounted root and then chroot to it */
> > +       if (!kern_path("/..", LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path) &&
> > +           !inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR) &&
> > +           ns_capable(current_user_ns(), CAP_SYS_CHROOT) &&
> > +           !security_path_chroot(&path)) {
> > +               set_fs_pwd(current->fs, &path);
> > +               set_fs_root(current->fs, &path);
> > +       }
> > +       path_put(&path);
> 
> This looks wrong.

It is wrong.  kern_path() leaves *path unmodified in case of error, and
that struct path is uninitialized here.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot
  2020-07-21 17:16     ` Al Viro
@ 2020-07-21 18:26       ` Christoph Hellwig
  0 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 18:26 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, Christoph Hellwig, Greg Kroah-Hartman,
	Rafael J. Wysocki, Linux Kernel Mailing List, linux-raid,
	linux-fsdevel, Linux API

On Tue, Jul 21, 2020 at 06:16:27PM +0100, Al Viro wrote:
> On Tue, Jul 21, 2020 at 09:49:17AM -0700, Linus Torvalds wrote:
> > On Tue, Jul 21, 2020 at 9:28 AM Christoph Hellwig <hch@lst.de> wrote:
> > >
> > > +
> > > +       /* traverse into overmounted root and then chroot to it */
> > > +       if (!kern_path("/..", LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path) &&
> > > +           !inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR) &&
> > > +           ns_capable(current_user_ns(), CAP_SYS_CHROOT) &&
> > > +           !security_path_chroot(&path)) {
> > > +               set_fs_pwd(current->fs, &path);
> > > +               set_fs_root(current->fs, &path);
> > > +       }
> > > +       path_put(&path);
> > 
> > This looks wrong.
> 
> It is wrong.  kern_path() leaves *path unmodified in case of error, and
> that struct path is uninitialized here.

Yep.  Only saving grace is that the error just doesn't happen during
early init.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 06/24] md: open code vfs_stat in md_setup_drive
  2020-07-21 16:55   ` Al Viro
@ 2020-07-21 18:27     ` Christoph Hellwig
  2020-07-22  7:44       ` Al Viro
  0 siblings, 1 reply; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-21 18:27 UTC (permalink / raw)
  To: Al Viro
  Cc: Christoph Hellwig, Linus Torvalds, Greg Kroah-Hartman,
	Rafael J. Wysocki, linux-kernel, linux-raid, linux-fsdevel,
	linux-api

On Tue, Jul 21, 2020 at 05:55:39PM +0100, Al Viro wrote:
> How about fs/for_init.c and putting the damn helpers there?  With
> calling conventions as close to syscalls as possible, and a fat
> comment regarding their intended use being _ONLY_ the setup
> in should-have-been-done-in-userland parts of init?

Where do you want the prototypes to go?  Also do you want devtmpfs
use the same helpers, which then't can't be marked __init (mount,
chdir, chroot), or separate copies?

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 06/24] md: open code vfs_stat in md_setup_drive
  2020-07-21 18:27     ` Christoph Hellwig
@ 2020-07-22  7:44       ` Al Viro
  2020-07-22 14:05         ` Christoph Hellwig
  0 siblings, 1 reply; 37+ messages in thread
From: Al Viro @ 2020-07-22  7:44 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linus Torvalds, Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel, linux-raid, linux-fsdevel, linux-api

On Tue, Jul 21, 2020 at 08:27:01PM +0200, Christoph Hellwig wrote:
> On Tue, Jul 21, 2020 at 05:55:39PM +0100, Al Viro wrote:
> > How about fs/for_init.c and putting the damn helpers there?  With
> > calling conventions as close to syscalls as possible, and a fat
> > comment regarding their intended use being _ONLY_ the setup
> > in should-have-been-done-in-userland parts of init?
> 
> Where do you want the prototypes to go?  Also do you want devtmpfs
> use the same helpers, which then't can't be marked __init (mount,
> chdir, chroot), or separate copies?

Hmm...  mount still can be __init (devtmpfs_mount() is), and I suspect
devtmpfs_setup() could also be made such - just turn devtmpfsd()
into
static int __init devtmpfsd(void *p)
{
        int err = devtmpfs_setup(p);

	if (!err)
		devtmpfsd_real();	/* never returns */
	return err;
}
and you are done.  As for the prototypes... include/linux/init_syscalls.h,
perhaps?

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 06/24] md: open code vfs_stat in md_setup_drive
  2020-07-22  7:44       ` Al Viro
@ 2020-07-22 14:05         ` Christoph Hellwig
  0 siblings, 0 replies; 37+ messages in thread
From: Christoph Hellwig @ 2020-07-22 14:05 UTC (permalink / raw)
  To: Al Viro
  Cc: Christoph Hellwig, Linus Torvalds, Greg Kroah-Hartman,
	Rafael J. Wysocki, linux-kernel, linux-raid, linux-fsdevel,
	linux-api

On Wed, Jul 22, 2020 at 08:44:32AM +0100, Al Viro wrote:
> On Tue, Jul 21, 2020 at 08:27:01PM +0200, Christoph Hellwig wrote:
> > On Tue, Jul 21, 2020 at 05:55:39PM +0100, Al Viro wrote:
> > > How about fs/for_init.c and putting the damn helpers there?  With
> > > calling conventions as close to syscalls as possible, and a fat
> > > comment regarding their intended use being _ONLY_ the setup
> > > in should-have-been-done-in-userland parts of init?
> > 
> > Where do you want the prototypes to go?  Also do you want devtmpfs
> > use the same helpers, which then't can't be marked __init (mount,
> > chdir, chroot), or separate copies?
> 
> Hmm...  mount still can be __init (devtmpfs_mount() is), and I suspect
> devtmpfs_setup() could also be made such - just turn devtmpfsd()
> into
> static int __init devtmpfsd(void *p)
> {
>         int err = devtmpfs_setup(p);
> 
> 	if (!err)
> 		devtmpfsd_real();	/* never returns */
> 	return err;
> }
> and you are done.

Yes, that seems to work.  We can obviously call non-__init functions
from __init ones, and kthread_run doesn't seem to care if it gets passed
a __init function.

Here is what I have now:

http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/init_path

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2020-07-22 14:05 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-21 16:27 add file system helpers that take kernel pointers for the init code v2 Christoph Hellwig
2020-07-21 16:27 ` [PATCH 01/24] fs: refactor do_mount Christoph Hellwig
2020-07-21 16:27 ` [PATCH 02/24] fs: refactor ksys_umount Christoph Hellwig
2020-07-21 16:27 ` [PATCH 03/24] fs: push the getname from do_rmdir into the callers Christoph Hellwig
2020-07-21 16:27 ` [PATCH 04/24] devtmpfs: open code do_mount Christoph Hellwig
2020-07-21 16:27 ` [PATCH 05/24] devtmpfs: open code ksys_chdir and ksys_chroot Christoph Hellwig
2020-07-21 16:49   ` Linus Torvalds
2020-07-21 17:16     ` Al Viro
2020-07-21 18:26       ` Christoph Hellwig
2020-07-21 16:28 ` [PATCH 06/24] md: open code vfs_stat in md_setup_drive Christoph Hellwig
2020-07-21 16:55   ` Al Viro
2020-07-21 18:27     ` Christoph Hellwig
2020-07-22  7:44       ` Al Viro
2020-07-22 14:05         ` Christoph Hellwig
2020-07-21 16:28 ` [PATCH 07/24] init: initialize ramdisk_execute_command at compile time Christoph Hellwig
2020-07-21 16:28 ` [PATCH 08/24] init: move the prepare_namespace prototype to init/do_mounts.h Christoph Hellwig
2020-07-21 16:28 ` [PATCH 09/24] init: mark create_dev as __init Christoph Hellwig
2020-07-21 16:28 ` [PATCH 10/24] init: open code ksys_umount in handle_initrd Christoph Hellwig
2020-07-21 16:28 ` [PATCH 11/24] init: open code do_utimes in do_utime Christoph Hellwig
2020-07-21 16:28 ` [PATCH 12/24] init: add an init_mount helper Christoph Hellwig
2020-07-21 16:58   ` Al Viro
2020-07-21 16:28 ` [PATCH 13/24] init: add an init_unlink helper Christoph Hellwig
2020-07-21 17:12   ` Al Viro
2020-07-21 16:28 ` [PATCH 14/24] init: add an init_rmdir helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 15/24] init: add an init_chdir helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 16/24] init: add an init_chroot helper Christoph Hellwig
2020-07-21 17:10   ` Al Viro
2020-07-21 16:28 ` [PATCH 17/24] init: add an init_chown helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 18/24] init: add an init_chmod helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 19/24] init: add an init_eaccess helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 20/24] init: add an init_link helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 21/24] init: add an init_symlink helper Christoph Hellwig
2020-07-21 17:00   ` Al Viro
2020-07-21 16:28 ` [PATCH 22/24] init: add an init_mkdir helper Christoph Hellwig
2020-07-21 16:28 ` [PATCH 23/24] init: add an init_mknod helper Christoph Hellwig
2020-07-21 17:02   ` Al Viro
2020-07-21 16:28 ` [PATCH 24/24] init: add an init_lstat helper Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).