mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Don't propagate mounts into detached trees
All versions up to 6.14 did not propagate mount events into detached tree. Shortly after 6.14 a merge of vfs-6.15-rc1.mount.namespace (130e696aa6) has changed that. Unfortunately, that has caused userland regressions (reported in https://lore.kernel.org/all/CAOYeF9WQhFDe+BGW=Dp5fK8oRy5AgZ6zokVyTj1Wp4EUiYgt4w@mail.gmail.com/) Straight revert wouldn't be an option - in particular, the variant in 6.14 had a bug that got fixed ind1ddc6f1d9("fix IS_MNT_PROPAGATING uses") and we don't want to bring the bug back. This is a modification of manual revert posted by Christian, with changes needed to avoid reintroducing the breakage in scenario described ind1ddc6f1d9. Cc: stable@vger.kernel.org Reported-by: Allison Karlitskaya <lis@redhat.com> Tested-by: Allison Karlitskaya <lis@redhat.com> Acked-by: Christian Brauner <brauner@kernel.org> Co-developed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									d1ddc6f1d9
								
							
						
					
					
						commit
						3b5260d12b
					
				
					 3 changed files with 4 additions and 20 deletions
				
			
		| 
						 | 
					@ -7,10 +7,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct list_head notify_list;
 | 
					extern struct list_head notify_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef __u32 __bitwise mntns_flags_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MNTNS_PROPAGATING	((__force mntns_flags_t)(1 << 0))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mnt_namespace {
 | 
					struct mnt_namespace {
 | 
				
			||||||
	struct ns_common	ns;
 | 
						struct ns_common	ns;
 | 
				
			||||||
	struct mount *	root;
 | 
						struct mount *	root;
 | 
				
			||||||
| 
						 | 
					@ -37,7 +33,6 @@ struct mnt_namespace {
 | 
				
			||||||
	struct rb_node		mnt_ns_tree_node; /* node in the mnt_ns_tree */
 | 
						struct rb_node		mnt_ns_tree_node; /* node in the mnt_ns_tree */
 | 
				
			||||||
	struct list_head	mnt_ns_list; /* entry in the sequential list of mounts namespace */
 | 
						struct list_head	mnt_ns_list; /* entry in the sequential list of mounts namespace */
 | 
				
			||||||
	refcount_t		passive; /* number references not pinning @mounts */
 | 
						refcount_t		passive; /* number references not pinning @mounts */
 | 
				
			||||||
	mntns_flags_t		mntns_flags;
 | 
					 | 
				
			||||||
} __randomize_layout;
 | 
					} __randomize_layout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mnt_pcp {
 | 
					struct mnt_pcp {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3648,7 +3648,7 @@ static int do_move_mount(struct path *old_path,
 | 
				
			||||||
	if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
 | 
						if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (is_anon_ns(ns)) {
 | 
						if (is_anon_ns(ns) && ns == p->mnt_ns) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Ending up with two files referring to the root of the
 | 
							 * Ending up with two files referring to the root of the
 | 
				
			||||||
		 * same anonymous mount namespace would cause an error
 | 
							 * same anonymous mount namespace would cause an error
 | 
				
			||||||
| 
						 | 
					@ -3656,16 +3656,7 @@ static int do_move_mount(struct path *old_path,
 | 
				
			||||||
		 * twice into the mount tree which would be rejected
 | 
							 * twice into the mount tree which would be rejected
 | 
				
			||||||
		 * later. But be explicit about it right here.
 | 
							 * later. But be explicit about it right here.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if ((is_anon_ns(p->mnt_ns) && ns == p->mnt_ns))
 | 
							goto out;
 | 
				
			||||||
			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)) {
 | 
						} else if (is_anon_ns(p->mnt_ns)) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Don't allow moving an attached mount tree to an
 | 
							 * Don't allow moving an attached mount tree to an
 | 
				
			||||||
| 
						 | 
					@ -3722,8 +3713,6 @@ static int do_move_mount(struct path *old_path,
 | 
				
			||||||
	if (attached)
 | 
						if (attached)
 | 
				
			||||||
		put_mountpoint(old_mp);
 | 
							put_mountpoint(old_mp);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	if (is_anon_ns(ns))
 | 
					 | 
				
			||||||
		ns->mntns_flags &= ~MNTNS_PROPAGATING;
 | 
					 | 
				
			||||||
	unlock_mount(mp);
 | 
						unlock_mount(mp);
 | 
				
			||||||
	if (!err) {
 | 
						if (!err) {
 | 
				
			||||||
		if (attached) {
 | 
							if (attached) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -231,8 +231,8 @@ static int propagate_one(struct mount *m, struct mountpoint *dest_mp)
 | 
				
			||||||
	/* skip if mountpoint isn't visible in m */
 | 
						/* skip if mountpoint isn't visible in m */
 | 
				
			||||||
	if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root))
 | 
						if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	/* skip if m is in the anon_ns we are emptying */
 | 
						/* skip if m is in the anon_ns */
 | 
				
			||||||
	if (m->mnt_ns->mntns_flags & MNTNS_PROPAGATING)
 | 
						if (is_anon_ns(m->mnt_ns))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (peers(m, last_dest)) {
 | 
						if (peers(m, last_dest)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue