setuid() — Set the effective user ID

Standards

Standards / Extensions C or C++ Dependencies

POSIX.1
XPG4
XPG4.2
Single UNIX Specification, Version 3

both  

Format

#define _POSIX_SOURCE
#include <unistd.h>

int setuid(uid_t uid);

General description

Sets the real, effective, or saved set user IDs (UIDs) for the current process to uid.

If uid is the same as the real UID or the saved set-user-ID of the process, setuid() always succeeds and sets the effective UID. the real user ID and saved set-user-ID will remain unchanged.

The setuid() function will not affect the supplementary group list in any way.

If uid is not the same as the real UID of the process, setuid() succeeds only if the process has appropriate privileges. If the process has such privileges, setuid() sets the real group ID (UID), effective UID, and saved set UID to uid.

The setuid() function is not supported from an address space running multiple processes, since it would cause all processes in the address space to have their security environment changed unexpectedly.

setuid() can be used by daemon processes to change the identity of a process in order for the process to be used to run work on behalf of a user. In z/OS® UNIX, changing the identify of a process is done by changing the real and effective UIDs and the auxiliary groups. In order to change the identity of the process on MVS™ completely, it is necessary to also change the MVS security environment. The identity change will only occur if the EUID value is specified, changing just the real UID will have no effect on the MVS environment.

The setuid() function invokes MVS SAF services to change the MVS identity of the address space. The MVS identity that is used is determined as follows:
  • If an MVS user ID is already known by the kernel from a previous call to a kernel function (for example, getpwnam()) and the UID for this user ID matches the UID specified on the setuid() call, then this user ID is used.
  • For nonzero target UIDs, if there is no saved user ID or the UID for the saved user ID does not match the UID requested on the setuid() call, the setuid() function queries the security database (for example, using getpwnam()) to retrieve a user ID. The retrieved user ID is then used.
  • If the target UID is 0 and a user ID is not known, the setuid() function always sets the MVS user ID to BPXROOT or the value specified on the SUPERUSER parm in sysparms. BPXROOT is set up during system initialization as a superuser with a UID=0. The BPXROOT user ID is not defined to the BPX.DAEMON FACILITY class profile. This special processing is necessary to prevent a superuser from gaining daemon authority.
    Note: When running under UID=0, some servers will issue setuid(0) in order to test whether they are running UID=0. The problem with this is that the setuid function will change the userid to BPXROOT which will likely cause the daemon to fail on subsequent function requests.
  • When changing from a nonzero UID to a UID=0, the MVS user ID is not changed. When using the su shell command without specifying user name to become a superuser, the new shell retains the original MVS user ID.
  • A nondaemon superuser that attempts to set a user ID to a daemon superuser UID fails with an EPERM.

When the MVS identity is changed, the daemon must make a call to initgroups() to set the auxiliary list of groups to the list of groups for the new user ID.

If the setuid() function is issued from multiple tasks within one address space, use synchronization to ensure that the setuid() functions are not performed concurrently. The execution of setuid() function concurrently within one address space can yield unpredictable results.

Returned value

If successful, setuid() returns 0.

If unsuccessful, setuid() returns -1 and sets errno to one of the following values:
Error Code
Description
EAGAIN
The process is currently not able to change UIDs.
EINVAL
The value of uid is incorrect.
EPERM
The process does not have appropriate privileges to set the UID to uid.

Example

CELEBS11
⁄* CELEBS11

   This example changes the effective UID.

 *⁄
#define _POSIX_SOURCE
#include <sys⁄types.h>
#include <stdio.h>
#include <unistd.h>

main() {
  printf("prior to setuid(), uid=%d, effective uid=%d\n",
         (int) getuid(), (int) geteuid());
  if (setuid(25) != 0)
    perror("setuid() error");
  else
    printf("after setuid(),    uid=%d, effective uid=%d\n",
           (int) getuid(), (int) geteuid());
}
Output
before setuid(), uid=0, effective uid=0
after setuid(),    uid=25, effective uid=25

Related information