File permissions are "basic" in Linux, but they are also one of the
most common causes of production incidents: a service won't start, a
deploy script can't execute, a web app returns 403, or a shared
directory becomes a security hole because permissions were made too
broad. To use permissions correctly, you need more than memorizing
chmod 755— you need to understand how permission
bits have completely different semantics on files vs
directories (r/w/x mean different things for directories), the
boundaries between owner/group/others, and why mechanisms like
umask, SUID/SGID, and the sticky bit exist and when they
should be used. This post starts from the minimal concept set,
systematically explains rwx semantics, numeric/symbolic notation,
typical usage and troubleshooting approaches for chmod/chown, uses
common scenarios (shared directories, executable scripts, temp
directories, security hardening) to explain "how to grant permissions
and to what extent," then adds extended mechanisms like ACL and
chattr plus a practical troubleshooting checklist, enabling
you to locate and correctly fix permission issues in one shot.
Linux Permission Model: The Three-Tier Architecture of owner/group/others
Basic Concepts
Linux is a multi-user system; every file/directory has three identity attributes:
- Owner (u): The user (UID) who created or was designated as the file/directory owner
- Group (g): Multiple users can belong to one group, sharing permissions within the group (GID)
- Others (o): Everyone who is neither the file owner nor in the file's group
Why this design?
- Owner: The file's "owner," usually has highest permissions (like read/write/execute)
- Group: Suitable for team collaboration (like dev team, ops team), members share permissions
- Others: Prevents files from being accessed by arbitrary users (security isolation)
Three Permission Bits (rwx)
Each identity (u/g/o) has three permission bits:
- r (read): Read permission
- w (write): Write permission
- x (execute): Execute permission
Example: rwxr-xr-x
- Owner:
rwx(can read, write, execute) - Group:
r-x(can read, execute, cannot write) - Others:
r-x(can read, execute, cannot write)
Convert to numeric:
rwx= 4+2+1 = 7r-x= 4+0+1 = 5r-x= 4+0+1 = 5- So
rwxr-xr-x=755
rwx Semantic Differences on Files vs Directories (The Most Common Pitfall)
This is the most confusing point: rwx mean completely different things on files vs directories.
On Files (Regular Files)
| Permission | Meaning | Example |
|---|---|---|
r |
Can read file contents | cat file.txt |
w |
Can modify file contents | echo "new" > file.txt |
x |
Can execute file (scripts need shebang like
#!/bin/bash) |
./script.sh |
On Directories
| Permission | Meaning | Example |
|---|---|---|
r |
Can list directory contents (see filenames) | ls dir |
w |
Can create, delete, rename files within directory (usually
requires x) |
touch dir/newfile |
x |
Can enter directory (cd), access files within if you
know the name |
cd dir or cat dir/file.txt |
Real-world examples:
Case 1: Directory has
r but not x
1 | chmod 644 mydir # mydir permissions become rw-r--r-- (no x) |
Reason: Without x, can't enter
directory or access files within.
Case 2: Directory has
x but not r
1 | chmod 311 mydir # mydir permissions become -wx--x--x (has x but not r) |
Reason: With x you can enter and access
files, but without r you can't list directory contents.
Case 3: Directory has
w but not x
1 | chmod 622 mydir # mydir permissions become rw--w--w- (has w but not x) |
Reason: Although it has w, without
x you can't enter directory, so can't operate within.
Conclusion: For directories, x
is the most fundamental permission (without x you
can't do anything); w usually needs to be used with
x.
chmod: Modifying Permissions (Numeric and Symbolic Notation)
Numeric Notation (Fast and Common)
Each permission bit corresponds to a number:
r = 4w = 2x = 1
Sum to get a 3-digit number (owner/group/others):
7 = rwx(4+2+1)6 = rw-(4+2)5 = r-x(4+1)4 = r--(4)0 = ---(no permissions)
Common examples: 1
2
3
4chmod 755 script.sh # owner=rwx, group=r-x, others=r-x (executable script)
chmod 644 file.txt # owner=rw-, group=r--, others=r-- (regular file)
chmod 600 secret.key # owner=rw-, group=---, others=--- (private key file)
chmod 777 shared # owner=rwx, group=rwx, others=rwx (fully open, not recommended)
Symbolic Notation (Safer, Suitable for Incremental Changes)
1 | chmod u+x script.sh # Add execute permission for owner |
Recursive modification: 1
2chmod -R 755 dir # Recursively modify directory and its contents
chmod -R u+rwX,g+rX,o-rwx dir # Capital X only adds x to directories and files that already have execute (avoids making all files executable)
When to use numeric vs symbolic?
- Numeric: Suitable for "one-shot set to target
value" (like
chmod 644 file) - Symbolic: Suitable for "incremental modification"
(like
chmod u+x script.sh), safer (won't accidentally change other permission bits)
chown: Modifying File Ownership
chown is used to modify file owner and group.
Basic usage: 1
2
3
4sudo chown newowner file # Only change owner
sudo chown newowner:newgroup file # Change both owner and group
sudo chown :newgroup file # Only change group
sudo chown -R user:group dir # Recursively modify directory and its contents
Notes:
- Only
rootor the file's current owner can modify ownership - Regular users can't "give" files to others (prevents malicious quota abuse)
Common scenarios:
- Web server directory:
sudo chown -R www-data:www-data /var/www/html - Shared project directory:
sudo chown -R :developers /srv/project
umask: Default Permissions for New Files
What is umask
umask is the User File Creation Mask,
determining default permissions for newly created files/directories.
Calculation method: 1. Default permissions (system preset):
- Files:
666(rw-rw-rw-, no execute permission, prevents accidental execution) - Directories:
777(rwxrwxrwx, directories need x to be enterable)
- Actual permissions = Default permissions - umask value
Example (umask = 022):
- File:
666 - 022 = 644(rw-r--r--) - Directory:
777 - 022 = 755(rwxr-xr-x)
View and Set umask
View current umask: 1
umask # Output: 0022 (first digit is special permission bit, usually ignored)
Temporarily set umask: 1
2umask 027 # Set to 027
# New files will have 640 (666-027), directories 750 (777-027)
Permanently set umask (for current user): Edit
~/.bashrc or ~/.zshrc, add: 1
umask 027
Common umask values:
| umask | File Perms | Dir Perms | Use Case |
|---|---|---|---|
| 022 | 644 | 755 | Default (files not modifiable by others) |
| 027 | 640 | 750 | Stricter (only group can access), recommended for production |
| 002 | 664 | 775 | Shared environment (group can modify), development |
| 077 | 600 | 700 | Extremely strict (only owner can access), personal private files |
Special Permissions: SUID/SGID/Sticky Bit
These three special permission bits are for specific operational needs; understanding their principles and use cases is important.
SUID (Set User ID)
Principle
When an executable file is given SUID permission, ordinary users executing the file run it with the file owner's identity, not the caller's own identity.
Common example: /usr/bin/passwd
ls -l /usr/bin/passwdshows:-rwsr-xr-xroot root (note owner's x became s)- When ordinary users execute
passwd, it runs as root, allowing modification of/etc/shadow(only root can write)
Why is SUID needed?
- Allows ordinary users to execute specific operations requiring high permissions (like changing own password)
- Doesn't need to give users
sudoprivileges (more secure)
View and Set
View: 1
ls -l file # If owner's x position shows s (lowercase) or S (uppercase), SUID is set
s(lowercase): SUID and has execute permissionS(uppercase): SUID but no execute permission (usually a configuration error)
Set SUID: 1
2chmod u+s myprog # Symbolic notation
chmod 4755 myprog # Numeric notation (4 means SUID, 755 is base permissions)
Remove SUID: 1
chmod u-s myprog
Hands-On Example
Suppose you have a C program myprog.c:
1
2
3
4
5
6
7
8
9
int main() {
printf("Real UID=%d, Effective UID=%d\n", getuid(), geteuid());
system("id");
return 0;
}
Compile and set SUID: 1
2
3gcc -o myprog myprog.c
sudo chown root myprog # Change owner to root
sudo chmod 4755 myprog # Set SUID + 755
Execute as ordinary user: 1
./myprog
Example output: 1
2Real UID=1000, Effective UID=0
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
- Real UID is current user (1000)
- Effective UID is file owner (0=root)
- So program runs with root privileges
Security Considerations
SUID is high-risk:
- If SUID program has vulnerabilities (like buffer overflow, command injection), attackers can gain root privileges
- Avoid setting SUID on untrusted programs
- Regularly audit SUID programs on system
Find all SUID programs on system: 1
find / -perm -4000 -type f 2>/dev/null
Common SUID programs (these are reasonable):
/usr/bin/passwd: Change password/usr/bin/sudo: Temporary privilege escalation/usr/bin/mount: Mount filesystems/usr/bin/ping: Send ICMP packets (needs raw socket permission)
SGID (Set Group ID)
Use Cases
SGID has two uses:
1. On Executable Files
When process runs, its effective group ID (GID) is replaced by the file's group. Common in tools that need to access specific group resources.
2. On Directories (More Common)
When a directory has SGID set, new files or subdirectories created within inherit the directory's group, not the creator's default group. This is perfect for team shared directories.
Example: 1
2
3sudo mkdir /srv/project
sudo chown :developers /srv/project # Change group to developers
sudo chmod 2775 /srv/project # Set SGID + 775 (2 means SGID)
Now, any files created by developers group members in
/srv/project automatically have group
developers, accessible to other group members.
View and Set
View: 1
ls -l file # If group's x position shows s (lowercase) or S (uppercase), SGID is set
Set SGID: 1
2chmod g+s shared_dir # Symbolic notation
chmod 2775 shared_dir # Numeric notation (2 means SGID)
Remove SGID: 1
chmod g-s shared_dir
Sticky Bit
Function and Principle
Sticky Bit is most common on multi-user writable public directories
like /tmp. When a directory has Sticky Bit set,
files in that directory can only be deleted or renamed by their owner or
root, even if others have write permission on the
directory.
Why is Sticky Bit needed?
/tmpis a temporary directory shared by all users, permissions are1777(rwxrwxrwt)- Without Sticky Bit, user A could delete user B's temp files (security risk)
- With Sticky Bit, user A can only delete their own files, not user B's files
View and Set
View: 1
ls -ld /tmp # Output: drwxrwxrwt (last character is t)
Set Sticky Bit: 1
2chmod o+t dirname # Symbolic notation
chmod 1777 /tmp # Numeric notation (1 means Sticky Bit)
Remove Sticky Bit: 1
chmod o-t dirname
Common Scenarios and Best Practices
Scenario 1: Executable Script
Problem:
./script.sh: Permission denied
Troubleshoot: 1
ls -l script.sh # Check permissions
If it shows -rw-r--r-- (no x), execute permission is
missing.
Solution: 1
2
3chmod +x script.sh # Add execute permission for all
# Or
chmod 755 script.sh # owner=rwx, group=r-x, others=r-x
Note: Script also needs shebang (like
#!/bin/bash), otherwise need to run with
bash script.sh.
Scenario 2: Web Server Directory
Requirement: Nginx/Apache needs to read files in
/var/www/html.
Troubleshoot: 1
2ls -ld /var/www /var/www/html
ls -l /var/www/html/index.html
Common issues:
- Insufficient directory permissions (Nginx user doesn't have x permission, can't enter)
- Insufficient file permissions (Nginx user doesn't have r permission, can't read)
Solution: 1
2
3
4
5sudo chown -R www-data:www-data /var/www/html # Change owner to www-data
sudo chmod -R 755 /var/www/html # Both directories and files set to 755
# Or stricter
sudo find /var/www/html -type d -exec chmod 755 {} \; # Directories 755
sudo find /var/www/html -type f -exec chmod 644 {} \; # Files 644
Scenario 3: Shared Directory (Team Collaboration)
Requirement: /srv/project directory,
developers group members can all read/write, others cannot access.
Solution: 1
2
3sudo mkdir /srv/project
sudo chown :developers /srv/project # Change group to developers
sudo chmod 2770 /srv/project # SGID + 770 (only owner and group can access)
2: SGID (new files automatically inherit developers group)770: owner and group both rwx, others no permissions
Verification: 1
2
3# User A (developers group member) creates file
touch /srv/project/fileA
ls -l /srv/project/fileA # Output: -rw-r--r-- userA developers
File group is automatically developers, other group
members can also access.
Scenario 4: Temp Directory (Prevent Mutual File Deletion)
Requirement: /tmp directory, all users
can create files, but can't delete others' files.
Solution: 1
sudo chmod 1777 /tmp # Sticky Bit + 777
1: Sticky Bit (only owner and root can delete files)777: All users can read/write/execute
Extended Mechanisms: ACL and chattr
ACL (Access Control Lists)
Why ACL is needed?
- Traditional permissions can only set three layers (owner/group/others), not flexible enough
- ACL can set permissions for specific users or specific groups (like "user A has read permission, user B has write permission")
View ACL: 1
getfacl file.txt
Set ACL: 1
2
3
4setfacl -m u:alice:rw file.txt # Give user alice read/write permission
setfacl -m g:dev:rx dir # Give group dev read/execute permission
setfacl -x u:alice file.txt # Remove alice's ACL
setfacl -b file.txt # Remove all ACLs
Recursive setting: 1
setfacl -R -m u:alice:rwx dir # Recursively set
chattr: File Attributes (Prevent Accidental Deletion/Modification)
chattr can set special file attributes (supported by
ext4 filesystem).
Common attributes:
i(immutable): File cannot be modified, deleted, renamed (not even by root, unless i attribute is removed first)a(append-only): File can only be appended to, cannot modify existing content (suitable for log files)
Set immutable: 1
2
3sudo chattr +i important.conf # File becomes immutable
rm important.conf # ❌ Operation not permitted (not even root can delete)
sudo chattr -i important.conf # Remove i attribute before deleting
Set append-only: 1
2
3sudo chattr +a logfile.txt # Only append allowed
echo "new line" >> logfile.txt # ✅ Can append
echo "overwrite" > logfile.txt # ❌ Operation not permitted (cannot overwrite)
View attributes: 1
lsattr file.txt
Use cases:
- Protect important config files (
/etc/fstab,/etc/passwd) - Prevent log files from being cleared
Permission Troubleshooting Checklist: What to Do When Problems Arise
Problem 1:
Permission denied
Troubleshooting steps: 1. Confirm executing user:
whoami (or check service's running user, like systemd unit
file) 2. View file permissions: ls -l file 3. View all
parent directory permissions: namei -l /full/path/to/file
(needs util-linux package) 4. Check group membership:
id (see which groups current user belongs to) 5. Check
special attributes: lsattr file (whether has i
or a attribute)
Common causes:
- File doesn't have read/write/execute permission
- Parent directory doesn't have x permission (can't enter)
- User not in file's group
Solutions: 1
2
3
4sudo chmod 644 file # Give read permission
sudo chmod +x script.sh # Give execute permission
sudo chmod 755 /path/to/parent/dir # Give parent directory x permission
sudo chown user:group file # Modify ownership
Problem 2: Web Server 403 Forbidden
Cause: Nginx/Apache user (like
www-data, nginx) doesn't have permission to
read file.
Troubleshoot: 1
2
3ps aux | grep nginx # Check nginx running user
ls -l /var/www/html/index.html # Check file permissions
namei -l /var/www/html/index.html # Check all parent directory permissions
Solution: 1
2
3sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html # Directories 755
sudo find /var/www/html -type f -exec chmod 644 {} \; # Files 644
Problem 3: Script Execution Fails
Cause: Script doesn't have execute permission or shebang is wrong.
Troubleshoot: 1
2ls -l script.sh # Check permissions
head -1 script.sh # Check shebang
Solution: 1
2chmod +x script.sh # Add execute permission
# Ensure shebang is correct (like #!/bin/bash)
Problem
4: rm: cannot remove 'file': Operation not permitted
Cause: File might have i attribute
(immutable).
Troubleshoot: 1
lsattr file
If output contains i (like ----i--------),
file has immutable attribute.
Solution: 1
2sudo chattr -i file # Remove i attribute
rm file # Can delete now
Summary and Further Reading
This article covers the core content of Linux file permissions: 1. ✅ Linux permission model (owner/group/others, rwx semantics) 2. ✅ rwx differences on files vs directories (most common pitfall) 3. ✅ chmod and chown usage (numeric/symbolic notation) 4. ✅ umask principles and common values (default permissions for new files) 5. ✅ Special permissions (SUID/SGID/Sticky Bit principles and use cases) 6. ✅ Extended mechanisms (ACL, chattr) 7. ✅ Permission troubleshooting checklist (Permission denied, 403, script execution failure, etc.)
Further Reading:
man chmod: View detailed chmod manualman chown: View detailed chown manualman 5 acl: View detailed ACL explanation- SELinux / AppArmor: More advanced security models (Mandatory Access Control MAC)
Next Steps:
- 《 Linux User Management 》: Learn how to manage
users/groups,
/etc/passwd,/etc/shadow, sudo configuration - 《 Linux Advanced File Operations 》: Learn pipes,
redirection, stdin/stdout/stderr,
xargs,tee
By this point, you should have upgraded from "can use chmod 755" to "understand permission semantics, can design shared directory permission schemes, can troubleshoot permission issues." File permissions are the cornerstone of Linux security; mastering them allows you to better protect systems and data.
- Post title:Linux File Permissions: rwx, chmod/chown, umask, SUID/SGID/Sticky, and Troubleshooting
- Post author:Chen Kai
- Create time:2022-12-15 00:00:00
- Post link:https://www.chenk.top/en/linux-file-permissions/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.