The 9 Bits That Run Everything
Every file and directory on Linux carries 9 permission bits arranged in three groups of three: user, group, other. Each group has read (r), write (w), and execute (x). Plus three special bits (setuid, setgid, sticky) you’ll meet less often. That’s it. Everything else is shorthand or syntactic sugar.
This article is a working reference for Linux file permissions and ownership: how to read them, how to set them with both numeric and symbolic syntax, what each bit actually does, and the gotchas that catch people in production.
Reading Permissions: ls -l
$ ls -l install.sh
-rwxr-xr-x 1 alice developers 2148 Mar 15 09:32 install.sh
The first character is the file type: - regular file, d directory, l symbolic link, c character device, b block device, s socket, p named pipe.
Then three groups of three:
rwx— user (owner) can read, write, executer-x— group can read, execute (NOT write)r-x— other can read, execute (NOT write)
Octal: The Numeric Shorthand
| Bit | Value | Meaning |
|---|---|---|
r |
4 | read |
w |
2 | write |
x |
1 | execute |
Sum the values for each group. Three groups give you three digits: the famous octal mode.
| Octal | rwx | Common use |
|---|---|---|
755 |
rwxr-xr-x |
Executable scripts, public dirs |
644 |
rw-r--r-- |
Regular files (config, docs) |
700 |
rwx------ |
Private executables (SSH keys, secrets) |
600 |
rw------- |
Private regular files |
777 |
rwxrwxrwx |
Almost never the right answer |
666 |
rw-rw-rw- |
Almost never the right answer |
If you find yourself typing chmod 777 or chmod 666 in production, stop and ask why. The right answer is almost always tighter.
chmod — Two Syntaxes
Numeric (octal)
chmod 755 install.sh # rwxr-xr-x
chmod 600 ~/.ssh/id_rsa # rw-------
chmod -R 644 docs/ # recursive (careful!)
chmod 4755 /usr/bin/passwd # leading 4 = setuid
Symbolic (more readable for incremental changes)
chmod u+x script.sh # add user-execute
chmod g-w sensitive.txt # remove group-write
chmod o= secret # strip other's permissions
chmod a+r public.txt # all (user, group, other) +r
chmod u+rwx,g+rx,o-rwx file # multiple at once
The symbolic form is the right choice when you want to add or remove ONE permission without touching the others. The numeric form is the right choice when you want to set everything explicitly.
chmod -R Carefully
Recursive chmod is the most common foot-gun in Linux ops. Two patterns:
# BAD: gives execute to every file, including data files
chmod -R 755 /var/www/html
# GOOD: separate handling for files and directories
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
Or use the symbolic X (capital) which adds execute only where it already makes sense (already-executable files, or directories):
chmod -R u+rwX,go+rX,go-w /var/www/html
Ownership: chown and chgrp
chown alice file.txt # change owner only
chown alice:developers file.txt # owner AND group
chown :developers file.txt # group only (alternative: chgrp)
chgrp developers file.txt # group only
chown -R alice:dev /var/www/html # recursive
chown --reference=existing.txt new.txt # match another file's ownership
Only root can change a file’s owner. A regular user can change the group, but only to a group they’re a member of.
umask — Default Permissions for New Files
The umask is a bitmask SUBTRACTED from 666 (or 777 for directories) to get the default mode of newly created files.
umask # show current
umask 022 # default for most distros
umask 077 # paranoid: only owner
| umask | New file | New directory |
|---|---|---|
022 |
644 (rw-r--r--) |
755 (rwxr-xr-x) |
027 |
640 (rw-r-----) |
750 (rwxr-x---) |
077 |
600 (rw-------) |
700 (rwx------) |
Set in ~/.bashrc or /etc/profile for persistence. Many production environments use 027 for tighter defaults.
The Three Special Bits
setuid (4xxx) — run as the file’s owner
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Apr 4 /usr/bin/passwd
That s in the user-execute slot means the program runs with the owner’s privileges (root, here) regardless of who invokes it. Required for passwd to write to /etc/shadow. Set with chmod u+s or octal leading 4: chmod 4755 file.
Setuid binaries are a security-sensitive surface. Audit yours: find / -type f -perm -4000 2>/dev/null
setgid (2xxx)
On a directory: new files inherit the directory’s group, not the creator’s primary group. Useful for shared project directories. chmod g+s dir/ or octal leading 2.
Sticky bit (1xxx)
On a directory: only the file’s owner can delete or rename it, even if other users have write permission on the directory. The classic example is /tmp:
$ ls -ld /tmp
drwxrwxrwt 17 root root 4096 May 6 16:22 /tmp
That t at the end is the sticky bit. Without it, anyone could delete anyone else’s files in /tmp. Set with chmod +t dir/ or octal leading 1.
ACLs — When 9 Bits Aren’t Enough
Need user bob specifically to read this file, even though he’s not in the group? POSIX ACLs:
setfacl -m u:bob:r-- file.txt # grant bob read
setfacl -m g:audit:rx /var/log/app/ # grant audit group rx
getfacl file.txt # display ACL
setfacl -x u:bob file.txt # remove bob's ACL entry
setfacl -b file.txt # remove ALL ACLs
Files with ACLs show a + at the end of ls -l: -rw-r--r--+.
Common Pitfalls
chmod -R 755on a code tree. Suddenly every.pyfile is executable. Usefind -type f+find -type dseparately, orXin symbolic mode.- SSH key permissions too loose. SSH refuses keys with group/other-readable perms.
chmod 600 ~/.ssh/id_rsa;chmod 700 ~/.ssh. - Web server can’t read uploaded files. Files written by the application user with umask 077 won’t be readable by the web user. Fix:
chmod 644or align umask, or use ACLs. - setuid script shebang. Setuid on shell scripts is ignored by Linux for security reasons. Setuid only works on compiled binaries.
chownnot enough. Ownership change without permission change can leave a file unreadable to its new owner if the existing perms blocked them.- Forgetting that read on a directory means “list”, write means “create/delete entries,” execute means “cd into.”
Conclusion
Five mental models that make permissions click:
- Three groups, three bits each. 9 bits.
- Octal:
r=4 w=2 x=1, sum per group, three digits total. - Symbolic:
u/g/o/a++/-/=+rwx. Use for incremental changes. - For directories:
r= list,w= create/delete,x= enter. - When 9 bits aren’t enough, use ACLs, not
chmod 777.
Related Linux Admin troubleshooting
For common errors and fixes related to this topic, see: