Infra, Illustrated.
LINUX FOUNDATION · IDENTITY CONSOLE

Identity & Access

Follow usernames from human configuration through NSS resolution into the numeric kernel credential vectors (RUID, EUID, FSUID) and hierarchical directory traversal gates.

← Back to Linux MapREFERENCE HOST · devbox-01DEEP DIVE · FOUNDATIONALPublished Sep 15, 2026 · Reviewed Sep 18, 2026
CHAPTER 01 / 08 · 8 VISUAL LESSONS

What this chapter builds

Start here if usernames, groups, sudo, SSH, and file permissions feel like one security feature. This chapter separates account lookup, process credentials, authentication, and authorization.

By the end, you can

  • Resolve a name to numeric identity without confusing NSS with authentication
  • Predict which owner, group, or other mode class the kernel selects
  • Locate the first directory that blocks a pathname
  • Explain what sudo and SSH change—and what they do not

Objects to keep straight

struct credUID / GID vectorsinode ownershipsupplementary groups

Applied task: Diagnose why nginx UID 33 cannot read /srv/site/config.json without reaching for chmod 777.

SCENARIO · devbox-01 / nginxCore concepts
OBJECT Core conceptsSTATE ready to inspectOWNER process credentials
01 / IDENTITY · SYSTEM MODEL

Before looking at the mechanics, what actually is a User or a Group?

What are the foundational primitives of Linux Identity?

DEVBOX-01 · CORE CONCEPTSGLOSSARY

UID (User ID)

Analogy: A Social Security Number

Linux does not care about your username ("nginx"). It only cares about an integer number (e.g. 33). This integer is stamped onto every process and every file to determine who owns what.

GID (Group ID)

Analogy: A Company Department Badge

Another integer. A single UID can belong to multiple GIDs (like belonging to both HR and Engineering). This allows multiple different users to share access to the same files.

NSS (Name Service Switch)

Analogy: A Phonebook Directory

The system that translates human names (like "nginx") into the integer IDs (like 33). It can look up names in local files (/etc/passwd) or over the network (Active Directory).

Mode Bits (Permissions)

Analogy: Three Locks on a Door

Every file has 3 locks: one for the Owner UID, one for the Group GID, and one for Everyone Else. Each lock grants or denies Read, Write, or Execute access.

Strip away the usernames. At the kernel level, you are just an integer UID knocking on a door with a matching integer lock.

Identity in Linux fundamentally reduces to two 32-bit integers: a UID and a GID. Everything you do on a Linux system—starting a web server, reading a file, SSHing in—is evaluated mathematically by the kernel comparing your process's UID against a file's UID. Human names like "root" are just illusions provided by user-space tools for our convenience.

Model scope. The kernel evaluates numeric credentials, not the spelling of a username. UID 0 conventionally receives a full capability set, but namespaces, dropped capabilities, LSM policy, seccomp, and mount state can still constrain a process.

INSPECT · id
uid=1000(darshan) gid=1000(darshan) groups=1000(darshan),27(sudo)
NEXT PROBE · stat -c "%u:%g" /etc/passwd
0:0
Primary source ↗
02 / IDENTITY · SYSTEM MODEL

Usernames are human syntax; the kernel only evaluates numeric IDs.

How does Linux translate a username into kernel-enforced credentials?

DEVBOX-01 · NSS RESOLUTION LABREADY TO INSPECT
1. RESOLVER CONFIGURATION/etc/nsswitch.conf

Configure the order glibc searches for users.

passwd:
2. DATABASE CONTENTS
files (/etc/passwd)
root:x:0:0::/root:/bin/bash
nginx:x:33:33::/var/cache/nginx:/sbin/nologin
sss (Active Directory / LDAP)
ldap_user:x:5001:5001::/home/ldap_user:/bin/bash
nginx:x:9999:9999::/network/nginx:/bin/bash
3. APPLICATION LOOKUPglibc getpwnam()
GUIDED SCENARIOS:
4. RESOLUTION TRACE
Never grep /etc/passwd in automation; use getent passwd to query the full NSS resolution chain.

When a service starts or a user authenticates, glibc calls getpwnam() to resolve the username. The Name Service Switch (/etc/nsswitch.conf) configures the resolution order—typically local files first, then directory services like LDAP, SSSD, or Winbind. The kernel itself has no concept of usernames; all discretionary access checks operate exclusively on 32-bit integer UIDs and GIDs.

Model scope. In rootless containers and user namespaces, container UID 0 is mapped to an unprivileged high UID on the host (e.g. 100000) via /etc/subuid.

INSPECT · getent passwd nginx
nginx:x:33:33:nginx user:/var/cache/nginx:/sbin/nologin
NEXT PROBE · id -u nginx
33
Primary source ↗
03 / IDENTITY · SYSTEM MODEL

