Home > Articles > Operating Systems, Server > Linux/UNIX/Open Source

This chapter is from the book

10.2 Process Attributes

10.2.1 The pid and Parentage

Two of the most basic attributes are its process ID, or pid, and the pid of its parent process. A pid is a positive integer that uniquely identifies a running process and is stored in a variable of type pid_t. When a new process is created, the original process is known as the parent of the new process and is notified when the new child process ends.

When a process dies, its exit code is stored until the parent process requests it. The exit status is kept in the kernel's process table, which forces the kernel to keep the process's entry active until it can safely discard its exit status. Processes that have exited and are kept around only to preserve their exit status are known as zombies. Once the zombie's exit status has been collected, the zombie is removed from the system's process table.

If a process's parent exits (making the child process an orphan process), that process becomes a child of the init process. The init process is the first process started when a machine is booted and is assigned a pid of 1. One of the primary jobs of the init process is to collect the exit statuses of processes whose parents have died, allowing the kernel to remove the child processes from the process table. Processes can find their pid and their parent's pid through the getpid() and getppid() functions.

pid_t getpid(void)

Returns the pid of the current process.

pid_t getppid(void)

Returns the parent process's pid.

10.2.2 Credentials

Linux uses the traditional Unix security mechanisms of users and groups. User IDs (uids) and group IDs (gids) are integers [1] that are mapped to symbolic user names and group names through /etc/passwd and /etc/group, respectively (see Chapter 28 for more information on the user and group databases). However, the kernel knows nothing about the names—it is concerned only with the integer representation. The 0 uid is reserved for the system administrator, normally called root. All normal security checks are disabled for processes running as root (that is, with a uid of 0), giving the administrator complete control over the system.

In most cases, a process may be considered to have a single uid and gid associated with it. Those are the IDs that are used for most system security purposes (such as assigning ownerships to newly created files). The system calls that modify a process ownership are discussed later in this chapter.

As Unix developed, restricting processes to a single group turned out to create new difficulties. Users involved in multiple projects had to explicitly switch their gid when they wanted to access files whose access was restricted to members of different groups.

Supplemental groups were introduced in BSD 4.3 to eliminate this problem. Although every process still has its primary gid (which it uses as the gid for newly created files, for example), it also belongs to a set of supplemental groups. Security checks that used to ensure that a process belonged to a particular group (and only that group) now allow access as long as the group is one of the supplemental groups to which the process belongs. The sysconf() macro _SC_NGROUPS_MAX specifies how many supplemental groups a process may belong to. (See Chapter 6, page 54, for details on sysconf().) Under Linux 2.4 and earlier, _SC_NGROUPS_MAX is 32; under Linux 2.6 and later, _SC_NGROUPS_MAX is 65536. Do not use a static array to store supplemental groups; instead, dynamically allocate memory, taking into account the return value of sysconf(_SC_NGROUPS_MAX). Older code may use the NGROUPS_MAX macro to determine how many supplemental groups are supported by a system; using this macro does not function correctly when the code is compiled in one environment and used in another.

Setting the list of groups for a process is done through the setgroups() system call and may be done only by processes running with root permissions.

int setgroups(size_t num, const gid_t * list);

The list parameter points to an array of num gids. The process's supplemental group list is set to the gids listed in the list array.

The getgroups() function lets a process get a list of the supplemental groups to which it belongs.

int getgroups(size_t num, gid_t * list);

The list must point to an array of gid_t, which is filled in with the process's supplemental group list, and num specifies how many gid_ts list can hold. The getgroups() system call returns -1 on error (normally, if list is not large enough to hold the supplemental group list) or the number of supplemental groups. As a special case, if num is 0, getgroups() returns the number of supplemental groups for the process.

Here is an example of how to use getgroups():

gid_t *groupList;
int numGroups;

