interview-prep

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:

  1. If effective UID == file owner UID → apply owner bits
  2. If effective GID == file group GID OR any supplementary group matches → apply group bits
  3. 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."


My notes