Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1588019 > unrolled thread

[PATCH 2/3] fs: Extracts pivot_root so it can be made optional

Started bybosrsf04@gmail.com
First post2017-02-25 01:30 +0100
Last post2017-02-26 02:50 +0100
Articles 6 — 5 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 2/3] fs: Extracts pivot_root so it can be made optional bosrsf04@gmail.com - 2017-02-25 01:30 +0100
    Re: [PATCH 2/3] fs: Extracts pivot_root so it can be made optional Theodore Ts'o <tytso@mit.edu> - 2017-02-25 17:10 +0100
      Re: [PATCH 2/3] fs: Extracts pivot_root so it can be made optional Al Viro <viro@ZenIV.linux.org.uk> - 2017-02-25 17:10 +0100
        [PATCH 0/1] fs: Support compiling out the pivot_root syscall Brian Ashworth <bosrsf04@gmail.com> - 2017-02-26 02:10 +0100
          [PATCH 1/1] fs: Allows for the pivot_root syscall to be optional Brian Ashworth <bosrsf04@gmail.com> - 2017-02-26 02:10 +0100
            Re: [PATCH 1/1] fs: Allows for the pivot_root syscall to be  optional Nicolas Pitre <nicolas.pitre@linaro.org> - 2017-02-26 02:50 +0100

#1588019 — [PATCH 2/3] fs: Extracts pivot_root so it can be made optional

Frombosrsf04@gmail.com
Date2017-02-25 01:30 +0100
Subject[PATCH 2/3] fs: Extracts pivot_root so it can be made optional
Message-ID<teypk-86z-11@gated-at.bofh.it>
From: Brian Ashworth <bosrsf04@gmail.com>

add/remove: 0/0 grow/shrink: 1/0 up/down: 4/0 (4)
function                                     old     new   delta
sys_pivot_root                               610     614      +4
Total: Before=1899573, After=1899577, chg +0.00%

Signed-off-by Brian Ashworth <bosrsf04@gmail.com>
---
 fs/Makefile     |   2 +-
 fs/namespace.c  | 123 -----------------------------------------------------
 fs/pivot_root.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+), 124 deletions(-)
 create mode 100644 fs/pivot_root.c

diff --git a/fs/Makefile b/fs/Makefile
index 7bbaca9c67b1..34cb58c4127d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,7 +11,7 @@ obj-y :=	open.o read_write.o file_table.o super.o \
 		attr.o bad_inode.o file.o filesystems.o namespace.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o \
 		pnode.o splice.o sync.o utimes.o \
-		stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
+		stack.o fs_struct.o statfs.o fs_pin.o nsfs.o pivot_root.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=	buffer.o block_dev.o direct-io.o mpage.o
diff --git a/fs/namespace.c b/fs/namespace.c
index d49d615e30a1..36e4faf4c6e6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3043,129 +3043,6 @@ bool path_is_under(const struct path *path1, const struct path *path2)
 }
 EXPORT_SYMBOL(path_is_under);
 
