Skip to content
ALB Wiki

Diff — Users and Permissions

Comparing rev 4 → rev 5

{{infobox
| title = Users & Permissions
| chapter = Linux Handbook, chapter 12 — uid/gid, mode bits, su/sudo, the security layer
| core | Everything is owned; every file carries the 9-bit contract
| skills | chmod · chown · umask · su/sudo · groups · the special bits
| files = /etc/passwd · /etc/group · /etc/shadow · /etc/sudoers
| next | Processes — what the users run
}}
**Linux's security model is three questions applied to every file**: who owns it, what group, and what do the three classes — owner, group, other — get to do? `rwxr-xr--` is a contract printed in nine bits. This chapter reads the contract fluently, then goes deeper: the special bits, umask, the password machinery, and `sudo`'s precise delegation of root.
## Reading the contract
```sh
ls -l file
# -rwxr-xr-- 1 alice devs 4096 Jan 5 file
# ^ the leading char = type: - file, d dir, l symlink, c/b devices
#  rwx r-x r--  = owner rwx · group r-x · other r--
```
**r=4, w=2, x=1** — modes as octal: `755` = rwxr-xr-x, `644` = rw-r--r--, `600` = rw-------. On directories `x` means *enterable* — a dir with `rw` but no `x` is unreadable-inside despite looking writable.
```sh
chmod 755 script.sh          # octal
chmod u+x script.sh          # symbolic — add exec to owner
chmod go-w file              # remove write from group+other
chmod -R 644 dir/            # recursive — usually a mistake on dirs+files mixed
chown alice file             # change owner
chown alice:devs file        # owner + group
chgrp devs file              # group only
```
## The special bits — beyond rwx
Three extra bits change behavior fundamentally:
```sh
chmod 4755 program     # SETUID — runs as the FILE's owner (passwd does this)
chmod 2755 dir         # SETGID — runs as group / new files inherit group
chmod 1777 /tmp        # STICKY — only owner can delete (why /tmp is shared-safe)
ls -l passwd           # -rwsr-xr-x — the 's' marks setuid
```
**setuid** is how `passwd` lets you change your password in a file you don't own — it runs *as root*. It's also a security hazard — a setuid binary with a bug is privilege escalation waiting. `find / -perm -4000` audits them.
## umask — the default permissions
New files get `666 & ~umask`, dirs `777 & ~umask`:
```sh
umask                  # usually 022 → files 644, dirs 755
umask 077              # strict — 600/700, only for you
umask 022              # the sane shared default
```
Set it in `~/.profile` — it's why your files arrive `644` not `777`.
## The account machinery
```sh
id alice               # uid, gid, all groups
whoami                 # effective user
groups                 # my groups
useradd -m -s /bin/bash alice   # create — -m home, -s shell
passwd alice           # set her password
usermod -aG wheel alice         # add to group — ALWAYS -a or you REPLACE the list
userdel -r alice       # remove + home
groupadd devs          # new group
gpasswd -d alice devs  # remove from group
```
`/etc/passwd` — the readable roster: `name:x:uid:gid:gecos:home:shell`. `/etc/shadow` — the hashes, root-only: `name:$6$hash:...` with aging fields. `/etc/group` — `group:x:gid:members`. The `x` in passwd is the shadow split — passwords moved out of the world-readable file long ago.
## su vs sudo — two kinds of becoming
```sh
su -                   # become root — LOGIN shell, root's env
su - alice             # become alice fully
sudo command           # run ONE command as root — logged, delegated
sudo -i                # root login via sudo
sudo -u alice cmd      # as any user
sudo !!                # rerun last command as root — the muscle memory
```
`sudo` is configured in `/etc/sudoers` — edit **only** with `visudo` (it syntax-checks before saving; a broken sudoers locks everyone out). The delegation grammar: `alice ALL=(ALL) ALL`, or `%wheel ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx` — precise commands, precise users, optionally passwordless. `su` shares the root password; `sudo` shares *nothing* — it logs who ran what.
## File ownership inside /proc and friends
A process carries real uid, effective uid, filesystem uid — `ls -l /proc/PID/` shows the process's view. Files created follow the *effective* uid and the process's umask — which is why a daemon's files land with its service user's name on them.
## The mode bits — the complete grammar
```sh
# symbolic — who, op, what
chmod u+x file        # user +execute
chmod g-w file        # group -write
chmod o=r file        # other =read-only
chmod a+r file        # all +read
chmod u+s program     # setuid
chmod g+s dir         # setgid
chmod +t dir          # sticky
chmod u=rwx,g=rx,o= file   # combined
# octal — the number language
chmod 644 file        # rw- r-- r--  = 6 4 4
chmod 755 file        # rwx r-x r-x
chmod 700 dir         # rwx --- ---   (private)
chmod 600 key         # rw- --- ---   (keys/secrets)
chmod 640 conf        # rw- r-- ---
chmod 664 shared      # rw- rw- r--
chmod 2775 sharedir   # setgid + 775 — the shared-dir formula
chmod 4755 program    # setuid — runs as owner
chmod 1777 /tmp       # sticky + world — /tmp's magic
chmod 751 dir         # rwx r-x --x   — group-traversable, world-blocked
```
Reading the bits: `r=4 w=2 x=1` per triad. `find / -perm -4000` finds setuid; `find / -perm -0002` world-writable. `chmod --reference=other file` clones another's mode.
## /etc/passwd + shadow + group — the schema
```sh
# /etc/passwd — world-readable roster:
#   name : x : uid : gid : gecos : home : shell
#   alice:x:1000:1000:Alice:/home/alice:/bin/bash
# /etc/shadow — root-only hashes:
#   name : $6$salt$hash : lastchange : min : max : warn : inactive : expire
#   alice:$6$salt$...:19500:0:99999:7:::
# /etc/group — groups:
#   name : x : gid : members
#   devs:x:1001:alice,bob
# $6$ = SHA-512 · $y$ = yescrypt · $1$ = MD5 (dead) · $2b$ = bcrypt
```
`vipw`/`vigr` edit passwd/group safely (locking); `pwck`/`grpck` sanity-check them. `getent passwd alice`, `getent group devs`, `getent shadow alice` read through NSS (covers LDAP/AD sources too).
## The user/group administration surface
```sh
useradd -m -s /bin/bash -G wheel,devs alice    # -m home -s shell -G groups
useradd -r -s /sbin/nologin svcacct            # system account — no login
usermod -aG devs alice                          # append to groups — ALWAYS -a
-
usermod -L alice / -U alice                     # lock/unlock
+
usermod -L alice                                # lock the password
+
usermod -U alice                                # unlock it
usermod -s /sbin/nologin alice                  # kill login without deleting
usermod -d /newhome -m alice                    # move home
userdel -r alice                                # remove + home + spool
passwd alice                                    # set password
passwd -l alice                                 # lock the password
chage -l alice                                  # the aging policy
chage -M 90 alice                               # 90-day max
groupadd devs; gpasswd -a alice devs; gpasswd -d alice devs
newgrp devs                                     # switch primary group live
```
The classic traps: `-G` without `-a` *replaces* all groups; `-r` system accounts get low UIDs; `/sbin/nologin` is a shell that refuses — for service accounts.
## su vs sudo — the deep difference
```sh
su -             # full root login — env, cd ~, everything
su - alice       # become alice — her env, her shell
su alice         # partial — keeps YOUR env, her identity
su -c 'cmd' alice # one command as alice
sudo cmd          # one command as root — your password, logged
sudo -i           # root login via sudo
sudo -s           # root shell, your env
sudo -u alice cmd # as any user
sudo -l           # YOUR allowed commands
sudo -v           # validate/refresh the timestamp
sudo -k           # kill the timestamp — force re-auth
sudo !!           # the classic muscle memory
sudoedit file     # edit-as-root without a root-owned file
visudo            # THE only way to edit /etc/sudoers
```
`sudo -l` shows your delegated rights; `visudo` syntax-checks before saving (a broken sudoers file locks everyone out). The delegation grammar — `alice ALL=(root) /usr/bin/systemctl restart nginx` — user, hosts, target-identity, commands. `%wheel` prefixes groups.
## PAM — the auth layer
```sh
ls /etc/pam.d/              # per-service policies — login, sshd, sudo...
cat /etc/pam.d/sshd         # what sshd auth requires
# auth|account|password|session  required|requisite|sufficient|optional  module
```
PAM (Pluggable Authentication Modules) sits under every login — `pam_unix` (passwords), `pam_nologin`, `pam_securetty`, `pam_faildelay`, `pam_faillock` (lockout), `pam_umask`, `pam_env`. The `auth/account/password/session` stack order is the policy.
## Groups — the shared-access mechanism
A file's *group* is the primitive for shared access: `chgrp devs repo/; chmod g+w repo/` — every `devs` member can write. Setgid on a directory makes new files inherit the directory's group — the shared-workspace idiom: `chmod 2775 repo/` keeps `devs` ownership propagating downward.
## ACLs — when 9 bits aren't enough
```sh
setfacl -m u:alice:rw file       # alice specifically gets rw
getfacl file                   # the access-control list
setfacl -m d:u:devs:rwx dir    # default ACL — new files inherit
ls -l file                     # the '+' after the mode = ACLs present
```
When a file needs *different* permissions for several specific users — beyond owner/group/other — ACLs carry it. Most systems never need them; the day you do, they're indispensable.
## Capabilities — root's powers, unbundled
Traditional root is all-or-nothing; **capabilities** split it:
```sh
setcap 'cap_net_bind_service=+ep' server   # bind :80 without root
getcap server
```
`cap_net_bind_service`, `cap_setuid`, `cap_sys_admin` — the modern way to grant a process one privilege instead of all.
## Where permissions go wrong
| Symptom | Cause |
| --- | --- |
| "Permission denied" on a file you own | Directory missing `x` — can't traverse |
| `chmod -R 755` broke ssh keys | `~/.ssh` must be 700, keys 600 |
| sudo asks for password constantly | `NOPASSWD:` absent, or wrong sudoers line |
| usermod wiped group membership | Forgot `-a` — `-G` REPLACES |
| New files wrong group | Missing setgid on the shared dir |
| `find / -perm -4000` surprises | Setuid binaries you didn't expect — audit |
| Script "can't execute" despite 755 | Filesystem mounted `noexec` — `/tmp` often is |
## Exercises
1. `stat` a file — read all three timestamps and the mode.
2. `umask 077; touch f` then `umask 022; touch g` — compare.
3. `find /usr/bin -perm -4000` — inventory the setuid binaries; identify three.
4. Create a shared dir with setgid; prove new files inherit the group.
5. `visudo`-safe edit: grant your user `NOPASSWD` for one specific command.
6. Explain why `passwd` needs setuid — and why it must be bug-free.
## See also
- [[Linux]] · [[Filesystem]] · [[Processes]] · [[Shell]]
[[Category:Linux]]
[[Category:Handbook]]
[[Category:Security]]