SETGROUPS(2)              FreeBSD System Calls Manual             SETGROUPS(2)

NAME

     setgroups - set the calling process' supplementary groups

LIBRARY

     Standard C Library (libc, -lc)

SYNOPSIS

     #include <sys/param.h>
     #include <unistd.h>

     int
     setgroups(int ngroups, const gid_t *gidset);

DESCRIPTION

     The setgroups() system call sets the calling process' supplementary
     groups according to the gidset array.  The ngroups argument indicates the
     number of entries in the array and must be no more than {NGROUPS_MAX}.

     The ngroups argument may be set to zero to clear all supplementary
     groups, in which case gidset is ignored.

     Only the super-user may install a new supplementary groups set.

RETURN VALUES

     The setgroups() function returns the value 0 if successful; otherwise the
     value -1 is returned and the global variable errno is set to indicate the
     error.

ERRORS

     The setgroups() system call will fail if:

     [EPERM]            The caller is not the super-user.

     [EINVAL]           The number specified in the ngroups argument is larger
                        than the {NGROUPS_MAX} limit.

     [EFAULT]           Part of the groups array starting at gidset is outside
                        the process address space.

SEE ALSO

     getgroups(2), setcred(2), initgroups(3)

HISTORY

     The setgroups() system call appeared in 4.2BSD.

     Before FreeBSD 15.0, the setgroups() system call would set the effective
     group ID for the process to the first element of gidset, and only the
     other elements as supplementary groups.  Despite treating the first
     element as the effective group ID to set, it accepted an empty gidset
     (ngroups being zero) as a stance requiring to drop all supplementary
     groups, leaving the effective group ID unchanged.

SECURITY CONSIDERATIONS

     The setgroups() system call sets the process' supplementary groups to
     those contained in the gidset array.  In particular, as evoked in
     HISTORY, it does not anymore treat the first element of gidset
     separately.  Formerly, it would set it as the effective group ID while
     only the others were used as supplementary groups.

     Programs solely relying on setgroups() to change the effective group ID
     must be modified, e.g., to also call setegid(2) or to instead use
     setcred(2), else they will unwillingly keep their effective group ID.

     Programs using setgroups() with the effective group ID as the first
     element of array gidset and not duplicating it in the rest of the array,
     which includes those using initgroups(), now insert this group ID in the
     supplementary groups set.  This is in general desirable, as explained in
     the initgroups(3) manual page, and has the consequence that subsequent
     process' effective group ID's changes do not remove membership of the
     original effective group ID, since these changes do not affect the
     supplementary groups.  Applications that expressly do not want that must
     be modified to stop passing the effective group ID as the first element
     to setgroups().

     To clear all the calling process' supplementary groups, always use the
     statement

           setgroups(0, NULL);

     which works also on older FreeBSD version (see the HISTORY section).

FreeBSD 15.1-STABLE-HBSD      September 17, 2025                  SETGROUPS(2)