Crisp answer: The kernel checks permissions based on the process's effective UID and GID against the file's owner, group, and other fields. The first matching category wins.
The permission check algorithm:
When a process tries to access a file, the kernel evaluates in order:
- If
effective UID == file owner UID→ apply owner bits - If
effective GID == file group GIDOR any supplementary group matches → apply group bits - Otherwise → apply other bits
Only one set of bits applies. If you're the owner, only owner bits apply even if the group bits are more permissive.
UID types for a process:
| Type | What | Changed by |
|---|---|---|
| Real UID (RUID) | Who actually started the process | The logged-in user |
| Effective UID (EUID) | What the kernel checks for permissions | setuid programs, sudo |
| Saved UID (SUID) | Allows switching back after temporary privilege drop | setuid programs |
id # Shows UID, GID, and all supplementary groups
cat /proc/<pid>/status | grep -E "^(Uid|Gid)"
# Uid: 1000 1000 1000 1000
# Real Effective Saved Filesystem
SUID (setuid) in practice:
The passwd command lets regular users change their own passwords, which
requires writing /etc/shadow (owned by root, mode 640). Passwd has the
setuid bit set, so when you run it, your process's effective UID becomes 0
(root):
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root ... /usr/bin/passwd
# ^ 's' = SUID bit: runs with owner's (root's) effective UID
sudo vs su:
sudo runs a command with elevated privileges (typically root) using PAM
for authentication. It sets the effective UID to 0 for the duration of the
command. su switches the entire shell to another user by setting real UID,
effective UID, and supplementary groups.
Supplementary groups:
A process can be a member of multiple groups simultaneously. File access checks include all supplementary groups, not just the primary GID:
id joyson
# uid=1000(joyson) gid=1000(joyson) groups=1000(joyson),4(adm),27(sudo),1001(docker)
# If a file has group=docker and group perms allow read,
# joyson can read it because of the supplementary docker group
Capabilities (Linux capabilities):
Root's powers are split into ~41 capabilities. A process can have individual capabilities without being fully root:
| Capability | Allows |
|---|---|
CAP_NET_ADMIN |
Configure network interfaces, iptables |
CAP_SYS_ADMIN |
Wide range of admin tasks (avoid if possible) |
CAP_CHOWN |
Change file ownership |
CAP_DAC_OVERRIDE |
Bypass file permission checks |
CAP_SYS_PTRACE |
Use ptrace (required for strace) |
capsh --print # Current capabilities
setcap cap_net_bind_service+ep /usr/bin/node # Allow node to bind port 80 without root
getcap /usr/bin/node # Check capabilities on a binary
What to say in the interview:
"The kernel checks the process's effective UID and GID against the file's permission bits. If effective UID matches the file owner, only owner bits apply. If a supplementary group matches the file group, group bits apply. Otherwise other bits. The important nuance is supplementary groups — a process can have many group memberships simultaneously, which is why adding a user to the docker group gives them access to the docker socket. For privilege escalation, setuid programs temporarily change the effective UID — that's how passwd can write /etc/shadow without the user being root."