User & Group Management

UID/GID, privilege escalation, setuid binaries, and PAM authentication in Linux

published: reading time: 25 min read author: GeekWorkBench

User & Group Management

Every process on a Linux system runs as a specific user and group. When you log into a server, you authenticate as a user identity that determines what files you can access, what operations you can perform, and what resources you can consume. This identity model is the foundation of Linux security, yet many administrators treat it as magical incantation rather than engineered system.

Understanding user and group management goes beyond knowing that root can do anything. It requires grasping the mechanics of identity transition, the security implications of privilege escalation mechanisms, and the flexibility of Pluggable Authentication Modules (PAM). When something goes wrong with permissions, often these fundamentals that reveal the root cause.

This post dissects the user and group system from the kernel perspective, examines privilege escalation pathways and their risks, and explores how authentication fits together through PAM.

Overview

Linux identifies users and groups by numeric IDs: User ID (UID) and Group ID (GID). Human-readable names like root, www-data, or pronit are conveniences that map to these numbers. The kernel does not care about names; it only cares about IDs.

UID 0 is the superuser (root) with unrestricted privileges. UID 1-999 are system users, reserved for system services and daemons. UID 1000+ are regular users, typically human accounts. This division is convention, not enforcement. GIDs follow similar patterns with the primary group 0 (root) and system groups in the 1-999 range.

Processes inherit UID and GID from their parent. When you log in, the login program authenticates you and spawns a shell running with your UID. Every command you run, every file you create, carries your identity. This identity determines whether you can read /etc/shadow, bind to port 80, or modify /var/log.

When to Use / When Not to Use

Deep understanding of user and group management becomes critical when designing multi-user systems, troubleshooting permission issues, securing servers against privilege escalation, or configuring single sign-on systems. System administrators, security engineers, and DevOps professionals need this knowledge for daily tasks.

Understanding these mechanisms helps diagnose why a service cannot access a resource, why privilege escalation succeeded or failed, or why a user’s login attempt was rejected. It enables proper configuration of shared systems, container security contexts, and automated deployment pipelines.

For single-user development machines, the default configuration suffices. The system is already set up correctly for your use case. However, understanding still matters when you encounter permission errors or need to run services on privileged ports.

Architecture or Flow Diagram

graph TD
    subgraph Authentication
        A[User Login] --> B{PAM Authentication}
        B -->|Success| C[ PAM Account Check]
        B -->|Failure| D[Login Rejected]
        C -->|OK| E[Set UID/GID]
        C -->|Fail| D
        E --> F[Spawn Shell]
    end

    subgraph Privilege Escalation
        G[Regular Process] --> H{Is setuid?}
        H -->|No| I[Same UID/GID]
        H -->|Yes| J[New UID/GID]
        J --> K[Capability Check]
        K -->|Has CAP| L[Privileged Op]
        K -->|No CAP| M[EPERM Denied]
    end

    subgraph File Access
        N[Process UID/GID] --> O{Check ACL/Permissions}
        O -->|Owner Match| P[Owner Permissions]
        O -->|Group Match| Q[Group Permissions]
        O -->|Neither| R[Other Permissions]
        P --> S{Execute Access}
        Q --> S
        R --> S
        S -->|Yes| T[Allow Operation]
        S -->|No| U[Permission Denied]
    end

    style D stroke:#ff6b6b
    style M stroke:#ff6b6b
    style U stroke:#ff6b6b

The diagram shows how authentication, privilege escalation, and file access interrelate. PAM handles initial authentication and can set the process identity. Setuid binaries run with different UIDs. File access checks the process UID/GID against file permissions at the moment of access.

Core Concepts

UID/GID Types

Linux distinguishes several UID categories within the kernel:

Real UID (RUID): The UID of the user who started the process. Always inherited from parent; only changed on login.

Effective UID (EUID): The UID used for permission checks. This is what matters for file access, capability checks, and privileged operations. Setuid programs run with the file owner’s EUID.

Saved UID (SUID): Allows a process to temporarily drop and restore privileges. When a setuid program changes its EUID, the original EUID is saved here.

