From: Alan Jenkins <alan.christopher.jenkins@gmail.com>
To: David Howells <dhowells@redhat.com>, viro@zeniv.linux.org.uk
Cc: linux-fsdevel@vger.kernel.org, torvalds@linux-foundation.org,
ebiederm@xmission.com, linux-security-module@vger.kernel.org
Subject: Re: [PATCH 03/10] teach move_mount(2) to work with OPEN_TREE_CLONE
Date: Wed, 20 Feb 2019 18:59:26 +0000 [thread overview]
Message-ID: <0c084993-d45d-20b3-2709-38bbd12c5936@gmail.com> (raw)
In-Reply-To: <155059612649.17079.7287713053194562461.stgit@warthog.procyon.org.uk>
On 19/02/2019 17:08, David Howells wrote:
> Allow a detached tree created by open_tree(..., OPEN_TREE_CLONE) to be
> attached by move_mount(2).
>
> If by the time of final fput() of OPEN_TREE_CLONE-opened file its tree is
> not detached anymore, it won't be dissolved. move_mount(2) is adjusted
> to handle detached source.
>
> That gives us equivalents of mount --bind and mount --rbind.
> Thanks also to Alan Jenkins<alan.christopher.jenkins@gmail.com> for
> providing a whole bunch of ways to break things using this interface.
>
> Signed-off-by: Al Viro<viro@zeniv.linux.org.uk>
> Signed-off-by: David Howells<dhowells@redhat.com>
> Signed-off-by: Al Viro<viro@zeniv.linux.org.uk>
> ---
>
> fs/namespace.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 55 insertions(+), 7 deletions(-)
>
> diff --git a/fs/namespace.c b/fs/namespace.c
> index f10122028a11..56423c60ac7e 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -1840,10 +1840,16 @@ void dissolve_on_fput(struct vfsmount *mnt)
> namespace_lock();
> lock_mount_hash();
> ns = real_mount(mnt)->mnt_ns;
> - umount_tree(real_mount(mnt), UMOUNT_CONNECTED);
> + if (ns) {
> + if (is_anon_ns(ns))
> + umount_tree(real_mount(mnt), UMOUNT_CONNECTED);
> + else
> + ns = NULL;
> + }
> unlock_mount_hash();
> namespace_unlock();
> - free_mnt_ns(ns);
> + if (ns)
> + free_mnt_ns(ns);
> }
>
> void drop_collected_mounts(struct vfsmount *mnt)
> @@ -2079,6 +2085,10 @@ static int attach_recursive_mnt(struct mount *source_mnt,
> attach_mnt(source_mnt, dest_mnt, dest_mp);
> touch_mnt_namespace(source_mnt->mnt_ns);
> } else {
> + if (source_mnt->mnt_ns) {
> + /* move from anon - the caller will destroy */
> + list_del_init(&source_mnt->mnt_ns->list);
> + }
> mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
> commit_tree(source_mnt);
> }
> @@ -2537,13 +2547,37 @@ static inline int tree_contains_unbindable(struct mount *mnt)
> return 0;
> }
>
> +/*
> + * Check that there aren't references to earlier/same mount namespaces in the
> + * specified subtree. Such references can act as pins for mount namespaces
> + * that aren't checked by the mount-cycle checking code, thereby allowing
> + * cycles to be made.
> + */
> +static bool check_for_nsfs_mounts(struct mount *subtree)
> +{
> + struct mount *p;
> + bool ret = false;
> +
> + lock_mount_hash();
> + for (p = subtree; p; p = next_mnt(p, subtree))
> + if (mnt_ns_loop(p->mnt.mnt_root))
> + goto out;
> +
> + ret = true;
> +out:
> + unlock_mount_hash();
> + return ret;
> +}
> +
> static int do_move_mount(struct path *old_path, struct path *new_path)
> {
> struct path parent_path = {.mnt = NULL, .dentry = NULL};
> + struct mnt_namespace *ns;
> struct mount *p;
> struct mount *old;
> struct mountpoint *mp;
> int err;
> + bool attached;
>
> mp = lock_mount(new_path);
> if (IS_ERR(mp))
> @@ -2551,12 +2585,19 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
>
> old = real_mount(old_path->mnt);
> p = real_mount(new_path->mnt);
> + attached = mnt_has_parent(old);
> + ns = old->mnt_ns;
>
> err = -EINVAL;
> - if (!check_mnt(p) || !check_mnt(old))
> + /* The mountpoint must be in our namespace. */
> + if (!check_mnt(p))
> goto out;
>
> - if (!mnt_has_parent(old))
> + /* The thing moved should be either ours or completely unattached. */
> + if (attached && !check_mnt(old))
> + goto out;
> +
> + if (!attached && !is_anon_ns(ns))
I think this is missing a check for ns != NULL, before passing it to
is_anon_ns().
E.g. in case I called umount2(old_path, MNT_DETACH) beforehand.
> goto out;
>
> if (old->mnt.mnt_flags & MNT_LOCKED)
> @@ -2571,7 +2612,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
> /*
> * Don't move a mount residing in a shared parent.
> */
> - if (IS_MNT_SHARED(old->mnt_parent))
> + if (attached && IS_MNT_SHARED(old->mnt_parent))
> goto out;
> /*
> * Don't move a mount tree containing unbindable mounts to a destination
> @@ -2580,12 +2621,14 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
> if (IS_MNT_SHARED(p) && tree_contains_unbindable(old))
> goto out;
> err = -ELOOP;
> + if (!check_for_nsfs_mounts(old))
> + goto out;
> for (; mnt_has_parent(p); p = p->mnt_parent)
> if (p == old)
> goto out;
>
> err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp,
> - &parent_path);
> + attached ? &parent_path : NULL);
> if (err)
> goto out;
>
> @@ -2594,8 +2637,11 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
> list_del_init(&old->mnt_expire);
> out:
> unlock_mount(mp);
> - if (!err)
> + if (!err) {
> path_put(&parent_path);
> + if (!attached)
> + free_mnt_ns(ns);
> + }
> return err;
> }
>
> @@ -3289,6 +3335,8 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
>
> /*
> * Move a mount from one place to another.
> + * In combination with open_tree(OPEN_TREE_CLONE [| AT_RECURSIVE]) it can be
> + * used to copy a mount subtree.
> *
> * Note the flags value is a combination of MOVE_MOUNT_* flags.
> */
>
>
next prev parent reply other threads:[~2019-02-20 18:59 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-19 17:08 [PATCH 00/10] VFS: Provide new mount UAPI David Howells
2019-02-19 17:08 ` [PATCH 01/10] vfs: syscall: Add open_tree(2) to reference or clone a mount David Howells
2019-02-19 17:08 ` [PATCH 02/10] vfs: syscall: Add move_mount(2) to move mounts around David Howells
2019-02-20 12:32 ` Alan Jenkins
2019-02-20 12:41 ` Alan Jenkins
2019-02-20 16:23 ` Jann Horn
2019-07-08 12:02 ` Tetsuo Handa
2019-07-08 13:18 ` Al Viro
2019-07-08 17:12 ` Eric W. Biederman
2019-07-08 18:01 ` Al Viro
2019-07-08 18:13 ` Al Viro
2019-07-08 20:21 ` Al Viro
2019-07-09 0:13 ` Eric W. Biederman
2019-07-09 10:51 ` Tetsuo Handa
2019-07-22 10:12 ` Tetsuo Handa
2019-07-23 4:16 ` John Johansen
2019-07-23 13:45 ` Tetsuo Handa
2019-08-06 10:43 ` Tetsuo Handa
2019-08-22 3:51 ` [RFC][PATCH] fix d_absolute_path() interplay with fsmount() Al Viro
2019-08-30 10:11 ` Tetsuo Handa
2019-07-23 21:45 ` [PATCH 02/10] vfs: syscall: Add move_mount(2) to move mounts around James Morris
2019-07-23 23:30 ` Al Viro
2019-02-19 17:08 ` [PATCH 03/10] teach move_mount(2) to work with OPEN_TREE_CLONE David Howells
2019-02-20 18:59 ` Alan Jenkins [this message]
2019-02-26 17:45 ` Alan Jenkins
2019-02-19 17:08 ` [PATCH 04/10] Make anon_inodes unconditional David Howells
2019-02-19 17:09 ` [PATCH 05/10] vfs: syscall: Add fsopen() to prepare for superblock creation David Howells
2019-02-19 17:09 ` [PATCH 06/10] vfs: Implement logging through fs_context David Howells
2019-02-19 17:09 ` [PATCH 07/10] vfs: syscall: Add fsconfig() for configuring and managing a context David Howells
2019-02-19 17:09 ` [PATCH 08/10] vfs: syscall: Add fsmount() to create a mount for a superblock David Howells
2019-02-19 17:09 ` [PATCH 09/10] vfs: syscall: Add fspick() to select a superblock for reconfiguration David Howells
2019-02-19 17:09 ` [PATCH 10/10] vfs: Add a sample program for the new mount API David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0c084993-d45d-20b3-2709-38bbd12c5936@gmail.com \
--to=alan.christopher.jenkins@gmail.com \
--cc=dhowells@redhat.com \
--cc=ebiederm@xmission.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).