summaryrefslogtreecommitdiff
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2025-02-25 11:15:46 +0100
committerChristian Brauner <brauner@kernel.org>2025-03-04 09:29:54 +0100
commit064fe6e233e8d54d1b26bfabc38ed96d798c7416 (patch)
treee00765c0bac8b7214cfe8e64e85486f491b4ed5f /fs/namespace.c
parent99b6a1dee086e69d242c268a547714cae71d9e59 (diff)
mount: handle mount propagation for detached mount trees
In commit ee2e3f50629f ("mount: fix mounting of detached mounts onto targets that reside on shared mounts") I fixed a bug where propagating the source mount tree of an anonymous mount namespace into a target mount tree of a non-anonymous mount namespace could be used to trigger an integer overflow in the non-anonymous mount namespace causing any new mounts to fail. The cause of this was that the propagation algorithm was unable to recognize mounts from the source mount tree that were already propagated into the target mount tree and then reappeared as propagation targets when walking the destination propagation mount tree. When fixing this I disabled mount propagation into anonymous mount namespaces. Make it possible for anonymous mount namespace to receive mount propagation events correctly. This is no also a correctness issue now that we allow mounting detached mount trees onto detached mount trees. Mark the source anonymous mount namespace with MNTNS_PROPAGATING indicating that all mounts belonging to this mount namespace are currently in the process of being propagated and make the propagation algorithm discard those if they appear as propagation targets. Link: https://lore.kernel.org/r/20250225-work-mount-propagation-v1-1-e6e3724500eb@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index a7da41e81673..59894e3f3e68 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3536,13 +3536,6 @@ static int do_move_mount(struct path *old_path,
if (!may_use_mount(p))
goto out;
- /*
- * Don't allow moving an attached mount tree to an anonymous
- * mount tree.
- */
- if (!is_anon_ns(ns) && is_anon_ns(p->mnt_ns))
- goto out;
-
/* The thing moved must be mounted... */
if (!is_mounted(&old->mnt))
goto out;
@@ -3551,15 +3544,31 @@ static int do_move_mount(struct path *old_path,
if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
goto out;
- /*
- * Ending up with two files referring to the root of the same
- * anonymous mount namespace would cause an error as this would
- * mean trying to move the same mount twice into the mount tree
- * which would be rejected later. But be explicit about it right
- * here.
- */
- if (is_anon_ns(ns) && is_anon_ns(p->mnt_ns) && ns == p->mnt_ns)
+ if (is_anon_ns(ns)) {
+ /*
+ * Ending up with two files referring to the root of the
+ * same anonymous mount namespace would cause an error
+ * as this would mean trying to move the same mount
+ * twice into the mount tree which would be rejected
+ * later. But be explicit about it right here.
+ */
+ if ((is_anon_ns(p->mnt_ns) && ns == p->mnt_ns))
+ goto out;
+
+ /*
+ * If this is an anonymous mount tree ensure that mount
+ * propagation can detect mounts that were just
+ * propagated to the target mount tree so we don't
+ * propagate onto them.
+ */
+ ns->mntns_flags |= MNTNS_PROPAGATING;
+ } else if (is_anon_ns(p->mnt_ns)) {
+ /*
+ * Don't allow moving an attached mount tree to an
+ * anonymous mount tree.
+ */
goto out;
+ }
if (old->mnt.mnt_flags & MNT_LOCKED)
goto out;
@@ -3603,6 +3612,9 @@ static int do_move_mount(struct path *old_path,
if (err)
goto out;
+ if (is_anon_ns(ns))
+ ns->mntns_flags &= ~MNTNS_PROPAGATING;
+
/* if the mount is moved, it should no longer be expire
* automatically */
list_del_init(&old->mnt_expire);