Linux

File Permissions and chmod on Linux

·2 min read

Every file on a Linux system carries a permission triple — owner, group, and others — and a set of three bits for each: read, write, execute. chmod changes those bits. After fifty years of Unix, this is still the foundation of every access control decision the kernel makes, and it still trips people up.

Reading the output of ls -l

Run ls -l and you'll see something like -rwxr-xr-- 1 alice devs 4096 May 5 10:30 deploy.sh. The first character is the file type (- regular, d directory, l symlink, c/b device). The next nine are three permission triples: owner (rwx), group (r-x), others (r--). Owner and group columns identify whose triple applies to whom.

Octal vs symbolic modes

Each triple is a 3-bit number: r=4, w=2, x=1. The classic 755 means owner can read+write+execute (7), group and others can read+execute (5). Symbolic notation is more surgical:

# Octal — replaces the whole mode
chmod 644 secrets.env
chmod 750 deploy.sh

# Symbolic — adds/removes specific bits
chmod u+x deploy.sh        # add execute for user
chmod g-w sensitive.conf   # remove write for group
chmod o= private.key       # zero out others
chmod a+r README.md        # all (ugo) +r

umask: the inverse mode

When a process creates a new file, the kernel applies mode & ~umask. A umask of 022 means newly-created files get 666 & ~022 = 644, directories get 777 & ~022 = 755. Set it in your shell rc to control defaults across your session:

umask 027    # files 640, dirs 750 — typical "private user" default
umask 077    # files 600, dirs 700 — paranoid; nobody else sees anything

Special bits: setuid, setgid, sticky

Three rarely-discussed bits unlock specific behaviours. setuid on an executable runs the binary with the owner's privileges — that's how /usr/bin/passwd can edit /etc/shadow. setgid on a directory makes new files inherit the directory's group, useful for shared project folders. Sticky on a directory means only the file's owner can delete or rename their own files — that's why /tmp works.

chmod u+s /usr/local/bin/my-suid-tool   # setuid (shows as 'rws')
chmod g+s /srv/shared-project           # setgid on dir
chmod +t /var/tmp                       # sticky (shows as 'rwt' on others)
Setuid is sharp.

A setuid root binary that calls anything user-controlled is a privilege escalation waiting to happen. Audit them with find / -perm -4000 -type f 2>/dev/null.

When chmod isn't enough: ACLs

The classic owner/group/other model can't express "Alice and Bob can write, Charlie and the auditors group can read." POSIX ACLs extend the model with per-user and per-group entries:

setfacl -m u:bob:rw report.pdf
setfacl -m g:auditors:r report.pdf
getfacl report.pdf

A trailing + in ls -l output means the file has an extended ACL.

Common mistakes

Setting a directory to 644 makes it unreadable for traversal — directories need x for anyone who wants to enter them. Running chmod -R 644 /home will lock you out of your own subdirectories. Use chmod -R u+rwX,go+rX instead — capital X sets execute only on directories and already-executable files.

Related