-/*
- * pivot_root Semantics:
- * Moves the root file system of the current process to the directory put_old,
- * makes new_root as the new root file system of the current process, and sets
- * root/cwd of all processes which had them on the current root to new_root.
- *
- * Restrictions:
- * The new_root and put_old must be directories, and  must not be on the
- * same file  system as the current process root. The put_old  must  be
- * underneath new_root,  i.e. adding a non-zero number of /.. to the string
- * pointed to by put_old must yield the same directory as new_root. No other
- * file system may be mounted on put_old. After all, new_root is a mountpoint.
- *
- * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
- * See Documentation/filesystems/ramfs-rootfs-initramfs.txt for alternatives
- * in this situation.
- *
- * Notes:
- *  - we don't move root/cwd if they are not at the root (reason: if something
- *    cared enough to change them, it's probably wrong to force them elsewhere)
- *  - it's okay to pick a root that isn't the root of a file system, e.g.
- *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
- *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
- *    first.
- */
-SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
-		const char __user *, put_old)
-{
-	struct path new, old, parent_path, root_parent, root;
-	struct mount *new_mnt, *root_mnt, *old_mnt;
-	struct mountpoint *old_mp, *root_mp;
-	int error;
-
-	if (!may_mount())
-		return -EPERM;
-
-	error = user_path_dir(new_root, &new);
-	if (error)
-		goto out0;
-
-	error = user_path_dir(put_old, &old);
-	if (error)
-		goto out1;
-
-	error = security_sb_pivotroot(&old, &new);
-	if (error)
-		goto out2;
-
-	get_fs_root(current->fs, &root);
-	old_mp = lock_mount(&old);
-	error = PTR_ERR(old_mp);
-	if (IS_ERR(old_mp))
-		goto out3;
-
-	error = -EINVAL;
-	new_mnt = real_mount(new.mnt);
-	root_mnt = real_mount(root.mnt);
-	old_mnt = real_mount(old.mnt);
-	if (IS_MNT_SHARED(old_mnt) ||
-		IS_MNT_SHARED(new_mnt->mnt_parent) ||
-		IS_MNT_SHARED(root_mnt->mnt_parent))
-		goto out4;
-	if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
-		goto out4;
-	if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
-		goto out4;
-	error = -ENOENT;
-	if (d_unlinked(new.dentry))
-		goto out4;
-	error = -EBUSY;
-	if (new_mnt == root_mnt || old_mnt == root_mnt)
-		goto out4; /* loop, on the same file system  */
-	error = -EINVAL;
-	if (root.mnt->mnt_root != root.dentry)
-		goto out4; /* not a mountpoint */
-	if (!mnt_has_parent(root_mnt))
-		goto out4; /* not attached */
-	root_mp = root_mnt->mnt_mp;
-	if (new.mnt->mnt_root != new.dentry)
-		goto out4; /* not a mountpoint */
-	if (!mnt_has_parent(new_mnt))
-		goto out4; /* not attached */
-	/* make sure we can reach put_old from new_root */
-	if (!is_path_reachable(old_mnt, old.dentry, &new))
-		goto out4;
-	/* make certain new is below the root */
-	if (!is_path_reachable(new_mnt, new.dentry, &root))
-		goto out4;
-	root_mp->m_count++; /* pin it so it won't go away */
-	lock_mount_hash();
-	detach_mnt(new_mnt, &parent_path);
-	detach_mnt(root_mnt, &root_parent);
-	if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
-		new_mnt->mnt.mnt_flags |= MNT_LOCKED;
-		root_mnt->mnt.mnt_flags &= ~MNT_LOCKED;
-	}
-	/* mount old root on put_old */
-	attach_mnt(root_mnt, old_mnt, old_mp);
-	/* mount new_root on / */
-	attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
-	touch_mnt_namespace(current->nsproxy->mnt_ns);
-	/* A moved mount should not expire automatically */
-	list_del_init(&new_mnt->mnt_expire);
-	put_mountpoint(root_mp);
-	unlock_mount_hash();
-	chroot_fs_refs(&root, &new);
-	error = 0;
-out4:
-	unlock_mount(old_mp);
-	if (!error) {
-		path_put(&root_parent);
-		path_put(&parent_path);
-	}
-out3:
-	path_put(&root);
-out2:
-	path_put(&old);
-out1:
-	path_put(&new);
-out0:
-	return error;
-}
-
 static void __init init_mount_tree(void)
 {
 	struct vfsmount *mnt;
diff --git a/fs/pivot_root.c b/fs/pivot_root.c
new file mode 100644
index 000000000000..a609b21a1438
--- /dev/null
+++ b/fs/pivot_root.c
@@ -0,0 +1,129 @@
+#include <linux/syscalls.h>
+#include <linux/security.h>
+#include <linux/namei.h>
+#include <linux/fs_struct.h>
+#include "pnode.h"
+#include "internal.h"
+
+/*
+ * pivot_root Semantics:
+ * Moves the root file system of the current process to the directory put_old,
+ * makes new_root as the new root file system of the current process, and sets
+ * root/cwd of all processes which had them on the current root to new_root.
+ *
+ * Restrictions:
+ * The new_root and put_old must be directories, and  must not be on the
+ * same file  system as the current process root. The put_old  must  be
+ * underneath new_root,  i.e. adding a non-zero number of /.. to the string
+ * pointed to by put_old must yield the same directory as new_root. No other
+ * file system may be mounted on put_old. After all, new_root is a mountpoint.
+ *
+ * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
+ * See Documentation/filesystems/ramfs-rootfs-initramfs.txt for alternatives
+ * in this situation.
+ *
+ * Notes:
+ *  - we don't move root/cwd if they are not at the root (reason: if something
+ *    cared enough to change them, it's probably wrong to force them elsewhere)
+ *  - it's okay to pick a root that isn't the root of a file system, e.g.
+ *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
+ *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
+ *    first.
+ */
+SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
+		const char __user *, put_old)
+{
+	struct path new, old, parent_path, root_parent, root;
+	struct mount *new_mnt, *root_mnt, *old_mnt;
+	struct mountpoint *old_mp, *root_mp;
+	int error;
+
+	if (!may_mount())
+		return -EPERM;
+
+	error = user_path_dir(new_root, &new);
+	if (error)
+		goto out0;
+
+	error = user_path_dir(put_old, &old);
+	if (error)
+		goto out1;
+
+	error = security_sb_pivotroot(&old, &new);
+	if (error)
+		goto out2;
+
+	get_fs_root(current->fs, &root);
+	old_mp = lock_mount(&old);
+	error = PTR_ERR(old_mp);
+	if (IS_ERR(old_mp))
+		goto out3;
+
+	error = -EINVAL;
+	new_mnt = real_mount(new.mnt);
+	root_mnt = real_mount(root.mnt);
+	old_mnt = real_mount(old.mnt);
+	if (IS_MNT_SHARED(old_mnt) ||
+		IS_MNT_SHARED(new_mnt->mnt_parent) ||
+		IS_MNT_SHARED(root_mnt->mnt_parent))
+		goto out4;
+	if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
+		goto out4;
+	if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
+		goto out4;
+	error = -ENOENT;
+	if (d_unlinked(new.dentry))
+		goto out4;
+	error = -EBUSY;
+	if (new_mnt == root_mnt || old_mnt == root_mnt)
+		goto out4; /* loop, on the same file system  */
+	error = -EINVAL;
+	if (root.mnt->mnt_root != root.dentry)
+		goto out4; /* not a mountpoint */
+	if (!mnt_has_parent(root_mnt))
+		goto out4; /* not attached */
+	root_mp = root_mnt->mnt_mp;
+	if (new.mnt->mnt_root != new.dentry)
+		goto out4; /* not a mountpoint */
+	if (!mnt_has_parent(new_mnt))
+		goto out4; /* not attached */
+	/* make sure we can reach put_old from new_root */
+	if (!is_path_reachable(old_mnt, old.dentry, &new))
+		goto out4;
+	/* make certain new is below the root */
+	if (!is_path_reachable(new_mnt, new.dentry, &root))
+		goto out4;
+	root_mp->m_count++; /* pin it so it won't go away */
+	lock_mount_hash();
+	detach_mnt(new_mnt, &parent_path);
+	detach_mnt(root_mnt, &root_parent);
+	if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
+		new_mnt->mnt.mnt_flags |= MNT_LOCKED;
+		root_mnt->mnt.mnt_flags &= ~MNT_LOCKED;
+	}
+	/* mount old root on put_old */
+	attach_mnt(root_mnt, old_mnt, old_mp);
+	/* mount new_root on / */
+	attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
+	touch_mnt_namespace(current->nsproxy->mnt_ns);
+	/* A moved mount should not expire automatically */
+	list_del_init(&new_mnt->mnt_expire);
+	put_mountpoint(root_mp);
+	unlock_mount_hash();
+	chroot_fs_refs(&root, &new);
+	error = 0;
+out4:
+	unlock_mount(old_mp);
+	if (!error) {
+		path_put(&root_parent);
+		path_put(&parent_path);
+	}
+out3:
+	path_put(&root);
+out2:
+	path_put(&old);
+out1:
+	path_put(&new);
+out0:
+	return error;
+}
-- 
2.11.1

