Skip to content

Commit 7da4add

Browse files
committed
fs/fhandle.c: fix a race in call of has_locked_children()
JIRA: https://issues.redhat.com/browse/RHEL-113598 CVE: CVE-2025-38306 Conflicts: 1) A context diff with the has_locked_children() hunk and a merge conflict with clone_private_mount() hunk due to missing upstream commit db04662 ("fs: allow detached mounts in clone_private_mount()"). 2) A merge conflict with the __do_loopback() hunk due to missing upstream commit 9ed72af ("fs: add may_copy_tree()"). commit 1f282cd Author: Al Viro <viro@zeniv.linux.org.uk> Date: Sun, 1 Jun 2025 14:23:52 -0400 fs/fhandle.c: fix a race in call of has_locked_children() may_decode_fh() is calling has_locked_children() while holding no locks. That's an oopsable race... The rest of the callers are safe since they are holding namespace_sem and are guaranteed a positive refcount on the mount in question. Rename the current has_locked_children() to __has_locked_children(), make it static and switch the fs/namespace.c users to it. Make has_locked_children() a wrapper for __has_locked_children(), calling the latter under read_seqlock_excl(&mount_lock). Reviewed-by: Christian Brauner <brauner@kernel.org> Reviewed-by: Jeff Layton <jlayton@kernel.org> Fixes: 620c266 ("fhandle: relax open_by_handle_at() permission checks") Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Waiman Long <longman@redhat.com>
1 parent 42a425b commit 7da4add

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

fs/namespace.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,7 +2232,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
22322232
namespace_unlock();
22332233
}
22342234

2235-
bool has_locked_children(struct mount *mnt, struct dentry *dentry)
2235+
static bool __has_locked_children(struct mount *mnt, struct dentry *dentry)
22362236
{
22372237
struct mount *child;
22382238

@@ -2246,6 +2246,16 @@ bool has_locked_children(struct mount *mnt, struct dentry *dentry)
22462246
return false;
22472247
}
22482248

2249+
bool has_locked_children(struct mount *mnt, struct dentry *dentry)
2250+
{
2251+
bool res;
2252+
2253+
read_seqlock_excl(&mount_lock);
2254+
res = __has_locked_children(mnt, dentry);
2255+
read_sequnlock_excl(&mount_lock);
2256+
return res;
2257+
}
2258+
22492259
/**
22502260
* clone_private_mount - create a private clone of a path
22512261
* @path: path to clone
@@ -2268,7 +2278,7 @@ struct vfsmount *clone_private_mount(const struct path *path)
22682278
if (!check_mnt(old_mnt))
22692279
goto invalid;
22702280

2271-
if (has_locked_children(old_mnt, path->dentry))
2281+
if (__has_locked_children(old_mnt, path->dentry))
22722282
goto invalid;
22732283

22742284
new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
@@ -2747,7 +2757,7 @@ static struct mount *__do_loopback(struct path *old_path, int recurse)
27472757
return mnt;
27482758
}
27492759

2750-
if (!recurse && has_locked_children(old, old_path->dentry))
2760+
if (!recurse && __has_locked_children(old, old_path->dentry))
27512761
return mnt;
27522762

27532763
if (recurse)
@@ -3144,7 +3154,7 @@ static int do_set_group(struct path *from_path, struct path *to_path)
31443154
goto out;
31453155

31463156
/* From mount should not have locked children in place of To's root */
3147-
if (has_locked_children(from, to->mnt.mnt_root))
3157+
if (__has_locked_children(from, to->mnt.mnt_root))
31483158
goto out;
31493159

31503160
/* Setting sharing groups is only allowed on private mounts */

0 commit comments

Comments
 (0)