Re: FreeBSD Security Advisory FreeBSD-SA-26:18.setcred

From: Olivier Certner <olce_at_freebsd.org>
Date: Thu, 21 May 2026 08:39:32 UTC
Hi,

Let me add some more information and correct some inaccuracy:

> I.   Background

> (snip)

> setcred(2) is a system call which enables a privileged process to atomically
> set its full credential set, including the real, effective, and saved user
> and group identifiers, as well as the list of supplementary groups.  It is
> intended for use by programs such as login(1) and PAM(3)-aware authentication
> frameworks that must transition a process into a target user context in a
> single, race-free operation, replacing the need for multiple discrete calls
> to setuid(2), setgid(2), and setgroups(2).

The only base system's program currently leveraging setcred(2) is mdo(1), so only those using it could stumble on the bug inadvertently (unless they have their own programs calling setcred(2)).

Of course, this does not preclude malicious people from trying to actively exploit that, either through mdo(1) or by calling setcred(2) directly. 

> II.  Problem Description
> 
> The setcred(2) system call is only available to privileged users.  However,
> before the privilege level of the caller is checked, the user-supplied list
> of supplementary groups is copied into a fixed-size kernel stack buffer
> without first validating its length.  If the supplied list exceeds the
> capacity of that buffer, a stack buffer overflow occurs.

The fixed-size kernel stack buffer is in fact a C array of group IDs, whose length was (of course) validated in an indirect manner, by deciding to copy to it only if the number of groups was low enough to fit.  The actual problem is that the *byte size* calculation driving the copy used a wrong sizeof() (twice too big), and we do allocate a buffer of this computed size only if there are more than CRED_SMALLGROUPS_NB (16) supplementary groups, else we use the fixed-size buffer.

Bottom line, the mentioned buffer overflow only occurs when the passed number of supplementary groups is exactly between 9 and 16 included, not in any other cases, which is why it was not caught earlier.

Even before discovery of this flaw, that code had been simplified (allowed by the change in how we handle the effective GID and supplementary groups starting from FreeBSD 15), so the bug has not been present anymore both in main and stable/15 for months (so, not in releng/15.1 either), which is why no commit to them was necessary.  Unfortunately, the MFC of this simplification to stable/15 occurred too late for inclusion in 15.0, hence requiring a direct commit to releng/15.0

Thanks to those who reported and those who fixed the bug for the supported releases.  Sorry that this stupid mistake slipped through the cracks.

Regards.

-- 
Olivier Certner