[toc] | [next] | [standalone]


#1588152

FromTheodore Ts'o <tytso@mit.edu>
Date2017-02-25 17:10 +0100
Message-ID<teN4Z-1WC-1@gated-at.bofh.it>
In reply to#1588019
If you're only going to be removing a single function, instead of
having to export a bunch of previously-static functions, my preference
would be to just insert a pair of #ifdef CONFIG_PIVOT_ROOT_SYSCALL / #endif
statements around the function in question.

Is it worth it to save 600-odd bytes?  Shrug; but if that's what you
are after, I'd suggest doing it the simplest and least-instrusive way
possible.

Cheers,

						- Ted

[toc] | [prev] | [next] | [standalone]


#1588153

FromAl Viro <viro@ZenIV.linux.org.uk>
Date2017-02-25 17:10 +0100
Message-ID<teN4Z-1WC-9@gated-at.bofh.it>
In reply to#1588152
On Sat, Feb 25, 2017 at 10:22:21AM -0500, Theodore Ts'o wrote:
> If you're only going to be removing a single function, instead of
> having to export a bunch of previously-static functions, my preference
> would be to just insert a pair of #ifdef CONFIG_PIVOT_ROOT_SYSCALL / #endif
> statements around the function in question.

Quite.  In this form: NAK for the reasons above.

