diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2026-08-24 18:13:29 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2026-08-24 19:29:47 +0000 |
| commit | 00036dad647ff171b8c1847e92ac74bb511ed9d9 (patch) | |
| tree | acefa01f0be59fc64bb7bfe35a77c680feac67e4 | |
| parent | 0e8a1c849c3be9e2a18652a9221c3dba413fcf91 (diff) | |
cred: Fix group_is_primary()
This helper wasn't updated in commit be1f7435ef21, so in reality it was
testing whether "gid" is the first supplemental group. If a user
doesn't belong to a supplementary group, then it's testing an
uninitialized slot; since ucreds are allocated with M_ZERO, this
typically means that we're testing gid == 0.
group_is_primary() has exactly one use, in mac_do. There, it's used to
determine whether to keep the caller's current primary groups. This
means that a rule such as gid=0>uid=0 will permit any credential with no
supplementary groups.
I believe this is mostly exploitable by daemons which have explicitly
dropped privileges and called setgroups(0, NULL); logged in users will
have a non-empty supplementary group list by virtue of having gone
through initgroups(3).
Fix group_is_primary(), and add a regression test.
Approved by: so
Security: FreeBSD-SA-26:59.mac_do
Security: CVE-2026-58092
Reported by: Hazley Samsudin of GovTech CSG
Fixes: be1f7435ef21 ("kern: start tracking cr_gid outside of cr_groups[]")
Reviewed by: olce, kevans
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D59051
| -rw-r--r-- | sys/sys/ucred.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 254f58841993..0edd1549b5f6 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -258,7 +258,7 @@ bool cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred); static inline bool group_is_primary(const gid_t gid, const struct ucred *const cred) { - return (gid == cred->cr_groups[0] || gid == cred->cr_rgid || + return (gid == cred->cr_gid || gid == cred->cr_rgid || gid == cred->cr_svgid); } bool group_is_supplementary(const gid_t gid, const struct ucred *const cred); |