Filesystem UID: Used on Linux for permission checks on filesystem operations. Usually identical to EUID, but can differ in certain container scenarios with user namespaces.

# View all UIDs for a process
id

# View specific process UIDs
cat /proc/$$/status | grep -E '^Uid|^Gid'

# Example output:
# Uid:    1000    1000    1000    1000
# Gid:    1000    1000    1000    1000
# (Real EUID Saved-UID Filesystem-UID)

Setuid and Setgid Binaries

Setuid (set user ID) is a permission bit that changes the effective UID of a process when executing a file. When you run /bin/passwd, it runs as root even if you are a regular user, because passwd has the setuid bit set. This allows users to modify their own password in /etc/shadow, which requires root privileges.

# Setuid on a binary
chmod u+s /usr/bin/program
# or
chmod 4755 /usr/bin/program

# Setgid on a binary (runs with group permissions)
chmod g+s /usr/bin/program
# or
chmod 2755 /usr/bin/program

# View setuid files
find /usr -perm /4000 -ls

# View setgid files
find /usr -perm /2000 -ls

Setgid works similarly but changes the effective GID. Setgid binaries are less common but important for group-accessible resources like write command that allows users to send messages to each other’s terminals.

PAM (Pluggable Authentication Modules)

PAM provides a flexible framework for authentication in Linux. Instead of hardcoding authentication logic, programs use PAM through a standard API. System administrators configure which PAM modules to use, enabling everything from simple password authentication to smartcard verification or LDAP integration.

# PAM configuration for a service
/etc/pam.d/sshd

# Typical structure:
# auth        - authentication modules
# account     - account expiration, access restrictions
# password    - password quality and changing
# session     - actions around session management
# Example /etc/pam.d/login
auth        required    pam_securetty.so
auth        required    pam_stack.so service=system-auth
auth        required    pam_nologin.so
account     required    pam_time.so
account     required    pam_stack.so service=system-auth
password    required    pam_stack.so service=system-auth
session     required    pam_selinux.so close
session     required    pam_selinux.so open
session     required    pam_stack.so service=system-auth
session     optional    pam_console.so

Production Failure Scenarios + Mitigations

Scenario: Password Authentication Failures

Problem: Users cannot log in despite correct credentials. PAM configuration or password database issues.

Symptoms: Login attempts fail, secure log shows PAM errors, users locked out.

Mitigation: Check PAM configuration syntax. Verify password database (local /etc/shadow or remote like LDAP) is accessible. Ensure NSS is correctly configured to resolve user information. Test authentication module independently.

# Test PAM authentication
authenticate username password

# Check password database
getent shadow username

# Verify NSS configuration
cat /etc/nsswitch.conf | grep -E 'passwd|group'

# Check if account is locked
passwd -S username

Scenario: Privilege Escalation via Sudo Misconfiguration

Problem: Users can execute commands as root or other users due to overly permissive sudo rules.

Symptoms: Unauthorized root access, security audit failures, unexpected privilege changes.

Mitigation: Audit sudoers file carefully. Follow principle of least privilege. Use specific command paths rather than allowing any command. Avoid NOPASSWD in production. Regularly review who has sudo access.

# View sudo rules for current user
sudo -l

# Safely edit sudoers
visudo

# Example restrictive rule
username ALL=(webapp:webapp) /bin/systemctl status webapp

# Check sudo access logs
grep sudo /var/log/secure
grep sudo /var/log/auth.log

Scenario: setuid Binary Exploitation

Problem: Vulnerable setuid binary allows privilege escalation to root.

Symptoms: Unexpected root shells, suspicious setuid binaries with world write access, privilege escalation alerts.

Mitigation: Remove unnecessary setuid binaries. Keep system updated. Use file integrity monitoring on critical binaries. Audit setuid binaries regularly.

# Find potentially dangerous setuid binaries
# World-writable setuid binaries
find / -perm -4007 -type f 2>/dev/null

# Not owned by root
find / -perm -4000 ! -user root -type f 2>/dev/null

# Monitor for changes
rpm -Va | grep -E '^\.\.5.*s'

Trade-off Table

