How Linux Permissions Work
Every file and directory in Linux has three sets of permissions for three types of users:
-rwxr-xr-- 1 alice developers 4096 May 26 script.sh
^^^ ^^^ ^^^
| | └── Others (everyone else)
| └── Group (members of "developers")
└── Owner (alice)
Each set has three bits: read (r), write (w), execute (x).
| Symbol | Files | Directories |
|---|---|---|
| r (read) | Read file contents | List directory contents (ls) |
| w (write) | Modify file | Create/delete files inside directory |
| x (execute) | Run as program | Enter directory (cd) and access contents |
The first character indicates type: - = regular file, d = directory, l = symbolic link.
Numeric (Octal) Notation
Each permission set maps to a 3-bit number:
| Binary | Octal | Permissions |
|---|---|---|
| 000 | 0 | --- (none) |
| 001 | 1 | --x |
| 010 | 2 | -w- |
| 011 | 3 | -wx |
| 100 | 4 | r-- |
| 101 | 5 | r-x |
| 110 | 6 | rw- |
| 111 | 7 | rwx |
chmod 755 script.sh means:
- Owner: 7 = rwx (read, write, execute)
- Group: 5 = r-x (read, execute)
- Others: 5 = r-x (read, execute)
Common Permission Patterns
chmod 644 file.txt # -rw-r--r-- Regular files: owner edits, others read
chmod 755 script.sh # -rwxr-xr-x Scripts: owner runs, others can execute
chmod 700 private.key # -rwx------ Sensitive files: owner only
chmod 664 shared.txt # -rw-rw-r-- Collaborative files: group can edit
chmod 775 shared-dir/ # drwxrwxr-x Shared directory: group can add/delete
chmod 750 config/ # drwxr-x--- App config: group reads, others nothing
Web Server Patterns
# Static web files — readable by web server (www-data)
find /var/www/html -type f -exec chmod 644 {} \; # files: owner writes, server reads
find /var/www/html -type d -exec chmod 755 {} \; # dirs: can traverse
# Upload directory — web server can write
chmod 755 /var/www/html/uploads
chown www-data:www-data /var/www/html/uploads
# Configuration files — not readable by web server
chmod 600 .env
chmod 600 config/database.php
Symbolic Notation
chmod u+x script.sh # add execute for owner (u = user/owner)
chmod g-w shared.txt # remove write from group (g = group)
chmod o-rwx private/ # remove all from others (o = others)
chmod a+r public.txt # add read for all (a = all)
chmod u+x,g-w file # multiple changes at once
chmod go=r file # set group and others to exactly read-only
Changing Ownership: chown and chgrp
chown alice file.txt # change owner to alice
chown alice:developers file.txt # change owner and group
chown :developers file.txt # change group only
chown -R alice:alice /home/alice/ # recursive (-R)
chgrp www-data /var/www/ # change group to www-data
Special Permission Bits
Setuid (4000)
When set on an executable, it runs as the file owner rather than the user who executes it. Used by passwd, sudo, and similar system utilities.
chmod 4755 /usr/bin/example # -rwsr-xr-x ('s' in owner execute position)
ls -la /usr/bin/passwd # -rwsr-xr-x 1 root root ...
Setgid (2000)
On executables: runs as the file's group. On directories: new files inherit the directory's group rather than the creator's primary group.
chmod 2755 /shared-dir/ # drwxr-sr-x (group inheritance on new files)
Useful for shared project directories where all files should belong to the project group.
Sticky Bit (1000)
On directories: users can only delete files they own, even if they have write access to the directory. Used on /tmp.
chmod 1777 /tmp # drwxrwxrwt ('t' in others execute position)
ls -la / # /tmp has 'drwxrwxrwt'
Full Special Bits Example
chmod 6755 file # setuid + setgid + 755
chmod 7777 file # setuid + setgid + sticky + 777 (rarely appropriate)
The umask: Default Permission Mask
New files and directories don't get full permissions — umask subtracts permissions from the default.
umask # show current umask (typically 022 or 002)
umask 022 # set umask
# Default permissions before umask:
# Files: 666 (rw-rw-rw-)
# Directories: 777 (rwxrwxrwx)
# With umask 022:
# Files: 666 - 022 = 644 (rw-r--r--)
# Directories: 777 - 022 = 755 (rwxr-xr-x)
# With umask 002 (common for group collaboration):
# Files: 666 - 002 = 664 (rw-rw-r--)
# Directories: 777 - 002 = 775 (rwxrwxr-x)
Finding Files by Permission
# Files writable by others (potential security risk)
find /var/www -type f -perm -o+w
# Executable files owned by root with setuid
find / -type f -perm -4000 2>/dev/null
# Files with no owner
find / -nouser 2>/dev/null
# Directories writable by world
find / -type d -perm -o+w 2>/dev/null
ACL: Fine-Grained Access Control
For more complex scenarios than owner/group/others, use POSIX ACLs:
# Grant specific user read access
setfacl -m u:bob:r-- file.txt
# Grant specific group write access
setfacl -m g:contractors:rw- project/
# View ACL
getfacl file.txt
# Remove all ACL entries
setfacl -b file.txt
Security Checklist
# ✅ Sensitive files
chmod 600 ~/.ssh/id_rsa # private key
chmod 644 ~/.ssh/id_rsa.pub # public key
chmod 700 ~/.ssh/ # SSH directory
# ✅ Web application
chmod 644 /var/www/html/*.php # PHP files: not executable by web server
chmod 755 /var/www/html/ # web root: traversable
chmod 600 /var/www/.env # environment variables
# ❌ Never do this in production
chmod 777 /var/www/html/ # world-writable web root
chmod 777 uploads/ # world-writable upload directory
→ Calculate chmod permission values instantly with the chmod Calculator.