setgroups —
set the calling process' supplementary
groups
Standard C Library (libc, -lc)
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.
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.
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.
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.
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
which works also on older FreeBSD version (see the
HISTORY section).