setcred
— set
current process credentials atomically
Standard C Library (libc, -lc)
#include
<sys/ucred.h>
int
setcred
(u_int
flags, const struct
setcred *wcred, size_t
size);
The
setcred
()
system call can set any combination of user-accessible credentials of the
current process in an atomic manner.
This system call is normally permitted only for processes having
the ID of the super-user (0) as their effective user ID, or not at
all if the
sysctl(8)
variable security.bsd.suser_enabled is zero or some
active MAC policy specifically denies these processes.
Some MAC policies, such as
mac_do(4),
may also allow unprivileged users to call it successfully, possibly
depending on the exact credentials transition requested, once again unless
any active MAC policy specifically denies that.
The flags argument serves to indicate which
process credentials should be changed by the call. Allowed flags are:
- SETCREDF_UID
- Set the effective user ID.
- SETCREDF_RUID
- Set the real user ID.
- SETCREDF_SVUID
- Set the saved user ID.
- SETCREDF_GID
- Set the effective group ID.
- SETCREDF_RGID
- Set the real group ID.
- SETCREDF_SVGID
- Set the saved group ID.
- SETCREDF_SUPP_GROUPS
- Set the supplementary group list.
- SETCREDF_MAC_LABEL
- Set the MAC label.
The struct setcred structure is currently
defined as:
struct setcred {
uid_t sc_uid; /* effective user id */
uid_t sc_ruid; /* real user id */
uid_t sc_svuid; /* saved user id */
gid_t sc_gid; /* effective group id */
gid_t sc_rgid; /* real group id */
gid_t sc_svgid; /* saved group id */
u_int sc_pad; /* padding, unused */
u_int sc_supp_groups_nb; /* supplementary groups number */
gid_t *sc_supp_groups; /* supplementary groups */
struct mac *sc_label; /* MAC label */
};
Its fields are:
- sc_uid
- The ID to set the effective user to, if flag
SETCREDF_UID
is specified.
- sc_ruid
- The ID to set the real user to, if flag
SETCREDF_RUID
is specified.
- sc_svuid
- The ID to set the saved user to, if flag
SETCREDF_SVUID
is specified.
- sc_gid
- The ID to set the effective group to, if flag
SETCREDF_GID
is specified.
- sc_rgid
- The ID to set the real group to, if flag
SETCREDF_RGID
is specified.
- sc_svgid
- The ID to set the saved group to, if flag
SETCREDF_SVGID
is specified.
- sc_supp_groups_nb
- The size of array sc_supp_groups, if flag
SETCREDF_SUPP_GROUPS
is specified. It must be less
than or equal to {NGROUPS_MAX}
.
- sc_supp_groups
- An array of IDs to set the supplementary groups to, if flag
SETCREDF_SUPP_GROUPS
is specified. Note that all
groups in this array will be set as supplementary groups only, in contrast
to
setgroups(2)
which treats the first element specially as the new effective group, not
adding it to supplementary groups.
- sc_label
- A pointer to a valid MAC label structure, e.g., built with the
mac_from_text(3)
function, if flag
SETCREDF_MAC_LABEL
is
specified.
For forward compatibility and security reasons, it is recommended
that users always initialize objects of type struct
setcred with the provided initializer:
SETCRED_INITIALIZER
.
The size argument must be the size of the
passed wcred structure.
Upon successful completion, the value 0 is returned;
otherwise the value -1 is returned and the global variable
errno is set to indicate the error.
The setcred
() system call will fail
if:
- [
EINVAL
]
- Unrecognized flags were passed in flags, or the
size parameter does not match the size of
struct setcred, or the field
sc_supp_group_nb has a value strictly greater than
{NGROUPS_MAX}
(if flag
SETCREDF_SUPP_GROUPS
was supplied), or the MAC
label pointed to by field sc_label is invalid (if
flag SETCREDF_MAC_LABEL
was supplied).
- [
EFAULT
]
- The wcred pointer, or pointers in fields
sc_supp_groups (if flag
SETCREDF_SUPP_GROUPS
was supplied) or
sc_label (if flag
SETCREDF_MAC_LABEL
was supplied) point to invalid
locations.
- [
EPERM
]
- The user is not the super-user and/or the requested credentials transition
is not allowed by the system or MAC modules.
- [
EOPNOTSUPP
]
- Some of the requested credentials have a type that the system does not
support. This currently can occur only if the kernel has been compiled
without MAC and
SETCREDF_MAC_LABEL
has been
passed.
The setcred
() system call is specific to
FreeBSD.
A call to setcred
() usually changes
process credentials that are listed by POSIX/SUS standards. The changed
values then produce the effects with respect to the rest of the system that
are described in these standards, as if these changes had resulted from
calling standard or traditional credentials-setting functions. Currently,
all flags but SETCREDF_MAC_LABEL
lead to modifying
standard credentials.
The only differences in using setcred
() to
change standard credentials instead of standard or traditional functions
are:
- All requested changes are performed atomically.
- Only the super-user or an unprivileged user authorized by some MAC module
can successfully call
setcred
(), even if the
standard system calls would have authorized any unprivileged user to
effect the same changes. For example, seteuid
()
allows any unprivileged user to change the effective user ID to either the
real or saved ones, while setcred
() called with
flag SETCREDF_UID
does not.
The setcred
() system call appeared in
FreeBSD 14.3.
Traditionally in UNIX, all credential changes beyond shuffles of
effective, real and saved IDs have been done by setuid binaries that
successively call multiple credentials-setting system calls and in a
specific order. For example, to change all user IDs to that of some
unprivileged user, setuid
() must be called last so
that all other credentials-changing calls can be performed successfully
beforehand, as they require super-user privileges.
This piecewise approach causes such a process to transiently hold
high privilege credentials that are neither the original nor necessarily the
desired final ones. Besides opening a transition window where possible
vulnerabilities could have catastrophic consequences, it makes it impossible
for the kernel to enforce that only certain transitions of credentials are
allowed.
The necessity of an atomic, global approach to changing
credentials clearly appeared while working on extending
mac_do(4)
to allow rules to authorize only specific changes of primary or
supplementary groups, which prompted the addition of
setcred
().
The same considerations as those of standard or traditional
credentials-setting system calls apply to setcred
(),
except for the lack of atomicity of successive such calls.
In particular, please consult section
SECURITY
CONSIDERATIONS of the
setuid(2)
manual page about the absence of effect of changing standard credentials on
already open files.