Skip to content

Commit 58fa652

Browse files
committed
use uniform permission checks for all mount propagation changes
jira LE-4297 cve CVE-2025-38498 Rebuild_History Non-Buildable kernel-6.12.0-55.34.1.el10_0 commit-author Al Viro <[email protected]> commit cffd044 do_change_type() and do_set_group() are operating on different aspects of the same thing - propagation graph. The latter asks for mounts involved to be mounted in namespace(s) the caller has CAP_SYS_ADMIN for. The former is a mess - originally it didn't even check that mount *is* mounted. That got fixed, but the resulting check turns out to be too strict for userland - in effect, we check that mount is in our namespace, having already checked that we have CAP_SYS_ADMIN there. What we really need (in both cases) is * only touch mounts that are mounted. That's a must-have constraint - data corruption happens if it get violated. * don't allow to mess with a namespace unless you already have enough permissions to do so (i.e. CAP_SYS_ADMIN in its userns). That's an equivalent of what do_set_group() does; let's extract that into a helper (may_change_propagation()) and use it in both do_set_group() and do_change_type(). Fixes: 12f147d "do_change_type(): refuse to operate on unmounted/not ours mounts" Acked-by: Andrei Vagin <[email protected]> Reviewed-by: Pavel Tikhomirov <[email protected]> Tested-by: Pavel Tikhomirov <[email protected]> Reviewed-by: Christian Brauner <[email protected]> Signed-off-by: Al Viro <[email protected]> (cherry picked from commit cffd044) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 76d785f commit 58fa652

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

fs/namespace.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2673,6 +2673,19 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
26732673
return attach_recursive_mnt(mnt, p, mp, 0);
26742674
}
26752675

2676+
static int may_change_propagation(const struct mount *m)
2677+
{
2678+
struct mnt_namespace *ns = m->mnt_ns;
2679+
2680+
// it must be mounted in some namespace
2681+
if (IS_ERR_OR_NULL(ns)) // is_mounted()
2682+
return -EINVAL;
2683+
// and the caller must be admin in userns of that namespace
2684+
if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
2685+
return -EPERM;
2686+
return 0;
2687+
}
2688+
26762689
/*
26772690
* Sanity check the flags to change_mnt_propagation.
26782691
*/
@@ -2709,10 +2722,10 @@ static int do_change_type(struct path *path, int ms_flags)
27092722
return -EINVAL;
27102723

27112724
namespace_lock();
2712-
if (!check_mnt(mnt)) {
2713-
err = -EINVAL;
2725+
err = may_change_propagation(mnt);
2726+
if (err)
27142727
goto out_unlock;
2715-
}
2728+
27162729
if (type == MS_SHARED) {
27172730
err = invent_group_ids(mnt, recurse);
27182731
if (err)
@@ -3106,18 +3119,11 @@ static int do_set_group(struct path *from_path, struct path *to_path)
31063119

31073120
namespace_lock();
31083121

3109-
err = -EINVAL;
3110-
/* To and From must be mounted */
3111-
if (!is_mounted(&from->mnt))
3112-
goto out;
3113-
if (!is_mounted(&to->mnt))
3114-
goto out;
3115-
3116-
err = -EPERM;
3117-
/* We should be allowed to modify mount namespaces of both mounts */
3118-
if (!ns_capable(from->mnt_ns->user_ns, CAP_SYS_ADMIN))
3122+
err = may_change_propagation(from);
3123+
if (err)
31193124
goto out;
3120-
if (!ns_capable(to->mnt_ns->user_ns, CAP_SYS_ADMIN))
3125+
err = may_change_propagation(to);
3126+
if (err)
31213127
goto out;
31223128

31233129
err = -EINVAL;

0 commit comments

Comments
 (0)