Skip to content

Commit 290da20

Browse files
author
Al Viro
committed
do_move_mount(): split the checks in subtree-of-our-ns and entire-anon cases
... and fix the breakage in anon-to-anon case. There are two cases acceptable for do_move_mount() and mixing checks for those is making things hard to follow. One case is move of a subtree in caller's namespace. * source and destination must be in caller's namespace * source must be detachable from parent Another is moving the entire anon namespace elsewhere * source must be the root of anon namespace * target must either in caller's namespace or in a suitable anon namespace (see may_use_mount() for details). * target must not be in the same namespace as source. It's really easier to follow if tests are *not* mixed together... Reviewed-by: Christian Brauner <brauner@kernel.org> Fixes: 3b5260d ("Don't propagate mounts into detached trees") Reported-by: Allison Karlitskaya <lis@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 4954346 commit 290da20

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

fs/namespace.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3656,37 +3656,41 @@ static int do_move_mount(struct path *old_path,
36563656
ns = old->mnt_ns;
36573657

36583658
err = -EINVAL;
3659-
if (!may_use_mount(p))
3660-
goto out;
3661-
36623659
/* The thing moved must be mounted... */
36633660
if (!is_mounted(&old->mnt))
36643661
goto out;
36653662

3666-
/* ... and either ours or the root of anon namespace */
3667-
if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
3668-
goto out;
3669-
3670-
if (is_anon_ns(ns) && ns == p->mnt_ns) {
3663+
if (check_mnt(old)) {
3664+
/* if the source is in our namespace... */
3665+
/* ... it should be detachable from parent */
3666+
if (!mnt_has_parent(old) || IS_MNT_LOCKED(old))
3667+
goto out;
3668+
/* ... and the target should be in our namespace */
3669+
if (!check_mnt(p))
3670+
goto out;
3671+
} else {
36713672
/*
3672-
* Ending up with two files referring to the root of the
3673-
* same anonymous mount namespace would cause an error
3674-
* as this would mean trying to move the same mount
3675-
* twice into the mount tree which would be rejected
3676-
* later. But be explicit about it right here.
3673+
* otherwise the source must be the root of some anon namespace.
3674+
* AV: check for mount being root of an anon namespace is worth
3675+
* an inlined predicate...
36773676
*/
3678-
goto out;
3679-
} else if (is_anon_ns(p->mnt_ns)) {
3677+
if (!is_anon_ns(ns) || mnt_has_parent(old))
3678+
goto out;
36803679
/*
3681-
* Don't allow moving an attached mount tree to an
3682-
* anonymous mount tree.
3680+
* Bail out early if the target is within the same namespace -
3681+
* subsequent checks would've rejected that, but they lose
3682+
* some corner cases if we check it early.
36833683
*/
3684-
goto out;
3684+
if (ns == p->mnt_ns)
3685+
goto out;
3686+
/*
3687+
* Target should be either in our namespace or in an acceptable
3688+
* anon namespace, sensu check_anonymous_mnt().
3689+
*/
3690+
if (!may_use_mount(p))
3691+
goto out;
36853692
}
36863693

3687-
if (old->mnt.mnt_flags & MNT_LOCKED)
3688-
goto out;
3689-
36903694
if (!path_mounted(old_path))
36913695
goto out;
36923696

0 commit comments

Comments
 (0)