Every process carries a vector of distinct numeric identities.

Which UIDs does a running process hold, and which one gates file access?

DEVBOX-01 · SYSTEM MODELREADY TO INSPECT
The Effective and Filesystem UIDs govern permission checks; verify them via ps -eo pid,user,euser or /proc/<pid>/status.

Linux processes do not hold a single UID; the kernel maintains a credential structure (struct cred) with Real, Effective, Saved, and Filesystem IDs. The Real UID tracks who started the process. The Effective UID determines process privileges and signals. The Filesystem UID (FSUID) is tested for all filesystem open() and stat() operations, allowing NFS daemons and setuid binaries to drop filesystem privileges without losing signal control.

Model scope. Saved UID (SUID) allows a process that temporarily lowered its EUID to regain root privileges when needed, a pattern common in setuid utility binaries.

INSPECT · ps -eo pid,user,euser,comm | grep nginx
  418 root     root     nginx
  421 nginx    nginx    nginx
NEXT PROBE · grep -E "^(Uid|Gid):" /proc/421/status
Uid:	33	33	33	33
Gid:	33	33	33	33
Primary source ↗
04 / IDENTITY · SYSTEM MODEL

The Linux Access Control Matrix: Subject vs Object.

How does the kernel match process credentials against file mode bits?

DEVBOX-01 · ACCESS CONTROL MATRIX LABREADY TO INSPECT
SUBJECT (PROCESS)Who is asking for access?
KERNEL DAC LADDERAccess Control Evaluation
1
OWNER MATCH?Is Process UID == File Owner UID?
--
2
GROUP MATCH?Is File GID in Process Groups?
--
3
FALLBACK TO OTHERApply "Other" bits
--
SELECT A PROCESS
OBJECT (FILE)What are we accessing?
📄
/path
Owner: 0Group: 0
Mode Bits: 000
OWNER
GROUP
OTHER
Permissions are evaluated strictly numerically. Changing group memberships requires the process to restart to acquire the new GID.

Linux separates identity from access control. For ordinary mode-bit checks, the kernel compares a process's effective credentials with inode ownership, selects exactly one class—owner, matching group, or other—and evaluates that class. Relevant capabilities can override specific DAC checks; that is narrower than a universal “root bypass.”

Model scope. PAM (Pluggable Authentication Modules) can bypass local databases completely when authenticating against OAuth or LDAP.

INSPECT · id
uid=33(nginx) gid=33(nginx) groups=33(nginx),1001(appgroup)
NEXT PROBE · stat -c "%a %U:%G" /srv/site/config.json
640 root:appgroup
Primary source ↗
05 / IDENTITY · SYSTEM MODEL

Access is a hierarchical walk: ancestor directories gate the leaf file.

Why can a process with read permission on a file still get Permission Denied?

DEVBOX-01 · SYSTEM MODELBLOCKED FIXTURE
GATE 1: ROOT/ (root)Mode 0755 · other has +x
✓ GRANTED
GATE 2: MOUNT/srvMode 0755 · other has +x
✓ GRANTED
GATE 3: PARENT DIR/srv/siteMode 0750 · worker not in group
✗ DENIED (EACCES)
GATE 4: TARGETindex.htmlMode 0777 · read check
NOT REACHED!
FAILURE / ALTERNATE STATE SIMULATION

Default fixture: To open any file, the kernel must resolve every component of its path from the root directory downward (path_resolution(7)). For every directory along the way, the process requires the execute (+x) permission bit, which functions as the "search" right. If even one ancestor directory denies execute permission to the process credentials, traversal immediately aborts with EACCES (Permission Denied)—the leaf file permissions are never even evaluated.

Directory execute (+x) means search/traverse; directory read (+r) means list filenames. Without +x, you cannot access files inside.

To open any file, the kernel must resolve every component of its path from the root directory downward (path_resolution(7)). For every directory along the way, the process requires the execute (+x) permission bit, which functions as the "search" right. If even one ancestor directory denies execute permission to the process credentials, traversal immediately aborts with EACCES (Permission Denied)—the leaf file permissions are never even evaluated.

Model scope. The namei utility is essential in production to inspect permissions at every step of a path chain simultaneously.

INSPECT · namei -om /srv/site/index.html
f: /srv/site/index.html
 drwxr-xr-x root root / 
 drwxr-xr-x root root srv
 drwxr-x--- root root site    # BLOCKED: other lacks +x
 -rwxrwxrwx root root index.html
NEXT PROBE · sudo -u nginx cat /srv/site/index.html
cat: /srv/site/index.html: Permission denied
Primary source ↗
06 / IDENTITY · SECURITY ACCESS LAB

