Group identifier
View on WikipediaThis article needs additional citations for verification. (September 2014) |
In Unix-like systems, multiple users can be put into groups. POSIX and conventional Unix file system permissions are organized into three classes, user, group, and others. The use of groups allows additional abilities to be delegated in an organized fashion, such as access to disks, printers, and other peripherals. This method, among others, also enables the superuser to delegate some administrative tasks to normal users, similar to the Administrators group on Microsoft Windows NT and its derivatives.
A group identifier, often abbreviated to GID, is a numeric value used to represent a specific group.[1] The range of values for a GID varies amongst different systems; at the very least, a GID can be between 0 and 32,767, with one restriction: the login group for the superuser must have GID 0. This numeric value is used to refer to groups in the /etc/passwd and /etc/group files or their equivalents. Shadow password files and Network Information Service also refer to numeric GIDs. The group identifier is a necessary component of Unix file systems and processes.
Supplementary groups
[edit]In Unix systems, every user must be a member of at least one group, the primary group, which is identified by the numeric GID of the user's entry in the passwd database, which can be viewed with the command getent passwd (usually stored in /etc/passwd or LDAP). This group is referred to as the primary group ID. A user may be listed as member of additional groups in the relevant entries in the group database, which can be viewed with getent group (usually stored in /etc/group or LDAP); the IDs of these groups are referred to as supplementary group IDs.
Effective vs. real
[edit]Unix processes have an effective (EUID, EGID), a real (UID, GID) and a saved (SUID, SGID) ID. Normally these are identical, but in setuid and setgid processes they are different.
Conventions
[edit]Type
[edit]Originally, a signed 16-bit integer was used. Since the sign was not necessary – negative numbers do not make valid group IDs – an unsigned integer is now used instead, allowing group IDs between 0 and 65,535. Modern operating systems usually use unsigned 32-bit integers, which allow for group IDs between 0 and 4,294,967,295.
Reserved ranges
[edit]Many Linux systems reserve the GID number range 0 to 99 for statically allocated groups, and either 100−499 or 100−999 for groups dynamically allocated by the system in post-installation scripts. These ranges are often specified in /etc/login.defs, for useradd, groupadd and similar tools.
On FreeBSD, porters who need a GID for their package can pick a free one from the range 50 to 999 and then register this static allocation in ports/GIDs.[2]
Special values
[edit]- 0: The superuser normally has a GID of zero (0).
- −1: The value
(gid_t) -1is reserved by POSIX to identify an omitted argument.[3] - 65,534: The Linux kernel defaults to 216−2 = 65,534 (which many Linux distributions map to the group name "nogroup") when a 32-bit GID does not fit into the return value of a 16-bit system call.[4] The value is also returned by idmapd if a group name in an incoming NFSv4 packet does not match any known group on the system.
Personal groups
[edit]Many system administrators allocate for each user also a personal primary group that has the same name as the user's login name, and often also has the same numeric GID as the user's UID. Such personal groups have no other members and make collaboration with other users in shared directories easier, by allowing users to habitually work with umask 0002. This way, newly created files can have by default write permissions enabled for group members, because this will normally only enable write access for members of the personal group, that is only for the file's owner. However, if a file is created in a shared directory that belongs to another group and has the setgid bit set, then the created file will automatically become writable to members of that directory's group as well.
On many Linux systems, the USERGROUPS_ENAB variable in /etc/login.defs controls whether commands like useradd or userdel automatically add or delete an associated personal group.
See also
[edit]References
[edit]- ^ "Definitions". pubs.opengroup.org. Retrieved 2021-12-06.
- ^ FreeBSD Porter's Handbook, Section 6.26: Adding Users and Groups
- ^ "chown". pubs.opengroup.org. Retrieved 2021-12-06.
- ^ "Namespaces in operation, part 5: User namespaces [LWN.net]". lwn.net. Retrieved 2021-12-06.
Group identifier
View on Grokipedia/etc/group and are integral to user account management, where each group has a distinct ID ranging from reserved system values (often below 1000) to user-defined ones starting at configurable minima like 1000 or 5000.[2] Users can belong to a primary group (set during account creation) and multiple supplementary groups, allowing fine-grained control over access to resources such as files, devices, and network services.[3] Commands like groupadd, groupmod, and usermod are used to create, modify, and assign GIDs, ensuring uniqueness across the system to prevent conflicts in permission resolution.[2]
In Microsoft Windows environments, the equivalent concept is the security identifier (SID) for groups, a complex alphanumeric string that uniquely identifies security principals like user groups in Active Directory for authentication and authorization purposes.[4] Beyond operating systems, GIDs appear in networked and distributed systems, such as in 3GPP telecommunications standards for identifying subscription groups or in OpenFlow protocols for scalable flow management in software-defined networking.[1] These identifiers enhance security by allowing policies to be applied collectively rather than individually, reducing administrative overhead while maintaining robust isolation of resources.[1]
Fundamentals
Definition
A group identifier, commonly abbreviated as GID, is a numeric value employed to uniquely identify a group of users or processes within multi-user operating systems, particularly Unix-like systems. It serves as a fundamental mechanism for organizing and managing collective entities in the system, distinct from individual user accounts. Typically, a GID is represented as an unsigned integer, with sizes varying by implementation—historically 16 bits in early Unix systems and 32 bits in modern ones such as Linux, allowing for up to 65,536 or over 4 billion unique groups, respectively.[5][6] In contrast to the user identifier (UID), which assigns a unique number to individual users for personal authentication and permissions, the GID enables shared access rights among multiple users or processes belonging to the same group. This distinction supports efficient resource allocation and security policies in environments where collaboration is common. The GID type, defined asgid_t in system headers, is an arithmetic integer type suitable for holding group IDs, as specified in POSIX standards.[7]
Group identifiers are persistently stored in system configuration files, such as /etc/group in Unix-like operating systems, which is a plain-text file readable by all users. Each entry in this file follows a colon-separated format: group_name:password:GID:user_list, where the GID field provides the numeric identifier, the password is typically unused or shadowed, and the user_list enumerates comma-separated usernames as members. For instance, the root group, which encompasses administrative users, is conventionally assigned GID 0, symbolizing its elevated status.[8][3]
Purpose in Operating Systems
Group identifiers (GIDs) play a crucial role in operating systems, particularly Unix-like systems, by enabling efficient resource sharing in multi-user environments. Introduced in 1973 with the Fourth Edition of Unix at Bell Laboratories as part of Unix's foundational design, GIDs were developed to support collaborative access to system resources among researchers and developers without compromising basic isolation. This historical innovation addressed the needs of time-sharing systems where multiple users interacted with shared hardware, allowing for streamlined management of permissions and reducing administrative overhead in academic and industrial settings.[9] In the context of file and device management, GIDs allow multiple users to access shared files, directories, and devices collectively, eliminating the need to grant permissions individually to each user. By associating users with specific groups, operating systems can apply uniform access rights to group members, promoting collaboration while maintaining control through the file owner's discretion. For instance, a project team can be assigned to a group that has read-write access to a shared directory, ensuring all members benefit from the same privileges without redundant configuration.[10][11] GIDs underpin the discretionary access control (DAC) model prevalent in Unix-like systems, where resource owners define access policies based on user identities or group affiliations. Under DAC, permissions are set for three categories—owner, group, and others—enabling owners to delegate access granularly to groups, which supports flexible security policies tailored to organizational needs. This model relies on GIDs to evaluate access requests efficiently, checking if the requesting process's group matches the resource's group to grant or deny operations like reading or writing.[10][11] Additionally, GIDs facilitate process ownership and controlled privilege escalation via the setgid mechanism, which permits a process to inherit the group privileges of an executable file upon execution. This allows applications to perform tasks requiring elevated group-level access, such as modifying shared resources, while limiting the scope to the specific group context and preventing broader system compromise. By design, setgid ensures that privileges are temporary and tied to the execution environment, enhancing security in multi-user scenarios.[12]Types of Group Identifiers
Primary Group ID
The primary group ID (GID) is a numeric identifier assigned to a user account during its creation, typically using commands likeuseradd with the -g option to specify the initial login group. This GID is stored in the fourth colon-separated field of the /etc/passwd file, following the username, password placeholder, and user ID (UID).[13] The value references an entry in the /etc/group file, ensuring the group exists before assignment.
This primary GID establishes the default group ownership for files and directories created by the user in the absence of other mechanisms, such as setgid directories.[14] When a user creates a new file, the filesystem assigns the user's UID as the owner and the primary GID as the group, facilitating basic access control based on group permissions.[15] This behavior ensures that files inherit a consistent group affiliation aligned with the user's core identity, unless modified post-creation.
In the login process, the system uses the primary GID from /etc/passwd to initialize the real and effective group IDs of the user's initial process, such as the login shell.[16] This setup provides the foundational group context for all subsequent processes spawned by the user session.
For instance, in common Linux distributions like Red Hat Enterprise Linux and Ubuntu, the primary GID for the first standard user is often 1000, matching a dedicated user group to promote isolation from system groups.[3] While supplementary groups allow additional memberships for broader access, the primary GID remains the user's singular default association.[14]
Supplementary Group IDs
Supplementary group IDs (SGIDs) enable users in Unix-like operating systems to belong to multiple groups in addition to their primary group, thereby granting broader access permissions to files, directories, and other system resources owned by those groups.[17] These additional memberships allow for flexible role-based access control without requiring frequent changes to a user's primary group affiliation. A user can be assigned a list of supplementary group IDs, with the maximum number determined by system limits. In traditional Unix systems, this was commonly limited to 16 supplementary groups, though POSIX requires support for at least 8. Modern Linux kernels, however, support up to NGROUPS_MAX supplementary groups, a configurable value typically set to 65536 via /proc/sys/kernel/ngroups_max.[18][19] Supplementary groups are configured system-wide in the /etc/group file, an ASCII text file where each line defines a group with its name, optional password, GID, and a comma-separated list of member usernames.[8] Administrators can also manage these memberships using commands like usermod, for example, to append a user to additional groups withusermod -a -G groupname username.[20]
Upon process creation via fork(2), child processes inherit the parent's supplementary group IDs, which are preserved across execve(2).[18][17] During permission checks for accessing files or resources, the kernel verifies if the resource's group matches the process's effective GID or any of its supplementary GIDs, extending access beyond the primary group alone.[17]
For instance, a developer user with primary GID 1000 (users) might be assigned supplementary GIDs 1001 (developers) and 1002 (admins), allowing read/write access to project repositories owned by the developers group and administrative tools owned by the admins group.[17]
Process Group IDs
In Unix-like operating systems, processes have several group identifiers associated with their credentials: the real group ID, effective group ID, and saved set-group-ID. These are distinct from the process group ID (PGID), which identifies the process group for job control and signaling purposes as defined in POSIX standards.Real Group ID
The real group ID (RGID) is an attribute of a process in POSIX-compliant operating systems that identifies the group associated with the user who created the process at the time of its creation. It represents the actual group identity and is inherited from the parent process, ensuring continuity of the original ownership context. Upon user login, the login process establishes the initial shell or session process with a real group ID matching the user's primary group as defined in the system user database, such as the POSIX user database entry. This setting persists across child processes created during the session unless explicitly altered by privileged operations. For example, in environments supporting POSIX standards, the real group ID is assigned from the user's GID field during authentication and process initialization.[21] The real group ID remains unchanged during the execution of privilege-escalating binaries, such as those with the set-group-ID bit set. When such an executable is invoked via a call like execve(), the kernel updates only the effective group ID to match the file's group while preserving the real group ID from the calling process. This behavior is specified in POSIX standards, where the real group ID of the new process image explicitly remains the same as that of the caller, even under set-group-ID conditions. In practice, non-privileged processes cannot modify their real group ID using functions like setgid(); such changes require appropriate privileges (e.g., effective user ID of 0), and otherwise, only the effective group ID is affected if it matches the real or saved set-group-ID. This immutability ensures that the original group ownership is not altered by temporary privilege adjustments. The real group ID plays a key role in auditing and logging mechanisms within Unix-like systems. It is recorded in audit logs, such as those generated by the Linux Audit Daemon (auditd), to track the originating group of processes for security analysis and compliance monitoring—for instance, the "gid" field in audit records denotes the real group ID of the process initiator. This facilitates forensic review by distinguishing the true ownership from any effective changes during execution.[22] Processes can retrieve their real group ID using the POSIX system call getgid(), which returns the value as a gid_t data type without error conditions, providing a reliable way to query the persistent group identity.Effective Group ID
The effective group ID (EGID) of a process determines the group-based permissions it holds at runtime, particularly for accessing files, shared resources like message queues and semaphores, and other system objects where group membership is checked.[17] Unlike the real group ID, which represents the process's underlying group identity for purposes such as accounting and resource ownership, the EGID can vary to enforce privilege separation during execution.[17] During the execution of a new program via the execve() system call, the EGID is set to the group ID of the executable file if the file has its set-group-ID (setgid) bit enabled in its mode bits, thereby allowing the process to temporarily elevate its group privileges to those of the file's owning group.[23] This change occurs only if the filesystem does not have the ST_NOSUID bit set or other restrictions like no_new_privs are absent; otherwise, the EGID remains unchanged from the calling process.[23][24] The real group ID and supplementary group IDs are preserved from the parent process in this scenario.[23] The kernel uses the EGID to authorize access requests, such as when a process attempts to read or write a file owned by a specific group or to allocate resources in a group-restricted namespace.[17] For filesystem operations, the effective group ID for permission checks defaults to the EGID but can be overridden by a separate filesystem group ID if set.[17] A process with appropriate privileges—such as the CAP_SETGID capability—or if the target group ID matches the real group ID or saved set-group-ID, can modify its EGID using the setegid() system call, which updates only the effective value while leaving the real and supplementary group IDs intact.[25][26] For example, if a user executes a script with the setgid bit set and owned by a privileged group like "admin," the resulting process will operate with the EGID of the "admin" group, granting it access to admin-restricted files regardless of the caller's original group membership, until the EGID is explicitly changed or the process exits.[23][24]Saved Set-Group-ID
The saved set-group-ID (often abbreviated as saved SGID) is a runtime attribute in Unix-like operating systems that stores a copy of the effective group ID during privilege escalation, enabling processes to temporarily drop and later restore group privileges without permanent loss. Introduced in 4.4BSD in 1993, this feature was designed specifically for setgid programs, allowing them to operate with reduced privileges for security while retaining the capability to regain elevated access when necessary.[27] Upon execution of a setgid binary via a call like execve, the effective group ID is updated to match the file's group owner if the setgid bit is set, and this new effective value is simultaneously copied into the saved set-group-ID for preservation. This stored value becomes accessible through specialized system calls, such as setresgid(), which permits a process to independently modify the real, effective, and saved group IDs, provided it has sufficient privileges. Such flexibility is crucial for preventing irreversible privilege forfeiture in scenarios involving dynamic access control. In practice, the saved set-group-ID proves invaluable for complex applications like network daemons, where a process might need to bind to privileged ports initially but then operate with unprivileged credentials for handling user data, later restoring group privileges for administrative tasks. This mechanism supports secure privilege switching without requiring root-level intervention, thereby reducing the attack surface in multi-privileged environments. Although widely implemented in modern Unix derivatives, the saved set-group-ID is not universally supported across all historical or embedded systems; however, POSIX.1-2001 formalized related concepts by introducing the _POSIX_SAVED_IDS option, which mandates the presence of saved IDs and standardizes functions like setresgid for their manipulation.[28]Conventions and Standards
Data Types
In POSIX-compliant operating systems, group identifiers (GIDs) are represented using thegid_t data type, defined in the <sys/types.h> header as an integer type designated for holding group IDs.[7] This type ensures portability across conforming systems while allowing implementations to define its exact properties, such as signedness and bit width, to match the underlying architecture.[7]
Historically, in early Unix systems like those based on the PDP-11 architecture, gid_t was implemented as a 16-bit unsigned integer, supporting values in the range from 0 to 65,535.[18] As systems evolved to handle larger user bases and file systems, the type expanded; in modern Unix-like systems such as Linux, gid_t is typically a 32-bit unsigned integer, accommodating values from 0 to 4,294,967,295.[29] Although 64-bit architectures are prevalent today, gid_t often remains 32 bits wide for backward compatibility and to align with established system call interfaces, though some specialized implementations may use 64 bits.[18]
GIDs are stored in binary integer format within process credentials maintained by the kernel, enabling efficient access during permission checks and system calls.[17] Conversely, in user-facing configuration files like /etc/group, GIDs appear as textual decimal strings for readability and ease of manual editing.
Portability challenges stem from the lack of a fixed size in the POSIX specification, leading to variations across architectures and operating systems; for instance, Linux defaults to a 32-bit gid_t regardless of whether the system is 32-bit or 64-bit.[7] Developers must therefore use abstract types like gid_t in portable code rather than assuming specific widths, often relying on compile-time checks or standards-compliant headers to mitigate issues.[7]
Reserved Ranges
In Unix-like operating systems, group identifiers (GIDs) are allocated within predefined ranges to distinguish between system-defined and user-defined groups, ensuring consistent management across implementations. The range from 0 to 99 is reserved for statically allocated system groups, which are essential for core operating system functions and services. In Linux, for example, GID 0 is assigned to the root group for superuser privileges, while GID 1 is typically used for the daemon group to manage background processes.[30][31] This convention is similarly adopted in other Unix variants, where low-numbered GIDs support predefined accounts like bin, sys, and adm to handle system resources securely.[32] For dynamic and local groups, higher ranges are designated for administrator- or user-created entities. In Linux, GIDs starting from 1000 are commonly used for such purposes, with distribution-specific limits; Debian, for instance, dynamically allocates non-system groups within 1000 to 59999 to support local user environments.[33] The Linux Standard Base further reserves 100 to 499 for dynamically allocated system groups by administrators or installation scripts, bridging static and user spaces.[31] Vendor-specific allocations vary to accommodate platform needs. In Solaris, GIDs under 100 are reserved for system defaults, while 100 to 60000 are available for user-defined groups, promoting interoperability without overlapping core functions.[32] As of 2025, systems like FreeBSD maintain similar reserved ranges, withgid_t as a 32-bit unsigned integer supporting up to 4,294,967,295 unique groups, even on 64-bit architectures.[34]
Special Values
In Unix-like operating systems, the group identifier (GID) 0 is reserved for the root group, which is associated with the superuser account and grants unrestricted access to all system resources and privileges.[30] This GID enables processes running under the root group to perform administrative tasks without limitations, such as modifying protected files or configuring kernel parameters. A special value of -1, often represented as(gid_t)-1, serves as an invalid or unspecified GID in various system calls.[35] For instance, in the chown(2) system call, specifying a GID of -1 indicates that the group ownership of the file should remain unchanged, allowing selective updates to ownership attributes.[35] This convention prevents unintended modifications and is also used in functions like setregid(2) to denote "no change" for the group ID. Due to the unsigned nature of gid_t, (gid_t)-1 typically resolves to the maximum value (e.g., 65535 on 16-bit systems or 4294967295 on 32-bit systems), which is avoided for actual group assignments to prevent conflicts.[36]
In Linux distributions, GID 65534 is frequently assigned to the "nogroup" or "nobody" group, designed for unprivileged services and daemons that require minimal access to enhance system security.[37] This high-numbered GID ensures that processes using it cannot inadvertently or maliciously affect other users' files, as it lacks membership in any other groups by default.[38] For example, web servers or anonymous FTP processes often run under this group to isolate their operations.
Certain Unix variants employ additional special GIDs for administrative purposes, such as the wheel group, commonly assigned GID 10 in systems like Fedora and Slackware, which controls access to elevated commands like su or sudo.[39] Membership in the wheel group allows users to assume root privileges selectively, providing a layer of control over superuser access without direct root logins.[40] In contrast, Windows NT and its successors utilize security identifiers (SIDs) rather than numeric GIDs for group management, with the built-in Administrators group (SID S-1-5-32-544) serving a similar privileged role to Unix's root or wheel groups.[41]
User Private Groups
Concept and Benefits
User private groups represent a security-oriented convention in Unix-like operating systems, where each user account is automatically assigned a unique primary group that shares the same name and group identifier (GID) as the user's login name. For instance, a user named "alice" with a user ID (UID) of 1001 would be assigned a primary group "alice" with GID 1001, ensuring the user is the sole member of this group. This setup leverages the primary group mechanism to control default ownership of files and directories created by the user.[42] This approach has been widely adopted in Linux distributions, such as Red Hat Enterprise Linux, where it became a standard practice for user account creation.[43][44] A key benefit of user private groups is enhanced security in multi-user environments, as it prevents unintended access to personal files even when using a permissive umask value like 002, which grants group read and write permissions on newly created files. Under this scheme, such files are owned by the user and their private group, restricting group-level access exclusively to the owner and thereby defaulting to user-only readability and writability. This isolation reduces the risk of accidental data exposure while simplifying overall permission management compared to shared primary groups.[42]Implementation Across Systems
In Linux systems, user private groups are enabled by setting theUSERGROUPS_ENAB variable to yes in the /etc/login.defs configuration file, which causes the useradd command to automatically create a new group with the same name and primary group ID as the username during user creation.[45] This default behavior is adopted in major distributions like Arch Linux, where it ensures each user has an isolated primary group for file ownership without additional flags.[46]
In BSD variants such as FreeBSD, user private groups are handled similarly through the adduser utility or the pw command, which by default assigns a primary group with the same name as the username and a group ID matching the user ID when creating new accounts.[34] This creates a private group automatically, though the interactive adduser process prompts for confirmation and allows opting into shared groups like "users" in some configurations or older setups; the pw command provides finer control for explicit assignments.[47]
In macOS, user private groups are not implemented by default; new users are assigned the shared "staff" group (GID 20) as primary. However, a private group matching the username can be created and assigned manually via tools like dscl in the Directory Services framework for isolation, and this can integrate with Open Directory for centralized management across networked environments.[48]
As of 2025, enhancements in containerized environments like Docker have improved user private group isolation through user namespaces, which remap container UIDs and GIDs to non-privileged host ranges, preventing privilege escalation and enabling secure per-user group handling in multi-tenant setups without root access on the host.[49] This feature, refined in Docker Engine updates, supports isolated UPGs by default in rootless mode, reducing risks in cloud-native deployments.[50]