| | {{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 -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]] |
| | |