numGroups = getgroups(0, groupList);
if (numGroups) {
    groupList = alloca(numGroups * sizeof(gid_t));
    getgroups(numGroups, groupList);

A more complete example of getgroups() appears in Chapter 28.

Thus, a process has a uid, a primary gid, and a set of supplemental groups associated with it. Luckily, this is as much as most programmers ever have to worry about. There are two classes of programs that need very flexible management of uids and gids, however: setuid/setgid programs and system daemons.

System daemons are programs that are always running on a system and perform some action at the request of an external stimulus. For example, most World Wide Web (http) daemons are always running, waiting for a client to connect to it so that they can process the client's requests. Other daemons, such as the cron daemon (which runs requests periodically), sleep until a time when they need to perform actions. Most daemons need to run with root permissions but perform actions at the request of a user who may be trying to compromise system security through the daemon.

The ftp daemon is a good example of a daemon that needs flexible uid handling. It initially runs as root and then switches its uid to the uid of the user who logs into it (most systems start a new process to handle each ftp request, so this approach works quite well). This leaves the job of validating file accesses to the kernel where it belongs. Under some circumstances, however, the ftp daemon must open a network connection in a way that only root is allowed to do (see Chapter 17 for details on this). The ftp daemon cannot simply switch back to root, because user processes cannot give themselves superuser access (with good reason!), but keeping the root uid rather than switching to the user's uid would require the ftp daemon to check all file-system accesses itself. The solution to this dilemma has been applied symmetrically to both uids and primary gids, so we just talk about uids here.

A process actually has three uids: its real uid, saved uid, and effective uid. [2] The effective uid is used for all security checks and is the only uid of the process that normally has any effect.

The saved and real uids are checked only when a process attempts to change its effective uid. Any process may change its effective uid to the same value as either its saved or real uid. Only processes with an effective uid of 0 (processes running as root) may change their effective uid to an arbitrary value.

Normally, a process's effective, real, and saved uid's are all the same. However, this mechanism solves the ftp daemon's dilemma. When it starts, all its IDs are set to 0, giving it root permissions. When a user logs in, the daemon sets its effective uid to the uid of the user, leaving both the saved and real uids as 0. When the ftp daemon needs to perform an action restricted to root, it sets its effective uid to 0, performs the action, and then resets the effective uid to the uid of the user who is logged in.

Although the ftp daemon does not need the saved uid at all, the other class of programs that takes advantage of this mechanism, setuid and setgid binaries, does use it.

The passwd program is a simple example of why setuid and setgid functionality was introduced. The passwd program allows users to change their passwords. User passwords are usually stored in /etc/passwd. Only the root user may write to this file, preventing other users from changing user information. Users should be able to change their own passwords, however, so some way is needed to give the passwd program permission to modify /etc/passwd.

To allow this flexibility, the owner of a program may set special bits in the program's permission bits (see pages 158-162 for more information), which tells the kernel that whenever the program is executed, it should run with the same effective uid (or gid) as the user who owns the program file, regardless of what user runs the program. These programs are called setuid (or setgid) executables.

Making the passwd program owned by the root user and setting the setuid bit in the program's permission bits lets all users change their passwords. When a user runs passwd, the passwd program is run with an effective user ID of 0, allowing it to modify /etc/passwd and change the user's password. Of course, the passwd program has to be carefully written to prevent unintended side effects. Setuid programs are a popular target for system intruders, as poorly written setuid programs provide a simple way for users to gain unauthorized permissions.

There are many cases in which setuid programs need their special permissions only for short periods of time and would like to switch back to the uid of the actual user for the remainder of the time (like the ftp daemon). As setuid programs have only their effective uid set to the uid of the program's owner, they know the uid of the user who actually ran them (the saved uid), making switching back simple. In addition, they may set their real uid to the setuid value (without affecting the saved uid) and regain those special permissions as needed. In this situation, the effective, saved, and real uid's work together to make system security as simple as possible.

Unfortunately, using this mechanism can be confusing because POSIX and BSD take slightly different approaches, and Linux supports both. The BSD solution is more full-featured than the POSIX method. It is accessed with the setreuid() function.

int setreuid(uid_t ruid, uid_t euid);

The real uid of the process is set to ruid and the effective uid of the process is set to euid. If either of the parameters is -1, that ID is not affected by this call.

If the effective uid of the process is 0, this call always succeeds. Otherwise, the IDs may be set to either the saved uid or the real uid of the process. Note that this call never changes the saved uid of the current process; to do that, use POSIX's setuid() function, which can modify the saved uid.

int setuid(uid_t euid);

As in setreuid(), the effective uid of the process is set to euid as long as euid is the same as either the saved or real uid of the process, or as long as the process's effective uid at the time of the call is 0.

When setuid() is used by a process whose effective uid is 0, all the process's uids are changed to euid. Unfortunately, this makes it impossible for setuid() to be used in a setuid root program that needs to temporarily assume the permissions of another uid, because after calling setuid(), the process cannot recover its root privileges.

Although the ability to switch uids does make it easier to write code that cannot be tricked into compromising system security, it is not a panacea. There are many popular methods for tricking programs into executing arbitrary code [Lehey, 1995]. As long as either the saved or real uid of a process is 0, such attacks can easily set the effective uid of a process to 0. This makes switching uids insufficient to prevent serious vulnerabilities in system programs. However, if a process can give up any access to root privileges by setting its effective, real, and saved IDs to non-0 values, doing so limits the effectiveness of any attack against it.

10.2.3 The filesystem uid

In highly specialized circumstances, a program may want to keep its root permissions for everything but file-system access, for which it would rather use a user's uid. The user-space NFS server originally used by Linux illustrates the problem that can occur when a process assumes a user's uid. Although the NFS server in the past used setreuid() to switch uids while accessing the file system, doing so allowed the user whose uid the NFS server was assuming to kill the NFS server. After all, for a moment that user owned the NFS server process. To prevent this type of problem, Linux uses the filesystem uid (fsuid) for file-system access checks.

Whenever a process's effective uid is changed, the process's fsuid is set to the process's new effective user ID, making the fsuid transparent to most applications. Those applications that need the extra features provided by the separate fsuid must use the setfsuid() call to explicitly set the fsuid.

int setfsuid(uid_t uid);

The fsuid may be set to any of the current effective, saved, or real uids of the process. In addition, setfsuid() succeeds if the current fsuid is being retained or if the process's effective uid is 0.

10.2.4 User and Group ID Summary

Here is a summary of all the system calls that modify the access permissions of a running process. Most of the functions listed here that pertain to user IDs have been discussed in detail earlier in this chapter, but those related to group IDs have not. As those functions mirror similar functions that modify user IDs, their behavior should be clear.

All of these functions return -1 on error and 0 on success, unless otherwise noted. Most of these prototypes are in <unistd.h>. Those that are located elsewhere are noted below.

int setreuid(uid_t ruid, uid_t euid)

Sets the real uid of the current process to ruid and the effective uid of the process to euid. If either of the parameters is -1, that uid remains unchanged.

int setregid(gid_t rgid, gid_t egid)

Sets the real gid of the current process to rgid and the effective gid of the process to egid. If either of the parameters is -1, that gid remains unchanged.

int setuid(uid_t uid)

If used by a normal user, sets the effective uid of the current process to uid. If used by a process with an effective uid of 0, it sets the real, effective, and saved uids to uid.

int setgid(gid_t gid)

If used by a normal user, sets the effective gid of the current process to gid. If used by a process with an effective gid of 0, sets the real, effective, and saved gids to gid.

int seteuid(uid_t uid)

Equivalent to setreuid(-1, uid).

int setegid(gid_t gid)

Equivalent to setregid(-1, gid).

int setfsuid(uid_t fsuid)

Sets the fsuid of the current process to fsuid. It is prototyped in <sys/fsuid.h>. It returns the previous fsuid.

int setfsgid(gid_t fsgid)

Sets the fsgid of the current process to fsgid. It is prototyped in <sys/fsuid.h>. It returns the previous fsgid.

int setgroups(size_t num, const gid_t * list)

Sets the supplemental groups for the current process to the groups specified in the array list, which must contain num items. The sysconf() macro _SC_NGROUPS_MAX tells how many groups may be in the list (likely 32 or 65536, depending on the Linux versions you are currently running). The setgroups() function is prototyped in <grp.h>.

uid_t getuid()

Returns the real uid of the process.

uid_t geteuid()

Returns the effective uid of the process.

gid_t getgid()

Returns the real gid of the process.

gid_t getegid()

Returns the effective gid of the process.

size_t getgroups(size_t size, gid_t list[])

Returns the current set of supplemental groups for the current process in the array list.size tells how many gid_ts the list can hold. If the list is not big enough to hold all of the groups, -1 is returned and errno is set to EINVAL. Otherwise, the number of groups in the list is returned. If size is 0, the number of groups in the list is returned, but list is not affected. The getgroups() function is prototyped in <grp.h>.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information

To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.


Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.


If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information

Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.


This site is not directed to children under the age of 13.


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information

If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information

Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents

California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure

Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact

Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice

We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020