---
name: "setgroups"
section: "2"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["linux", "freebsd", "macos"]
url: "https://new.carta.tech/setgroups"
---

# setgroups(2)

set the calling process' supplementary groups

## 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)](/getgroups/2.md), [setcred(2)](/setcred/2.md), [initgroups(3)](/initgroups/3.md)

## 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)](/setegid/2.md) or to instead use [setcred(2)](/setcred/2.md), 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)](/initgroups/3.md) 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).
