Linux: File Permissions — chmod / chown / umask Explained
Linux is a multi-user operating system. File permissions are the foundation of its security model — controlling who can read, write, and execute each file and directory.
📋 Prerequisites: You should first complete
- Lesson 4: Filesystem Navigation
- Lesson 5: File and Directory Operations
1. What You Will Learn
- rwx permission model explained
- chmod numeric notation (755/644/700)
- chmod symbolic notation (u/g/o/a +-=)
- chown for changing owner and group
- umask default permissions
- Special permissions: SUID / SGID / Sticky Bit
2. A "Permission denied" Story
(1) The Pain: A Script That Won't Run
Alex wrote a deploy.sh script, but when he tried to run it:
./deploy.sh
# bash: ./deploy.sh: Permission denied
He checked the file permissions:
ls -l deploy.sh
# -rw-r--r-- 1 charlie charlie 50 Jul 7 10:23 deploy.sh
(2) Adding Execute Permission
Bob said: "Your script has read and write permissions, but no execute permission. Just add +x."
chmod +x deploy.sh
ls -l deploy.sh
# -rwxr-xr-x 1 charlie charlie 50 Jul 7 10:23 deploy.sh
./deploy.sh # It works now!
(3) The Benefit: Understanding the Linux Permission System
Alex now understood what chmod +x means. More importantly, he began to understand why Linux is secure — every file and every user has clear permission boundaries.
3. Knowledge Points
(1) The rwx Permission Model
The first column of ls -l output is the permission information. For example -rwxr-xr-x:
- rwx r-x r-x
│ └┬─┘ └┬─┘ └┬─┘
│ │ │ └── Others (other) permissions
│ │ └─────── Group (group) permissions
│ └──────────── File owner (user) permissions
└──────────────── File type (- regular file / d directory / l link)
Meaning of the three permission bits:
| Permission | Character | Numeric | For files | For directories |
|---|---|---|---|---|
| Read | r | 4 | View file contents | List directory contents (ls) |
| Write | w | 2 | Modify file contents | Create/delete files in the directory |
| Execute | x | 1 | Run the file (script/program) | Enter the directory (cd into it) |
(2) chmod Numeric Notation
Three digits correspond to User / Group / Other permissions:
| Number | Binary | Permissions |
|---|---|---|
| 7 | 111 | rwx (read+write+execute) |
| 6 | 110 | rw- (read+write) |
| 5 | 101 | r-x (read+execute) |
| 4 | 100 | r-- (read-only) |
| 3 | 011 | -wx (write+execute) |
| 2 | 010 | -w- (write-only) |
| 1 | 001 | --x (execute-only) |
| 0 | 000 | --- (no permissions) |
Common permission combinations:
chmod 755 script.sh # rwxr-xr-x Owner can read/write/execute, others can read/execute
chmod 644 file.txt # rw-r--r-- Owner can read/write, others can read only
> 💡 Tip: Remember the two most common permission combinations — 755 is the standard permission for scripts (owner can execute, others can read/execute), and 644 is the standard for regular files (owner can read/write, others can read only). The only difference between 755 and 644 is the "execute" bit.
chmod 700 private.sh # rwx------ Only the owner can operate
chmod 600 secret.txt # rw------- Only the owner can read/write
chmod 777 public/ # rwxrwxrwx Everyone can operate (⚠️ insecure)
chmod 777 lets all users read, write, and execute the file, which is extremely dangerous on a server — if any account is compromised, the attacker can modify that file. Never use 777 in production; use group permissions (e.g., 775) or ACLs for shared access.
(3) chmod Symbolic Notation
# Syntax: chmod [who][operation][permission] file
# Who: u (owner) / g (group) / o (others) / a (all)
# Operation: + (add) / - (remove) / = (set exactly)
chmod u+x script.sh # Add execute permission for owner
chmod g-w file.txt # Remove write permission for group
chmod o-r private.txt # Remove read permission for others
chmod a+x script.sh # Add execute permission for everyone
chmod u=rwx,g=rx,o=r # Equivalent to 754
(4) chown — Change Owner and Group
# Change file owner
sudo chown alice file.txt
# Change file group
sudo chown :developers file.txt
# Change both owner and group
sudo chown alice:developers file.txt
# Recursively change directory and its contents
sudo chown -R alice:developers /srv/project/
(5) umask — Default Permission Mask
When you create a new file or directory, Linux subtracts the umask value to determine default permissions.
# View current umask
umask
# Output: 0022
# Default permission calculation:
# File maximum: 666 (rw-rw-rw-)
# Directory maximum: 777 (rwxrwxrwx)
# Subtract umask 022:
# File default: 666 - 022 = 644 (rw-r--r--)
# Directory default: 777 - 022 = 755 (rwxr-xr-x)
# Change umask
umask 007 # Stricter default permissions
umask 000 # All users can write (insecure)
(6) Special Permissions
| Special permission | Numeric | Effect on files | Effect on directories |
|---|---|---|---|
| SUID | 4xxx | Runs as the file owner | (none) |
| SGID | 2xxx | Runs as the file group | New files inherit the directory's group |
| Sticky Bit | 1xxx | (none) | Only file owner can delete |
/usr/bin/passwd), and regularly audit SUID files on the system: find / -perm -4000 -type f 2>/dev/null
# Set SUID (4)
chmod u+s /usr/bin/passwd # passwd runs as root
chmod 4755 /usr/bin/program # Numeric notation for SUID
# Set SGID (2)
chmod g+s /srv/shared # Files created in this directory inherit the group
chmod 2775 /srv/shared # Numeric notation for SGID
# Set Sticky Bit (1)
chmod +t /tmp # Only file owner can delete
chmod 1777 /tmp # Standard permissions for /tmp
(7) ▶ Example: View File Permissions
# View permissions in long format
ls -l /etc/passwd
# -rw-r--r-- 1 root root 2845 Jul 7 10:23 /etc/passwd
# View directory permissions
ls -ld /tmp
# drwxrwxrwt 1 root root 4096 Jul 7 10:23 /tmp
# The trailing t indicates Sticky Bit
# Recursively view directory permissions
ls -laR /srv/project | head -20
Output:
TEXT/srv/project: total 16 drwxr-xr-x 3 alice developers 4096 Jul 7 10:23 . drwxr-xr-x 4 root root 4096 Jul 7 09:00 .. -rw-r--r-- 1 alice developers 256 Jul 7 10:23 config.yaml -rwxr-xr-x 1 alice developers 512 Jul 7 10:23 deploy.sh drwxr-xr-x 2 alice developers 4096 Jul 7 10:23 src
(8) ▶ Example: chmod Numeric Notation
# 755 — standard script permissions
chmod 755 deploy.sh
ls -l deploy.sh
# -rwxr-xr-x
# 644 — standard file permissions
chmod 644 index.html
ls -l index.html
# -rw-r--r--
# 600 — private file
chmod 600 private.key
ls -l private.key
# -rw-------
Output:
TEXT-rwxr-xr-x 1 alice developers 512 Jul 7 10:23 deploy.sh -rw-r--r-- 1 alice developers 256 Jul 7 10:23 index.html -rw------- 1 alice developers 128 Jul 7 10:23 private.key
(9) ▶ Example: chmod Symbolic Notation
# Add execute permission
chmod +x script.sh # Add +x for everyone (equivalent to a+x)
# Add execute permission for owner only
chmod u+x script.sh
# Remove write permission for group and others
chmod go-w config.txt
# Set standard permissions for a shell script
chmod u=rwx,g=rx,o=r script.sh
# Equivalent to chmod 755 script.sh
Output:
TEXT-rwxr-xr-- 1 alice developers 512 Jul 7 10:23 script.sh
(10) ▶ Example: chown to Change Owner
# Change file owner
sudo chown www-data index.html
# Change group
sudo chown :www-data /srv/www/
# Change both
sudo chown alice:developers project/
# Recursively change entire directory tree
sudo chown -R alice:alice ~alice/
Output:
TEXT-rw-r--r-- 1 www-data www-data 256 Jul 7 10:23 index.html drwxr-xr-x 2 www-data www-data 4096 Jul 7 10:23 /srv/www/ drwxr-xr-x 3 alice developers 4096 Jul 7 10:23 project/
(11) ▶ Example: umask in Practice
# View current umask
umask
# Output: 0022
# Create a new file to test
touch test.txt
ls -l test.txt
# -rw-r--r-- ← 644 (666 - 022)
mkdir testdir
ls -ld testdir
# drwxr-xr-x ← 755 (777 - 022)
# Create after changing umask
umask 0077
touch secret.txt
ls -l secret.txt
# -rw------- ← 600 (666 - 077)
Output:
TEXT0022 -rw-r--r-- 1 alice alice 0 Jul 7 10:23 test.txt drwxr-xr-x 2 alice alice 4096 Jul 7 10:23 testdir -rw------- 1 alice alice 0 Jul 7 10:23 secret.txt
(12) ▶ Comprehensive Example: Correct Permission Settings for a Web Application
# Assume /var/www/myapp is the web application directory
# 1. Set owner and group
sudo chown -R www-data:www-data /var/www/myapp
# 2. Directory permissions: 755 (owner read/write/execute, others read/execute)
find /var/www/myapp -type d -exec chmod 755 {} \;
# 3. File permissions: 644 (owner read/write, others read only)
find /var/www/myapp -type f -exec chmod 644 {} \;
# 4. Executable scripts: 755
chmod 755 /var/www/myapp/deploy.sh
# 5. Sensitive files: 600
chmod 600 /var/www/myapp/.env
# 6. Upload directory: writable directory
chmod 775 /var/www/myapp/uploads
❓ FAQ
Q: Why is
chmod 777insecure? A:chmod 777lets all users read, write, and execute the file. If any account is compromised, the attacker can modify or delete the file, creating a privilege escalation risk. In production, use group permissions (e.g., 775) or ACLs for shared access instead of 777.
Q: Why are newly created files 644 by default, not 755? A: Because of the security principle — new files don't get execute permission by default. Linux assumes most files don't need execute permission; if you need it, add it explicitly with
chmod +x.
Q: Why can't I write to
/etcafter SSH login? A:/etcbelongs to root, and regular users only have read permission (r-x). To modify files under/etc, you must usesudofor elevated privileges. This is a security design that protects the system.
Q: What are the risks of SUID programs? A: SUID programs run with the file owner's (usually root) permissions. If an SUID program has a vulnerability, a regular user could escalate to root. Therefore, SUID should only be set on necessary programs (like
passwd,ping), and should be audited regularly.
Q: Is
chmod -R 755safe for recursive directory changes? A: It depends. If the directory contains script files, 755 is reasonable. But usingfindto set different permissions for files (644) and directories (755) is safer and more precise.
📖 Summary
ls -lfirst column:-rwxr-xr-x= file type + owner/group/others × rwx- chmod numeric:
755for scripts,644for files,600for private files - chmod symbolic:
u+xadds execute for owner,go-wremoves write for group and others - chown changes owner (
alice:developers), use-Rfor recursive - umask controls default permissions; common values: 022 (644/755), 077 (600/700)
- Special permissions: SUID (4) inherits owner, SGID (2) inherits group, Sticky Bit (1) prevents deletion
📝 Exercises
- Basic (Difficulty ⭐): Create a script, add execute permission with
chmod +x, and run it; then use numeric notation to set a file to 644 and a directory to 755 - Intermediate (Difficulty ⭐⭐): Use symbolic notation to remove all group and others permissions from a file, then create a test user (
sudo useradd testuser) and usechownto transfer file ownership to that user - Advanced (Difficulty ⭐⭐⭐): Create a shared directory, set SGID (
chmod g+s) so new files inherit the group, and usefind+chmodto batch-set a web project's files to 644 and directories to 755