Prev: users-and-groups Next: times-and-dates
Every process has credentials:
The Real User ID and Real Group ID identify the user and group to which the process belongs.
The effective user ID and group ID are used to determine the permissions granted to a process when it tries to perform various operations. A process with an effective user ID of 0 has all the privileges of the super user. Normally real and effective ids are the same, but they can be different due to system calls.
A Set-User-ID program allows a process to gain privileges it was not originally granted. This is done by setting the process’ effective user ID to the same value as the user ID of the executable file. A Set-Group-ID does the same for the effective group id.
When an executable is allowed to be executable by a user
(chmod +x ./executable
) and then run, the kernel sets the
effective user ID of the process to be the same as the user ID of the
executable file. This is the same for the group ID.
Some Set-User-ID and Set-Group-ID programs are sudo
or
su
. These programs become useless if they are not owned by
the root user, because anybody could call them to gain access to
anything on the system.
The saved set-user-ID and saved set-group-ID are designed for
set-user-ID and set-group-ID programs. Imagine if a real user with a
user id of 1000
runs a program with set-user-ID of
0
.
After running, the user IDs of the process look like the following:
real=1000 effective=0 saved=0
.
On Linux, there are also File-System User IDs and File-System Group
IDs. This is a historical artifact of the NFS. Two additional system
calls, setfsuid
and setfsgid
are provided to
set these ids as well.
Supplementary group IDs are a set of additional groups to which a process belongs, inheriting IDs from its parent.
Linux provides system calls for modifying process credentials, and
provides the constants CAP_SETUID
and
CAP_SETGID
to allow a process to make changes to its user
ids and group ids.
To retrieve real and effective ids, the following calls are provided:
#include <unistd.h>
(void); // Returns real user ID of calling process
uid_t getuid(void); // Returns effective user ID of calling process
uid_t geteuid(void); // Returns real group ID of calling process
gid_t getgid(void); // Returns effective group ID of calling process gid_t getegid
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid); // Both return 0 on success, or –1 on error
There are a few rules:
setuid
, only the
effective user ID of the process is changed. It can only be changed to
the real user ID or the set-user-ID. If not, the error
EPERM
is raised. This is only useful for unprivileged users
executing a set-user-ID program.setuid
, it changes its
user id to the given value, but then loses the ability to call
setuid
again to change its user id, because it is no longer
privileged. This can be avoided by using seteuid
and
setreuid
.To set effective group ids, the following exists:
#include <unistd.h>
int seteuid(uid_t euid);
int setegid(gid_t egid);
Again the same caveat:
#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid); // Both return 0 on success, or –1 on error
The functions follow the same rules.
#define _GNU_SOURCE
#include <unistd.h>
int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); // Both return 0 on success, or –1 on error
#define _GNU_SOURCE
#include <unistd.h>
int setresuid(uid_t ruid, uid_t euid, uid_t suid);
int setresgid(gid_t rgid, gid_t egid, gid_t sgid); // Both return 0 on success, or –1 on error
#include <sys/fsuid.h>
int setfsuid(uid_t fsuid); // Always returns the previous file-system user ID
int setfsgid(gid_t fsgid); // Always returns the previous file-system group ID
To get group IDs:
#include <unistd.h>
int getgroups(int gidsetsize, gid_t grouplist[]); // Returns number of group IDs placed in grouplist on success, or –1 on error
To modify supplementary group IDs:
#define _BSD_SOURCE
#include <grp.h>
int setgroups(size_t gidsetsize, const gid_t *grouplist);
int initgroups(const char *user, gid_t group); // Both return 0 on success, or –1 on error
Prev: users-and-groups Next: times-and-dates