From 948e604aca8af30490accf7d46d44814ffa26f80 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 8 Oct 2026 09:33:33 +0000 Subject: [PATCH] mount: refuse setns() with a shared fs_struct again mntns_install() refuses to switch the mount namespace of a task that shares its fs_struct, since root and cwd of the others would move to a namespace they are not in. It looks at nsset->fs for that. If more than the mount namespace is asked for, that is a private copy made by prepare_nsset(), which has one user by definition; commit_nsset() then writes root and cwd of the copy to the fs_struct of the task. A thread of a process with two threads, pidfd of a task in another mount namespace: setns(pidfd, CLONE_NEWNS) -EINVAL setns(pidfd, CLONE_NEWNS | CLONE_NEWUTS) 0 and after the second call the other thread, still in the old mount namespace, has lost its cwd (/tmp became /) and sees the mounts of the other namespace under /. Look at the fs_struct that is going to be changed. The second call then fails with -EINVAL like the first one. Fixes: 303cc571d107 ("nsproxy: attach to namespaces via pidfds") Cc: stable@vger.kernel.org # v5.8+ Signed-off-by: Josef Bacik Signed-off-by: Christian Brauner (Amutable) --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index e5feb4e48290..25e196c05126 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -6727,7 +6727,7 @@ static int mntns_install(struct nsset *nsset, struct ns_common *ns) if (is_anon_ns(mnt_ns)) return -EINVAL; - if (fs->users != 1) + if (current->fs->users != 1) return -EINVAL; get_mnt_ns(mnt_ns);