[toc] | [prev] | [next] | [standalone]


#1588254 — [PATCH 0/1] fs: Support compiling out the pivot_root syscall

FromBrian Ashworth <bosrsf04@gmail.com>
Date2017-02-26 02:10 +0100
Subject[PATCH 0/1] fs: Support compiling out the pivot_root syscall
Message-ID<teVvA-7L7-9@gated-at.bofh.it>
In reply to#1588153
This patch will allow for the pivot_root syscall to be made
optional. Based on feedback, this patch uses an ifdef in the
source rather than conditional compilation in the Makefile.

The pivot_root syscall is not needed on systems that do not use
any intermediate filesystem. Allowing for pivot_root to be
ommitted from the kernel will aid in the tinification efforts.

Brian Ashworth (1):
  Allows for the pivot_root syscall to be optional

 fs/namespace.c  |  2 ++
 init/Kconfig    | 10 ++++++++++
 kernel/sys_ni.c |  1 +
 3 files changed, 13 insertions(+)

-- 
2.11.1

[toc] | [prev] | [next] | [standalone]


#1588255 — [PATCH 1/1] fs: Allows for the pivot_root syscall to be optional

FromBrian Ashworth <bosrsf04@gmail.com>
Date2017-02-26 02:10 +0100
Subject[PATCH 1/1] fs: Allows for the pivot_root syscall to be optional
Message-ID<teVvA-7L7-7@gated-at.bofh.it>
In reply to#1588254
The pivot_root syscall is not needed on systems that do not use
any intermediate filesystem. Allowing for pivot_root to be
ommitted from the kernel will aid in the tinification efforts.

Without CONFIG_PIVOT_ROOT_SYSCALL set
add/remove: 0/2 grow/shrink: 1/0 up/down: 45/-707 (-662)
function                                     old     new   delta
attach_recursive_mnt                         349     394     +45
attach_mnt                                    71       -     -71
sys_pivot_root                               636       -    -636
Total: Before=1899893, After=1899231, chg -0.03%

Signed-off-by: Brian Ashworth <bosrsf04@gmail.com>
---
 fs/namespace.c  |  2 ++
 init/Kconfig    | 10 ++++++++++
 kernel/sys_ni.c |  1 +
 3 files changed, 13 insertions(+)

diff --git a/fs/namespace.c b/fs/namespace.c
index 487ba30bb5c6..5e24a08bfb36 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3058,6 +3058,7 @@ bool path_is_under(const struct path *path1, const struct path *path2)
 }
 EXPORT_SYMBOL(path_is_under);
 
+#ifdef CONFIG_PIVOT_ROOT_SYSCALL
 /*
  * pivot_root Semantics:
  * Moves the root file system of the current process to the directory put_old,
@@ -3180,6 +3181,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 out0:
 	return error;
 }
+#endif  /* CONFIG_PIVOT_ROOT_SYSCALL */
 
 static void __init init_mount_tree(void)
 {
diff --git a/init/Kconfig b/init/Kconfig
index 8c39615165b7..4ea9ab25ec30 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1450,6 +1450,16 @@ config SYSCTL_SYSCALL
 
 	  If unsure say N here.
 
+config PIVOT_ROOT_SYSCALL
+	bool "Pivot_root syscall support" if EXPERT
+	default y
+	help
+	  pivot_root is a system call that allows the root to be moved and
+	  replaced by another root. This is needed for intermediate file
+	  systems such as initrd.
+
+	  If unsure say Y here.
+
 config POSIX_TIMERS
 	bool "Posix Clocks & timers" if EXPERT
 	default y
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 8acef8576ce9..7bd207571f87 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -178,6 +178,7 @@ cond_syscall(sys_setfsgid);
 cond_syscall(sys_capget);
 cond_syscall(sys_capset);
 cond_syscall(sys_copy_file_range);
+cond_syscall(sys_pivot_root);
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read);
-- 
2.11.1

