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

1. What You Will Learn


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:

BASH
./deploy.sh
# bash: ./deploy.sh: Permission denied

He checked the file permissions:

TEXT
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."

BASH
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:

TEXT

-  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:

BASH
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)
⚠️ Note: 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

BASH
# 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

BASH
# 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.

TEXT
# 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)
💡 Tip: umask calculation isn't simple subtraction — it's a permission "mask." The maximum file permissions are 666 (no execute by default), and maximum directory permissions are 777. A umask of 022 removes write permission for "group" and "others," resulting in file 644 and directory 755, which is the safest default.

(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
⚠️ Note: SUID/SGID programs run with the file owner's or group's permissions. If such a program has a vulnerability, an attacker can escalate privileges to root. Only set SUID on necessary programs (like /usr/bin/passwd), and regularly audit SUID files on the system: find / -perm -4000 -type f 2>/dev/null

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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

BASH
# 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:

TEXT
0022
-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

BASH
# 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 777 insecure? A: chmod 777 lets 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 /etc after SSH login? A: /etc belongs to root, and regular users only have read permission (r-x). To modify files under /etc, you must use sudo for 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 755 safe for recursive directory changes? A: It depends. If the directory contains script files, 755 is reasonable. But using find to set different permissions for files (644) and directories (755) is safer and more precise.


📖 Summary


📝 Exercises

  1. 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
  2. Intermediate (Difficulty ⭐⭐): Use symbolic notation to remove all group and others permissions from a file, then create a test user (sudo useradd testuser) and use chown to transfer file ownership to that user
  3. Advanced (Difficulty ⭐⭐⭐): Create a shared directory, set SGID (chmod g+s) so new files inherit the group, and use find + chmod to batch-set a web project's files to 644 and directories to 755
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