chmod 777 destroys security boundaries and masks architectural bugs.

Why is chmod 777 dangerous, and how do you implement least-privilege access?

DEVBOX-01 · SECURITY BOUNDARY LABSECURITY COMPROMISED (TRAP ACTIVE)
🔓WORLD-ACCESSIBLE PERMISSION (0777)rwxrwxrwx — DAC Protection Completely Disabled
UNTRUSTED ACTORRogue Process / AttackerUID 1000 / other
COMPROMISED ASSET/srv/app/config.jsonWorld-readable & world-writable
⚠ Critical Risk: Any unprivileged local user or breached container process can read secrets or overwrite configuration.
$ chmod -R 777 /srv/site
# "Works" immediately, but directory is now world-writable and vulnerable to tampering
Why this is dangerous:

World-writable directories allow any unprivileged process or compromised container to overwrite application binaries, tamper with logs, or plant backdoors. It treats an access-control failure by eliminating access control entirely.

Use group ownership (chgrp) and targeted modes (0640/0750) rather than opening the door to world-write permissions.

Every permission error has an exact reason: a specific UID or GID failed a specific bit check on a specific inode. Least-privilege system administration requires assigning files to a shared group (like www-data or appgroup) and using mode 0640 for files and 0750 for directories. This ensures application workers can read their data while preventing rogue processes from reading secrets or altering code.

Model scope. SetGID on directories (chmod g+s /dir) causes new files created inside to automatically inherit the directory group rather than the creating user primary group.

INSPECT · stat -c "%a %U:%G" /srv/site/index.html
640 root:www-data
NEXT PROBE · sudo -u nginx test -r /srv/site/index.html && echo "Read OK"
Read OK
Primary source ↗
07 / IDENTITY · PIPELINE WALKTHROUGH

Controlled privilege delegation with attributable records.

How does sudo safely elevate process credentials from unprivileged to root?

DEVBOX-01 · EXECUTION PIPELINESTAGE 01 / 04 ACTIVE
INTERACTIVE STAGE STEPPER

Stage 01: sudo -l lists all allowed privileges for the current user, including NOPASSWD exemptions for automated operational commands.

$ sudo -l
User dev1 may run the following commands on devbox-01:
    (ALL : ALL) ALL
    (root) NOPASSWD: /bin/systemctl restart nginx

sudo -l lists all allowed privileges for the current user, including NOPASSWD exemptions for automated operational commands.

sudo can delegate narrowly scoped commands and produce useful accountability records; the policy and logging pipeline determine how strong that control is.

The sudo binary relies on the setuid permission bit (mode 04755). When an ordinary user executes /usr/bin/sudo, the kernel transitions the process Effective UID (EUID) to 0 (root) while preserving the Real UID (RUID). sudo reads /etc/sudoers, checks if the invoking user is authorized to run the command, prompts for authentication, and logs the execution to journald or /var/log/auth.log before execve()ing the command.

Model scope. By default, sudo sanitizes the environment (env_reset), stripping LD_PRELOAD, PATH, and custom variables to prevent privilege escalation exploits.

INSPECT · sudo -u nginx whoami
nginx
NEXT PROBE · ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 232416 /usr/bin/sudo # Notice "s" setuid bit!
Primary source ↗
08 / IDENTITY · RUNBOOK STATE MACHINE

Cryptographic challenge-response eliminates brute-force vectors.

How does SSH public key authentication work at the protocol level?

DEVBOX-01 · RUNBOOK STATE MACHINEACTION 01 / 05 ACTIVE
RUNBOOK ACTION STEPPER

Action 01: Generate modern elliptic-curve keypair

$ ssh-keygen -t ed25519 -C "admin@devbox-01"
Your identification has been saved in ~/.ssh/id_ed25519
Your public key has been saved in ~/.ssh/id_ed25519.pub

Field Note: Ed25519 keys are faster, shorter, and cryptographically superior to legacy RSA-2048 keys.

Never expose a production server with PasswordAuthentication enabled; enforce Ed25519 keys and strict file permissions.

SSH public-key authentication uses proof of private-key possession. After the server accepts a permitted public key, the client signs session-bound authentication data with its private key; the private key never crosses the network. The server verifies that signature, then applies account, PAM, and session policy before starting the requested session.

Model scope. sshd will silently reject public key authentication if ~/.ssh (0700) or ~/.ssh/authorized_keys (0600) are writable by group or other (StrictModes).

INSPECT · cat ~/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyPayload admin@devbox-01
NEXT PROBE · sshd -T | grep -E "^(passwordauthentication|pubkeyauthentication)"
pubkeyauthentication yes
passwordauthentication no
Primary source ↗