Privilege MechanismSecurity LevelFlexibilityManagement Complexity
Standard sudoGoodHighMedium
Sudo with NOPASSWDLowerHighLow
PolkitGoodMediumMedium
Polkit without passwordLowerMediumLow
setuid binariesVariesLowHigh (binary vulns)
capabilitiesHighHighHigh
Authentication ModuleUse CaseSecurityComplexity
pam_unixLocal password authBasicLow
pam LDAPNetwork user authHigh (with TLS)Medium
pam_sssActive Directory/LDAPHighMedium
pam_sepermitTwo-factor authHighMedium
pam_accessHost-based accessMediumLow
UID ManagementContainer SupportPerformanceSecurity
Host UID/GIDPoorGoodLower
User namespacesExcellentGoodHigher
Remapped UID (LXD style)GoodGoodMedium

Implementation Snippets

Creating a Service Account with Restricted Access

#!/bin/bash
# Create service account with minimal privileges

# Create system account (no login shell)
useradd -r -s /sbin/nologin \
    -c "Web Application Service" \
    -d /var/www/webapp \
    webapp

# Set ownership
chown -R webapp:webapp /var/www/webapp

# Restrict login
usermod -L webapp  # Lock password
chsh -s /sbin/nologin webapp  # No shell access

# Verify
id webapp
passwd -S webapp

Configuring Sudo Access

# /etc/sudoers.d/webapp
# Allow webapp user to manage their service

webapp ALL=(systemd:webapp) /bin/systemctl status webapp.service
webapp ALL=(systemd:webapp) /bin/systemctl start webapp.service
webapp ALL=(systemd:webapp) /bin/systemctl stop webapp.service
webapp ALL=(systemd:webapp) /bin/systemctl restart webapp.service