[toc] | [prev] | [next] | [standalone]


#1588257 — Re: [PATCH 1/1] fs: Allows for the pivot_root syscall to be optional

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2017-02-26 02:50 +0100
SubjectRe: [PATCH 1/1] fs: Allows for the pivot_root syscall to be optional
Message-ID<teW8h-83d-1@gated-at.bofh.it>
In reply to#1588255
On Sat, 25 Feb 2017, Brian Ashworth wrote:

> The pivot_root syscall is not needed on systems that do not use
> any intermediate filesystem. Allowing for pivot_root to be
> ommitted from the kernel will aid in the tinification efforts.
> 
> Without CONFIG_PIVOT_ROOT_SYSCALL set
> add/remove: 0/2 grow/shrink: 1/0 up/down: 45/-707 (-662)
> function                                     old     new   delta
> attach_recursive_mnt                         349     394     +45
> attach_mnt                                    71       -     -71
> sys_pivot_root                               636       -    -636
> Total: Before=1899893, After=1899231, chg -0.03%

A -0.03% size difference doesn't seem much.  To bring up a more 
realistic scenario for tinification statistics, you could start from 
"make tinyconfig" instead.

> Signed-off-by: Brian Ashworth <bosrsf04@gmail.com>
> ---
>  fs/namespace.c  |  2 ++
>  init/Kconfig    | 10 ++++++++++
>  kernel/sys_ni.c |  1 +
>  3 files changed, 13 insertions(+)

I agree that this is a much more interesting diffstat than the previous 
one.

Acked-by: Nicolas Pitre <nico@linaro.org>


> diff --git a/fs/namespace.c b/fs/namespace.c
> index 487ba30bb5c6..5e24a08bfb36 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -3058,6 +3058,7 @@ bool path_is_under(const struct path *path1, const struct path *path2)
>  }
>  EXPORT_SYMBOL(path_is_under);
>  
> +#ifdef CONFIG_PIVOT_ROOT_SYSCALL
>  /*
>   * pivot_root Semantics:
>   * Moves the root file system of the current process to the directory put_old,
> @@ -3180,6 +3181,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
>  out0:
>  	return error;
>  }
> +#endif  /* CONFIG_PIVOT_ROOT_SYSCALL */
>  
>  static void __init init_mount_tree(void)
>  {
> diff --git a/init/Kconfig b/init/Kconfig
> index 8c39615165b7..4ea9ab25ec30 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1450,6 +1450,16 @@ config SYSCTL_SYSCALL
>  
>  	  If unsure say N here.
>  
> +config PIVOT_ROOT_SYSCALL
> +	bool "Pivot_root syscall support" if EXPERT
> +	default y
> +	help
> +	  pivot_root is a system call that allows the root to be moved and
> +	  replaced by another root. This is needed for intermediate file
> +	  systems such as initrd.
> +
> +	  If unsure say Y here.
> +
>  config POSIX_TIMERS
>  	bool "Posix Clocks & timers" if EXPERT
>  	default y
> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
> index 8acef8576ce9..7bd207571f87 100644
> --- a/kernel/sys_ni.c
> +++ b/kernel/sys_ni.c
> @@ -178,6 +178,7 @@ cond_syscall(sys_setfsgid);
>  cond_syscall(sys_capget);
>  cond_syscall(sys_capset);
>  cond_syscall(sys_copy_file_range);
> +cond_syscall(sys_pivot_root);
>  
>  /* arch-specific weak syscall entries */
>  cond_syscall(sys_pciconfig_read);
> -- 
> 2.11.1
> 
> 

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web