User and Group Fundamentals
{:.gc-basic}
Basic
Linux is a multi-user OS. Every process runs as a user, every file is owned by a user+group pair, and the kernel enforces access through these identities.
Key Files
/etc/passwd # User accounts (username:x:UID:GID:GECOS:home:shell)
/etc/shadow # Hashed passwords (root-readable only)
/etc/group # Group definitions (groupname:x:GID:members)
/etc/gshadow # Group passwords (rare)
Viewing the password file:
$ cat /etc/passwd | head -4
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
eslam:x:1000:1000:Eslam Mohamed,,,:/home/eslam:/bin/bash
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
# name:x:UID:GID:comment:home:shell
User Management Commands
# Add a user (high-level, interactive)
sudo adduser eslam
# Add a user (low-level, scriptable)
sudo useradd -m -s /bin/bash -G sudo,developers eslam
# Set / change password
sudo passwd eslam
# Modify user
sudo usermod -aG docker eslam # add to docker group (append!)
sudo usermod -s /bin/zsh eslam # change shell
sudo usermod -l newname eslam # rename login
sudo usermod -L eslam # lock account
sudo usermod -U eslam # unlock account
# Delete user
sudo userdel eslam # keep home directory
sudo userdel -r eslam # delete home + mail spool
# Get info about current user
id
whoami
groups
id output:
$ id
uid=1000(eslam) gid=1000(eslam) groups=1000(eslam),4(adm),24(cdrom),27(sudo),1001(docker)
Group Management
sudo groupadd developers # create group
sudo groupdel developers # delete group
sudo gpasswd -a eslam devs # add user to group
sudo gpasswd -d eslam devs # remove user from group
getent group docker # show group members
File Permissions
{:.gc-basic}
Reading Permission Bits
Every file has 9 permission bits (3 for owner, 3 for group, 3 for others):
- rwx r-x r--
│ │ │ └── other: r=4, -=0, -=0 → 4
│ │ └─────── group: r=4, -=0, x=1 → 5
│ └──────────── owner: r=4, w=2, x=1 → 7
└──────────────── type: - file, d dir, l link, c char, b block
chmod — Change Permissions
Symbolic mode:
chmod u+x script.sh # add execute for owner
chmod g-w file.txt # remove write from group
chmod o=r file.txt # set other to read-only
chmod a+x script.sh # add execute for all (u+g+o)
chmod u=rwx,g=rx,o= file # set all at once
Octal mode:
chmod 755 script.sh # rwxr-xr-x — typical for executables
chmod 644 file.txt # rw-r--r-- — typical for data files
chmod 600 id_rsa # rw------- — SSH private keys
chmod 700 ~/.ssh # rwx------ — SSH directory
chmod 777 /tmp/shared # rwxrwxrwx — world-writable (avoid in prod!)
chown — Change Owner
sudo chown eslam file.txt # change owner
sudo chown eslam:developers file.txt # change owner and group
sudo chown :developers file.txt # change group only
sudo chown -R eslam:eslam /home/eslam # recursive
sudo and /etc/sudoers
# Run command as root
sudo apt update
# Run as specific user
sudo -u www-data nginx -t
# Edit sudoers safely (validates syntax before saving)
sudo visudo
/etc/sudoers syntax:
# user host=(run_as) commands
eslam ALL=(ALL:ALL) ALL # full sudo
eslam ALL=(ALL) NOPASSWD: /bin/systemctl restart nginx
%sudo ALL=(ALL:ALL) ALL # group sudo (% = group)
Special Permission Bits
{:.gc-mid}
Intermediate
SUID (Set User ID) — bit 4000
When set on an executable, the process runs with the file owner’s UID, not the caller’s.
chmod u+s /usr/bin/passwd
# or
chmod 4755 /usr/bin/passwd
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59640 Nov 24 2022 /usr/bin/passwd
# ^ 's' = SUID is set
Why it exists: passwd must write to /etc/shadow (owned by root). With SUID, any user can run passwd and it temporarily gets root UID to update the shadow file — but only for that specific task.
Security implication: SUID binaries with vulnerabilities become privilege escalation vectors. Audit them with:
find / -perm /4000 -type f 2>/dev/null
SGID (Set Group ID) — bit 2000
On an executable: process runs with file’s group GID. On a directory: new files inherit the directory’s group (very useful for shared project dirs).
chmod g+s /shared/project
# or
chmod 2755 /shared/project
$ ls -ld /shared/project
drwxrwsr-x 2 root devteam 4096 Mar 5 10:00 /shared/project
# ^ 's' = SGID on directory
Sticky Bit — bit 1000
On a directory: users can only delete/rename their own files, even if they have write permission on the directory. Essential for /tmp.
chmod +t /tmp
# or
chmod 1777 /tmp
$ ls -ld /tmp
drwxrwxrwt 12 root root 4096 Mar 7 08:00 /tmp
# ^ 't' = sticky bit
umask — Default Permission Mask
umask subtracts bits from the default permissions (666 for files, 777 for dirs).
$ umask
0022 # means new files = 666-022 = 644, new dirs = 777-022 = 755
umask 027 # new files = 640, new dirs = 750 (no world access)
umask 077 # files = 600, dirs = 700 (private, good for home dirs)
Set it persistently in ~/.bashrc or /etc/profile.
Access Control Lists (ACLs)
{:.gc-mid}
Standard Unix permissions only allow one owner and one group. ACLs let you grant fine-grained access to specific users or groups.
# Install
sudo apt install acl
# View ACL
getfacl /shared/project
# Give user bob read+write on a file
setfacl -m u:bob:rw file.txt
# Give group qa read-only
setfacl -m g:qa:r-- /shared/reports/
# Set default ACL on a directory (inherited by new files)
setfacl -d -m u:bob:rw /shared/project/
# Remove specific ACL entry
setfacl -x u:bob file.txt
# Remove all ACLs
setfacl -b file.txt
getfacl output:
$ getfacl /shared/project
# file: shared/project
# owner: eslam
# group: devteam
# flags: -s-
user::rwx
user:bob:rw-
group::r-x
group:qa:r--
mask::rwx
other::---
The mask entry limits the effective permissions for named users/groups.
Advanced: Linux Capabilities
{:.gc-adv}
Advanced
Capabilities divide root’s omnipotence into distinct units that can be granted individually, reducing the attack surface of privileged programs.
Common Capabilities
| Capability | What it grants |
|---|---|
CAP_NET_BIND_SERVICE |
Bind ports < 1024 |
CAP_NET_ADMIN |
Configure network interfaces |
CAP_SYS_ADMIN |
Mount filesystems, many admin ops |
CAP_SYS_PTRACE |
Attach to processes with ptrace |
CAP_DAC_OVERRIDE |
Bypass file read/write/execute checks |
CAP_SETUID |
Change process UID |
CAP_KILL |
Send signals to any process |
# View capabilities on a file
getcap /usr/bin/ping
# Grant capability (instead of SUID root)
sudo setcap cap_net_bind_service+ep /usr/local/bin/myserver
# +ep = effective + permitted sets
# Remove capabilities
sudo setcap -r /usr/local/bin/myserver
# View current process capabilities
cat /proc/self/status | grep Cap
capsh --decode=0000000000000000 # decode hex capability mask
Real example: Give a Node.js app the ability to bind port 80 without running as root:
sudo setcap cap_net_bind_service+ep $(which node)
PAM — Pluggable Authentication Modules
PAM sits between applications and authentication backends, providing modular control over who can log in and how.
# PAM config lives in /etc/pam.d/
ls /etc/pam.d/
# sshd, login, sudo, common-auth, common-password, …
cat /etc/pam.d/common-auth
# auth [success=1 default=ignore] pam_unix.so nullok
# auth requisite pam_deny.so
# auth required pam_permit.so
Control flags: required (failure always fails), requisite (immediate failure), sufficient (success skips rest), optional.
Useful PAM modules:
| Module | Purpose |
|---|---|
pam_unix.so |
Traditional UNIX password auth |
pam_google_authenticator.so |
TOTP two-factor auth |
pam_limits.so |
Enforce resource limits (ulimit) |
pam_faillock.so |
Account lockout after N failed attempts |
pam_env.so |
Set environment variables on login |
User Namespaces
# Run a process in its own user namespace (appears as root inside, not outside)
unshare --user --map-root-user bash
# Check — inside the namespace you're UID 0
id
# uid=0(root) gid=0(root) groups=0(root),...
# From host, you're still your regular UID
User namespaces are the foundation of rootless containers (Podman, rootless Docker).
Interview Q&A
{:.gc-iq}
Interview Q&A
Q1 — Basic: What does chmod 644 mean?
Owner gets read+write (4+2=6), group gets read-only (4), others get read-only (4). Typical for config files and static web assets.
Q2 — Basic: What is the difference between adduser and useradd?
useraddis the low-level system binary — it does exactly what flags say and nothing more.adduseris a higher-level Perl/Python script (Debian/Ubuntu) that provides sensible defaults: creates home directory, copies/etc/skel, prompts for password and GECOS info. For scripts, useuseradd; for interactive admin, useadduser.
Q3 — Intermediate: Explain SUID on a directory. Does it have any effect?
SUID on a directory has no defined effect on most Linux filesystems (it is ignored). SGID on a directory is the useful one — it makes newly created files inherit the directory’s group instead of the creator’s primary group.
Q4 — Intermediate: What does the x permission mean on a directory vs a file?
On a file: permission to execute it as a program. On a directory: permission to enter it (traverse /
cdinto it) and access files within it if their names are known. Read (r) on a directory lets you list its contents; execute (x) lets you access contents by name. You need bothrandxto do a usefullsandcd.
Q5 — Intermediate: How would you allow www-data to read a file owned by eslam without changing ownership or using ACLs?
Add
www-datatoeslam’s group, then ensure the file has group-readable permissions (chmod g+r). Or usesetfacl -m u:www-data:r file.txtfor a more targeted ACL approach.
Q6 — Advanced: What is the difference between SUID and Linux capabilities, and which is preferred for new software?
SUID grants the entire UID of the file owner (usually root) for the duration of the process. Linux capabilities grant only specific privileges (e.g.,
CAP_NET_BIND_SERVICEfor binding low ports). Capabilities follow the principle of least privilege — if your daemon only needs to bind port 443, give itcap_net_bind_serviceinstead of making it SUID root, drastically reducing the blast radius of a vulnerability.
Q7 — Advanced: How do containers implement user isolation without a hypervisor?
Linux user namespaces map a range of host UIDs to a different range inside the namespace (commonly mapping host UID 100000-165535 to container UIDs 0-65535). Inside the container, the process appears to be root (UID 0), but the kernel sees it as UID 100000 on the host with no special privileges. Combined with mount, network, and PID namespaces, this provides strong isolation without a VM.
References
{:.gc-ref}
References
| Resource | Link |
|---|---|
man 5 passwd |
Format of /etc/passwd |
man 5 sudoers |
Sudoers file syntax reference |
man 1 setfacl / man 1 getfacl |
ACL management |
man 7 capabilities |
Full Linux capabilities reference |
man 8 pam |
PAM overview |
| Linux PAM documentation | linux-pam.org |
| Linux Capabilities in Practice | man7.org/linux/man-pages/man7/capabilities.7.html |