# Allow reading logs
webapp ALL=(root) /bin/less /var/log/webapp/*.log

# Never allow
webapp ALL=(ALL) ALL  # DISALLOWED

PAM Configuration for Two-Factor Authentication

# /etc/pam.d/sshd
# Require both password and OTP

auth        required    pam_sepermit.so
auth        required    pam_env.so
auth        required    pam_unix.so     try_first_pass
auth        optional    pam_permit.so
auth        required    pam_google_authenticator.so nullok

account     required    pam_time.so
account     required    pam_unix.so
account     optional    pam_permit.so
account     required    pam_time.so

password    required    pam_unix.so     shadow nullok try_first_pass use_authtok
password    optional    pam_permit.so

session     required    pam_selinux.so close
session     required    pam_selinux.so open
session     required    pam_unix.so
session     optional    pam_permit.so

Checking Process Privileges

#!/usr/bin/env python3
"""Check process privileges and capabilities."""

import os
import pwd

def read_status(pid):
    """Read /proc/PID/status for privilege info."""
    status_path = f'/proc/{pid}/status'
    result = {}
    with open(status_path) as f:
        for line in f:
            if line.startswith(('Uid', 'Gid', 'Cap')):
                result[line.split(':')[0]] = line.split(':', 1)[1].strip()
    return result

def uid_to_name(uid):
    """Convert UID to username."""
    try:
        return pwd.getpwuid(int(uid)).pw_name
    except KeyError:
        return uid

def main():
    pid = os.getpid()
    status = read_status(pid)

    print(f"Process {pid} Privileges")
    print("=" * 40)

    # Parse UIDs
    uids = status['Uid'].split()
    print(f"Real UID:      {uids[0]} ({uid_to_name(uids[0])})")
    print(f"Effective UID: {uids[1]} ({uid_to_name(uids[1])})")
    print(f"Saved UID:     {uids[2]}")

    # Parse GIDs
    gids = status['Gid'].split()
    print(f"Real GID:      {gids[0]}")
    print(f"Effective GID: {gids[1]}")
    print(f"Saved GID:     {gids[2]}")

    # Parse capabilities
    caps = status.get('CapPermitted', '0')
    print(f"\nCapabilities: {caps}")

    # Check if running as root
    if uids[1] == '0':
        print("\nRunning as EUID root!")
    else:
        print(f"\nRunning as EUID {uid_to_name(uids[1])}")

if __name__ == '__main__':
    main()

Observability Checklist

User and Group Activity Monitoring:

  • Monitor /var/log/secure or /var/log/auth.log for authentication events
  • Track sudo usage patterns
  • Alert on repeated failed login attempts
  • Monitor for UID 0 logins from unexpected sources

Privilege Escalation Detection:

  • File integrity monitoring on setuid binaries
  • Alert on new setuid binaries
  • Monitor for unexpected processes running as root
  • Track sudo configuration changes

Account Status Monitoring:

  • Check for accounts with empty passwords
  • Identify accounts with NOPASSWD sudo rules
  • Monitor for newly created accounts
  • Track account expiration violations

Key Commands for Monitoring:

# View recent logins
last -20

# Failed login attempts
lastb -20

# Who is currently logged in
who

# Sudo command logging
grep sudo /var/log/secure | tail -30

# Check for root-owned processes running from unusual locations
ps aux | grep '^[a-z]* root' | grep -v /usr/sbin | grep -v /sbin

Security/Compliance Notes

Password Policy Enforcement: PAM modules like pam_pwquality enforce password complexity requirements. Configure minimum length, complexity, and rotation policies. Enable password hashing with strong algorithms (SHA-512, yescrypt).

Account Lockout: Prevent brute force attacks by locking accounts after failed attempts. Use pam_faillock to temporarily lock accounts.

# /etc/security/faillock.conf
deny = 5
unlock_time = 900
fail_interval = 600

Session Timeout: Force logout of idle sessions to prevent unauthorized access left behind. Configure TMOUT in bash profile or use pam_session timeout.

Audit Requirements: Many compliance frameworks require logging of authentication events, privilege changes, and administrative actions. Ensure your logging captures these events and retains them appropriately.

Common Pitfalls / Anti-patterns

World-writable setuid Binaries: Setting chmod 4777 on a setuid binary allows any user to become any other user. Always use restrictive permissions like chmod 4755 (root-owned setuid binary).

Misunderstanding Sudo NOPASSWD: Using NOPASSWD for convenience in production enables anyone with account access to run privileged commands without authentication. Reserve NOPASSWD for specific automated scripts with limited scope.

UID Collisions in Containers: When mapping host UIDs to container UIDs, ensure no collision with existing container UIDs. A container UID 0 mapping to host UID 100000 effectively gives container root access to host resources.

Stale sudo Tokens: Sudo caches credentials for 15 minutes by default. A session left unattended remains privileged. Consider timestamp_timeout=0 to require password for each sudo command, or set a shorter timeout.

PAM Misconfiguration: Incorrect PAM configuration can lock everyone out of the system or disable authentication entirely. Always test PAM changes from a separate session before closing your current one.

Quick Recap Checklist

  • Linux uses numeric UID/GID for all permission checks
  • Real, Effective, and Saved UIDs serve different purposes
  • Setuid binaries allow privilege escalation for specific programs
  • PAM provides flexible authentication through modular configuration
  • Sudo enables controlled privilege escalation without sharing root password
  • File permissions (rwx) and ACLs control file access
  • Capabilities provide fine-grained privilege control
  • User namespaces map UIDs for container isolation
  • Monitoring authentication and privilege events is essential
  • Principle of least privilege applies to all identity decisions

Interview Questions

1. What is the difference between Real, Effective, and Saved UIDs?

Real UID (RUID) is the original user who started the process, inherited from parent and only changed on login. Effective UID (EUID) is used for permission checks and determines what operations the process can perform. Saved UID (SUID) allows a process to temporarily drop and restore privileges; when a setuid program changes its EUID, the original is saved here for later restoration.

2. How does a setuid binary work and what are the security implications?

A setuid binary has a permission bit that causes it to run with the file owner's effective UID rather than the caller's. When you run /bin/passwd as a regular user, it runs as root, allowing it to modify /etc/shadow. Security risks include vulnerabilities in setuid binaries that can be exploited for privilege escalation. Remove unnecessary setuid binaries, keep systems updated, and use file integrity monitoring on critical binaries.

3. What is PAM and why is it important?

Pluggable Authentication Modules (PAM) provides a flexible framework for authentication in Linux. Instead of hardcoding authentication logic, programs use PAM through a standard API. Administrators configure which modules to use, enabling everything from simple password auth to smartcard verification or LDAP integration. PAM allows centralized control over authentication policy without modifying applications.

4. What is the principle of least privilege in user management?

Least privilege means granting a user or process only the minimum permissions required for its function. Service accounts should run with specific UIDs and no login capability. Sudo rules should specify exact commands rather than allowing ALL. Capabilities should be dropped except those explicitly required. This limits damage from compromise and reduces attack surface.

5. How do UID collisions in containers create security vulnerabilities?

When mapping host UIDs to container UIDs, if container UID 0 maps to host UID 100000, the container's root effectively has host user 100000's permissions. If host UID 100000 owns files, the container root can modify them. A container escape plus UID mapping can give the attacker read/write access to host files owned by that UID. User namespaces mitigate this by providing truly isolated UID mappings.

6. How does the kernel handle UID/GID during a execve() system call?

During execve(), the effective UID and saved UID behave differently depending on whether the executable has a setuid or setgid bit. If the binary has a setuid bit, the kernel sets the process's effective UID to the file's owner UID before executing the new program. The saved UID is updated to copy the effective UID at the moment of execve, so the original caller's UID is preserved for potential privilege dropping.

For setgid binaries, the effective GID similarly changes to the file's group owner. Capabilities are recalculated after execve based on the new effective UID/GID and the file's capability sets. This behavior is why a setuid program can perform privileged operations while still being able to restore the original user's privileges later using the saved UID.

7. What is the difference between NSS and PAM?

NSS (Name Service Switch) and PAM (Pluggable Authentication Modules) serve different purposes despite both being modular authentication infrastructure. NSS resolves names to values: it maps usernames to UIDs (getpwnam()), group names to GIDs (getgrnam()), and hostnames to IP addresses. NSS uses a stacked configuration in /etc/nsswitch.conf to query sources like files, DNS, LDAP, or NIS in order.

PAM handles the authentication and session setup itself: verifying passwords, checking account validity, managing session setup and cleanup. A program uses PAM to authenticate a user (Is this password correct?) and to establish the session (Set up environment, create home directory). NSS is consulted by PAM to look up the user's UID, GID, and home directory after successful authentication.

8. How does Polkit differ from sudo for privilege escalation?

Polkit (PolicyKit) and sudo serve different privilege escalation models. Sudo grants specific commands to specific users with full root privileges for those commands. Polkit provides a framework for authorizing actions based on a policy database, where programs (like GNOME's system tools) query whether the current user is authorized to perform an action, and Polkit can prompt for authentication or check session activity.

Polkit's strength is fine-grained, context-aware authorization: it can allow a user to mount disks without a password when they are physically logged into the console, but require a password over SSH. It separates authentication (who are you?) from authorization (are you allowed to do this?). Sudo is simpler and more direct, making it better suited for server environments where specific command grants are needed.

9. What are the security implications of password hashing algorithms used in /etc/shadow?

Password hashes in /etc/shadow use configurable algorithms: DES (old, 56-bit key, trivially crackable), MD5 (salt + MD5, too fast for modern GPUs), SHA-256 and SHA-512 (salted, configurable rounds), and yescrypt/bcrypt/argon2 (memory-hard, resistant to GPU and ASIC attacks). The /etc/login.defs or PAM configuration specifies which algorithm is used for new passwords.

Weak hashing algorithms expose passwords to offline cracking attacks if the shadow file is leaked. DES and MD5 are considered broken for password storage. Modern systems should use SHA-512 with a high round count (500000+) or yescrypt/argon2 which are designed to resist brute-force attacks by requiring significant memory and computation. The cracklib library enforces password complexity before hashing.

10. How does account lockout work with PAM and what are the security tradeoffs?

PAM's pam_faillock module tracks failed authentication attempts per user in /var/run/faillock/ and locks the account after a configurable number of failures within a time window. When the account is locked, any login attempt (even with the correct password) returns authentication failure until the lockout expires or an administrator clears it.

Tradeoffs: lockout prevents brute-force attacks but creates a denial-of-service vector where an attacker can repeatedly try wrong passwords to lock out legitimate users. Some deployments use progressive delays instead of hard lockout. Long lockout durations increase security but also increase support burden. For SSH with key-based authentication, the sshd_config MaxAuthTries limits should be combined with PAM lockout to prevent both password brute-force and key-guessing attacks.

11. What are Access Control Lists (ACLs) and how do they extend traditional Unix permissions?

ACLs (Access Control Lists) extend traditional Unix permissions (owner/group/other with rwx) to support arbitrary lists of users and groups with specific permissions. POSIX ACLs use setfacl and getfacl commands, storing additional entries alongside the traditional permission bits. Each file can have a default ACL (inherited by new files in the directory) and an access ACL (effective permissions).

Extended ACL entries specify a qualifier (user or group UID/GID), a permissions set (rwx), and apply to named users, named groups, or the mask (which limits maximum permissions for named entries and group entries). ACLs solve the limitation where a file can only belong to one group and a user can only belong to a fixed number of groups (typically 16-32 per system).

12. What special properties does UID 0 (root) have in Linux beyond capabilities?

UID 0 (root) bypasses most permission checks in the kernel, but not all. Root can bypass file permission checks (read, write, execute) due to the inode-level check, but certain security mechanisms are independent of UID: SELinux or AppArmor mandatory access controls apply even to root, immutable files cannot be modified even by root (chattr -i), and certain system calls have additional capability checks even for UID 0.

Files with the immutable flag (chattr +i) cannot be deleted or modified regardless of UID 0, requiring the flag to be removed first. The CAP_SYS_RESOURCE capability (which UID 0 typically has) controls overrides of resource limits, core dump size, and filesystem quotas. Understanding that root is not absolutely supreme clarifies why capability dropping and MAC systems add defense in depth.

13. How does the sticky bit on directories work and what security properties does it provide?

The sticky bit (chmod +t or 1000 in octal) on a directory prevents users from deleting or renaming files they do not own within that directory. Classic example: /tmp has the sticky bit, allowing all users to create files there but preventing User A from deleting User B's file.

Without the sticky bit, any user with write permission on a directory could delete any file in it (since directory write permission controls deletion, not file write permission). The sticky bit adds a secondary check: the kernel verifies that the user attempting deletion either owns the file or owns the directory. On modern Linux, /tmp without the sticky bit would allow any user to delete any other user's files, causing obvious security and privacy issues.

14. What is the difference between useradd -r and useradd without -r?

useradd -r (or useradd --system) creates a system account with a UID in the range 1-999 (or the configured system account range). System accounts are not typically used for human login and are intended for running services. They typically have no valid login shell (/sbin/nologin or /usr/sbin/nologin) and no password.

A regular user account (useradd without -r) gets a UID starting at 1000 (or the configured range minimum). Regular users have password-enabled login capability and typically have functional shells like /bin/bash. Using system accounts for services follows the principle of least privilege: a compromised service running as UID 1-999 has no login capability and limited filesystem access by default.

15. How does the kernel resolve group membership for file access decisions?

When a process attempts to access a file, the kernel checks the process's effective UID and GID against the file's owner UID and owner GID. If the process's effective UID matches the file's owner UID, owner permissions apply. If not, the kernel then checks if any of the process's supplementary group IDs (not just the effective GID) match the file's owner GID, applying group permissions on a match.

A process can belong to up to 32 groups (NGROUPS_MAX, typically 65536 in modern kernels, queried with sysconf(_SC_NGROUPS_MAX)). When checking group membership, the kernel compares each supplementary group ID against the file's owner GID. If no group matches, other permissions apply. The groups command and getgrouplist() show which groups a user belongs to, reflecting both the primary group and supplementary groups from /etc/group.

16. What is the difference between fork() and vfork() regarding UID inheritance?

Both fork() and vfork() create child processes that inherit the parent's real, effective, and saved UIDs. However, vfork() was designed for performance in scenarios where the child would immediately call execve(), avoiding the full copy-on-write page table duplication of fork(). The child shares the parent's memory entirely until execve, which requires careful synchronization.

In modern Linux, fork() with copy-on-write is efficient enough that vfork()'s performance advantage is negligible, and vfork()'s strange semantics (the parent is blocked until the child calls execve or exit) make it a footgun. vfork() is still present for POSIX compliance and a few specialized cases, but fork() is the correct choice for nearly all scenarios. UID inheritance is identical in both.

17. How does LDAP authentication integrate with Linux through PAM and NSS?

LDAP authentication integrates through two separate mechanisms. PAM (pam_ldap or pam_sss) handles the authentication step: verifying the password by binding to the LDAP server with the user's credentials. NSS (nss_ldap or nsswitch.conf entries) handles name-to-UID resolution: when a program calls getpwnam("alice"), NSS queries LDAP to find Alice's UID, GID, home directory, and shell.

The sssd daemon (System Security Services Daemon) provides a unified interface to multiple identity providers (LDAP, Active Directory) with caching for offline login and reduced LDAP server load. PAM configuration in /etc/pam.d/common-auth stacks authentication modules so that LDAP is consulted along with local /etc/passwd and /etc/shadow.

18. What is a process's credential structure and which fields does the kernel maintain?

The kernel maintains a cred structure for each process containing: uid (real UID), gid (real GID), suid (saved UID), sgid (saved GID), euid (effective UID), egid (effective GID), fsuid (filesystem UID used for permission checks), fsgid (filesystem GID), plus capability sets (permitted, effective, inheritable, bounding). All threads in a process share the same cred structure.

The /proc/PID/status shows these as Uid and Gid lines with four values each (real, effective, saved-set, filesystem). The capability value shows the permitted capability bitmask. Process credentials are checked by the kernel at every permission-sensitive operation, and the commit_creds() function atomically replaces a process's credentials.

19. How does keyctl allow processes to share credentials without passing UIDs directly?

The Linux keyctl facility provides a kernel-managed keyring that can store arbitrary data (including credential information) with access control based on process UID/GID. Processes can use keyctl_read() and keyctl_write() to pass data between processes with matching UIDs, without the data being visible to other users. This is used by some session management systems to store session credentials securely.

The session keyring (keyctl join_session_keyring) links a keyring to a login session. When a process authenticates (via PAM or similar), credentials can be stored in the session keyring that all processes in the session can access. This allows credential propagation across fork()/execve() without storing sensitive data in environment variables or files.

20. What is the security model difference between capabilities and setuid root binaries?

Setuid root binaries grant full root privilege to any process that executes them, regardless of what the process actually needs. A vulnerable setuid binary can be exploited to spawn a root shell, giving the attacker complete control. The attack surface is the entire binary, not just the specific privileged operation.

Capabilities split root privileges into ~40 discrete units (CAP_NET_BIND_SERVICE, CAP_SYS_TIME, etc.), allowing a process to receive only the specific privileges it requires. A process with only CAP_NET_BIND_SERVICE cannot spawn a root shell even if it is exploited. Capabilities use file-based capability sets: a capability-aware binary's effective capability set at execve is determined by the file's permitted and inheritable sets and the process's inheritable set. This follows the principle of least privilege at a granular level.

Further Reading

Conclusion

Linux user and group management through UID/GID, setuid binaries, PAM, and capabilities forms the identity foundation for system security. Real, Effective, and Saved UIDs each play a distinct role in how privilege transitions happen. Setuid binaries and sudo let you escalate privileges for specific tasks without sharing root passwords. PAM plugs into authentication flexibly, which is why it handles enterprise setups like LDAP or smartcards without touching application code. For deeper study, look at how user namespaces map container UIDs, how Polkit separates authorization from authentication, and how identity management integrates with directories like Active Directory.

Category

Related Posts

ASLR & Stack Protection

Address Space Layout Randomization, stack canaries, and exploit mitigation techniques

#operating-systems #aslr-stack-protection #computer-science

Assembly Language Basics: Writing Code the CPU Understands

Learn to read and write simple programs in x86 and ARM assembly, understanding registers, instructions, and the art of thinking in low-level operations.

#operating-systems #assembly-language-basics #computer-science

Boolean Logic & Gates

Understanding AND, OR, NOT gates and how they combine into arithmetic logic units — the building blocks of every processor.

#operating-systems #boolean-logic-gates #computer-science