[HEADSUP] ucred / group changes in FreeBSD 15.0

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Fri, 08 Aug 2025 05:38:17 UTC
Hi,

I wanted to give some additional notice about some changes that olce@ 
and I have been working on w.r.t. ucrceds and group lists that are 
landing in advance of FreeBSD 15.0.  The associated changes are tagged 
for the relnotes to try and reach a wider audience, as some of these may 
require some adaptation in out-of-tree kmods and applications.

The major struct ucred change[0] here is that we now track the egid 
outside of the cr_groups array.  We've had a cr_gid macro to alias 
cr_groups[0] for over 30 years, but the macro has now been replaced by 
actual members in struct ucred and struct xucred.  In the xucred case, 
we use some union trickery to alias it to the first element of cr_groups 
to avoid breaking the ABI.

Consumers of `struct ucred` need to be adapted to use `cr_gid` instead 
of `cr_groups[0]` explicitly (in all versions of FreeBSD), and should 
avoid giving `cr_groups[0]` any special treatment otherwise if `cr_gid 
== &cr_groups[0]` to do the right thing across all supported versions.

Making this distinction in the struct ucred makes the userland-facing 
change marginally easier, but more importantly reduces some confusion in 
how we've historically conflated the egid and supplementary groups to 
some extent.

The userland facing change here has not been committed yet, but I plan 
to push it around early next week after doing some more due diligence. 
D51648[1] will spin up new versions of setgroups(2) and getgroups(2) to 
operate on and return only supplementary groups, rather than also 
altering the egid as it does today.

The userland revisions are notably important because we're one of the 
very few systems standing that still use groups[0] for the egid in these 
interfaces -- macOS is the only other system I've observed that behaves 
the same way; OpenBSD/NetBSD/Linux haven't behaved this way in years (if 
at all).  This has lead to weird bugs[2][3] (and another one noted but 
not described in www/uwsgi[4]), and likely more that haven't been 
discovered.  A quick grep through the ports tree doesn't find a single 
patch for getgroups/setgroups, so it's not clear that we've done any 
auditing for peculiarities of this form.

This is both a notice that changes may be needed to out-of-tree stuff, 
and a chance to object before landing the setgroups/getgroups change 
(tentatively aiming for the Monday/Tuesday time-frame).

Thanks,

Kyle Evans

[0] 
https://cgit.freebsd.org/src/commit/?id=be1f7435ef218b1df35aebf3b90dd65ffd8bbe51

[1] https://reviews.freebsd.org/D51648

[2] 
https://cgit.freebsd.org/src/commit/?id=48fd05999b0f8e822fbf7069779378d103a35f5c
[3] https://reviews.freebsd.org/D51753

[4] https://github.com/unbit/uwsgi/blob/master/core/utils.c#L834-L879

You'll note that if we have any additional_gids, they'll (maybe) wipe 
out our previous setgid() or initgroups() to set uwsgi.gid if it's not 
duplicated into additional_gids.  That's insanely subtle.