aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-11-05 12:40:31 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2019-03-20 18:49:06 -0400
commit44dfd84a6d54a675e35ab618d9fab47b36cb78cd (patch)
tree6b5542f217686066119c9bdfed2182e2c2a6d4a9
parent2db154b3ea8e14b04fee23e3fdfd5e9d17fbc6ae (diff)
teach move_mount(2) to work with OPEN_TREE_CLONE
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>
-rw-r--r--fs/namespace.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index dc600f53de9d..1e72d19fa4f8 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1842,10 +1842,16 @@ void dissolve_on_fput(struct vfsmount *mnt)
1842 namespace_lock(); 1842 namespace_lock();
1843 lock_mount_hash(); 1843 lock_mount_hash();
1844 ns = real_mount(mnt)->mnt_ns; 1844 ns = real_mount(mnt)->mnt_ns;
1845 umount_tree(real_mount(mnt), UMOUNT_CONNECTED); 1845 if (ns) {
1846 if (is_anon_ns(ns))
1847 umount_tree(real_mount(mnt), UMOUNT_CONNECTED);
1848 else
1849 ns = NULL;
1850 }
1846 unlock_mount_hash(); 1851 unlock_mount_hash();
1847 namespace_unlock(); 1852 namespace_unlock();
1848 free_mnt_ns(ns); 1853 if (ns)
1854 free_mnt_ns(ns);
1849} 1855}
1850 1856
1851void drop_collected_mounts(struct vfsmount *mnt) 1857void drop_collected_mounts(struct vfsmount *mnt)
@@ -2081,6 +2087,10 @@ static int attach_recursive_mnt(struct mount *source_mnt,
2081 attach_mnt(source_mnt, dest_mnt, dest_mp); 2087 attach_mnt(source_mnt, dest_mnt, dest_mp);
2082 touch_mnt_namespace(source_mnt->mnt_ns); 2088 touch_mnt_namespace(source_mnt->mnt_ns);
2083 } else { 2089 } else {
2090 if (source_mnt->mnt_ns) {
2091 /* move from anon - the caller will destroy */
2092 list_del_init(&source_mnt->mnt_ns->list);
2093 }
2084 mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt); 2094 mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
2085 commit_tree(source_mnt); 2095 commit_tree(source_mnt);
2086 } 2096 }
@@ -2539,13 +2549,37 @@ static inline int tree_contains_unbindable(struct mount *mnt)
2539 return 0; 2549 return 0;
2540} 2550}
2541 2551
2552/*
2553 * Check that there aren't references to earlier/same mount namespaces in the
2554 * specified subtree. Such references can act as pins for mount namespaces
2555 * that aren't checked by the mount-cycle checking code, thereby allowing
2556 * cycles to be made.
2557 */
2558static bool check_for_nsfs_mounts(struct mount *subtree)
2559{
2560 struct mount *p;
2561 bool ret = false;
2562
2563 lock_mount_hash();
2564 for (p = subtree; p; p = next_mnt(p, subtree))
2565 if (mnt_ns_loop(p->mnt.mnt_root))
2566 goto out;
2567
2568 ret = true;
2569out:
2570 unlock_mount_hash();
2571 return ret;
2572}
2573
2542static int do_move_mount(struct path *old_path, struct path *new_path) 2574static int do_move_mount(struct path *old_path, struct path *new_path)
2543{ 2575{
2544 struct path parent_path = {.mnt = NULL, .dentry = NULL}; 2576 struct path parent_path = {.mnt = NULL, .dentry = NULL};
2577 struct mnt_namespace *ns;
2545 struct mount *p; 2578 struct mount *p;
2546 struct mount *old; 2579 struct mount *old;
2547 struct mountpoint *mp; 2580 struct mountpoint *mp;
2548 int err; 2581 int err;
2582 bool attached;
2549 2583
2550 mp = lock_mount(new_path); 2584 mp = lock_mount(new_path);
2551 if (IS_ERR(mp)) 2585 if (IS_ERR(mp))
@@ -2553,12 +2587,19 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
2553 2587
2554 old = real_mount(old_path->mnt); 2588 old = real_mount(old_path->mnt);
2555 p = real_mount(new_path->mnt); 2589 p = real_mount(new_path->mnt);
2590 attached = mnt_has_parent(old);
2591 ns = old->mnt_ns;
2556 2592
2557 err = -EINVAL; 2593 err = -EINVAL;
2558 if (!check_mnt(p) || !check_mnt(old)) 2594 /* The mountpoint must be in our namespace. */
2595 if (!check_mnt(p))
2559 goto out; 2596 goto out;
2560 2597
2561 if (!mnt_has_parent(old)) 2598 /* The thing moved should be either ours or completely unattached. */
2599 if (attached && !check_mnt(old))
2600 goto out;
2601
2602 if (!attached && !is_anon_ns(ns))
2562 goto out; 2603 goto out;
2563 2604
2564 if (old->mnt.mnt_flags & MNT_LOCKED) 2605 if (old->mnt.mnt_flags & MNT_LOCKED)
@@ -2573,7 +2614,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
2573 /* 2614 /*
2574 * Don't move a mount residing in a shared parent. 2615 * Don't move a mount residing in a shared parent.
2575 */ 2616 */
2576 if (IS_MNT_SHARED(old->mnt_parent)) 2617 if (attached && IS_MNT_SHARED(old->mnt_parent))
2577 goto out; 2618 goto out;
2578 /* 2619 /*
2579 * Don't move a mount tree containing unbindable mounts to a destination 2620 * Don't move a mount tree containing unbindable mounts to a destination
@@ -2582,12 +2623,14 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
2582 if (IS_MNT_SHARED(p) && tree_contains_unbindable(old)) 2623 if (IS_MNT_SHARED(p) && tree_contains_unbindable(old))
2583 goto out; 2624 goto out;
2584 err = -ELOOP; 2625 err = -ELOOP;
2626 if (!check_for_nsfs_mounts(old))
2627 goto out;
2585 for (; mnt_has_parent(p); p = p->mnt_parent) 2628 for (; mnt_has_parent(p); p = p->mnt_parent)
2586 if (p == old) 2629 if (p == old)
2587 goto out; 2630 goto out;
2588 2631
2589 err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp, 2632 err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp,
2590 &parent_path); 2633 attached ? &parent_path : NULL);
2591 if (err) 2634 if (err)
2592 goto out; 2635 goto out;
2593 2636
@@ -2596,8 +2639,11 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
2596 list_del_init(&old->mnt_expire); 2639 list_del_init(&old->mnt_expire);
2597out: 2640out:
2598 unlock_mount(mp); 2641 unlock_mount(mp);
2599 if (!err) 2642 if (!err) {
2600 path_put(&parent_path); 2643 path_put(&parent_path);
2644 if (!attached)
2645 free_mnt_ns(ns);
2646 }
2601 return err; 2647 return err;
2602} 2648}
2603 2649
@@ -3289,6 +3335,8 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
3289 3335
3290/* 3336/*
3291 * Move a mount from one place to another. 3337 * Move a mount from one place to another.
3338 * In combination with open_tree(OPEN_TREE_CLONE [| AT_RECURSIVE]) it can be
3339 * used to copy a mount subtree.
3292 * 3340 *
3293 * Note the flags value is a combination of MOVE_MOUNT_* flags. 3341 * Note the flags value is a combination of MOVE_MOUNT_* flags.
3294 */ 3342 */