Linux File Permissions and Ownership Guide
Understanding file permissions and ownership is crucial for Linux security and system administration. This comprehensive guide covers everything from basic permission concepts to advanced access control lists (ACLs).
Overview: Understanding Linux Permissions
Linux uses a robust permission system to control who can read, write, or execute files and directories.
Permission Basics
Every file and directory has three types of permissions for three classes of users:
| Permission | Symbol | Value | On Files | On Directories |
|---|---|---|---|---|
| Read | r |
4 | View file contents | List directory contents |
| Write | w |
2 | Modify file contents | Create/delete files in directory |
| Execute | x |
1 | Run file as program | Enter directory |
User Classes
| Class | Symbol | Description |
|---|---|---|
| User/Owner | u |
The file owner |
| Group | g |
Users in the file's group |
| Others | o |
All other users |
| All | a |
All three classes |
Viewing Permissions
List Files with Permissions
# Basic listing
ls -l
# Output format:
# -rw-r--r-- 1 user group 1234 Jan 1 12:00 file.txt
# |[-][-][-] | | | | | └─ filename
# | └ other | | | | └─ modification time
# | └ group | | | └─ size
# | └ user | | └─ group name
# | | └─ owner name
# | └─ number of links
# └─ file type and permissions
Detailed Permission Viewing
# Long listing with human-readable sizes
ls -lh
# Show all files including hidden
ls -la
# Numeric permission display
stat -c '%a %n' file.txt
# Detailed file info
stat file.txt
# Show permissions in octal
ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));print k" "$9}'
Changing Permissions with chmod
Symbolic Mode
# Add execute permission for user
chmod u+x script.sh
# Remove write permission for group
chmod g-w file.txt
# Set read-only for others
chmod o=r file.txt
# Add read permission for all
chmod a+r document.txt
# Multiple changes
chmod u+x,g+w,o-r file.sh
Numeric (Octal) Mode
# Set permissions to 644 (rw-r--r--)
chmod 644 file.txt
# Set permissions to 755 (rwxr-xr-x)
chmod 755 script.sh
# Set permissions to 600 (rw-------)
chmod 600 private.key
# Set permissions to 777 (rwxrwxrwx) - USE WITH CAUTION
chmod 777 dangerous.sh
Common Permission Values
| Octal | Binary | Permission | Typical Use |
|---|---|---|---|
| 755 | rwxr-xr-x |
Full for owner, read/execute for others | Directories, executables |
| 644 | rw-r--r-- |
Read/write for owner, read-only for others | Regular files |
| 600 | rw------- |
Read/write for owner only | Private files, keys |
| 777 | rwxrwxrwx |
Full access for all | Temporary, testing (avoid) |
| 700 | rwx------ |
Full access for owner only | Private directories |
| 660 | rw-rw---- |
Read/write for owner and group | Shared files |
| 755 | rwxr-xr-x |
Executable scripts | Shell scripts, binaries |
Recursive Permission Changes
# Change permissions recursively
chmod -R 755 directory/
# Set all files to 644, directories to 755
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
# Add execute only to directories
chmod -R a+X directory/
# Verbose output
chmod -v 755 file.sh
Special Permissions
# Set SUID (Set User ID) - 4000
chmod u+s executable
chmod 4755 executable
# Set SGID (Set Group ID) - 2000
chmod g+s directory/
chmod 2755 directory/
# Set Sticky Bit - 1000
chmod +t /tmp
chmod 1777 /shared/temp/
# Remove special permissions
chmod u-s file
chmod g-s directory/
chmod -t directory/
Changing Ownership with chown
Basic chown Usage
# Change owner
chown newowner file.txt
# Change owner and group
chown newowner:newgroup file.txt
# Change only group (alternative to chgrp)
chown :newgroup file.txt
# Change owner recursively
chown -R username directory/
Advanced chown Operations
# Preserve root ownership
chown --preserve-root user /
# Change ownership from reference file
chown --reference=ref.txt target.txt
# Verbose output
chown -v user:group file.txt
# Change but keep existing group
chown newuser: file.txt
# Recursive with different file types
find /var/www -type f -exec chown www-data:www-data {} \;
find /var/www -type d -exec chown www-data:www-data {} \;
Changing Group with chgrp
Basic chgrp Usage
# Change group
chgrp developers file.txt
# Change group recursively
chgrp -R staff project/
# Verbose output
chgrp -v webgroup index.html
# From reference file
chgrp --reference=template.txt newfile.txt
Practical Group Examples
# Set web server group
chgrp -R www-data /var/www/html/
# Set development team group
chgrp -R devteam /opt/projects/
# Share directory with group
chgrp staff /shared/
chmod 770 /shared/
Default Permissions with umask
Understanding umask
# View current umask
umask
# View in symbolic notation
umask -S
# Set umask (subtract from 777 for dirs, 666 for files)
umask 022 # Creates files as 644, dirs as 755
# Set umask with symbolic notation
umask u=rwx,g=rx,o=rx
Common umask Values
| umask | Files Created | Directories Created | Use Case |
|---|---|---|---|
| 022 | 644 (rw-r--r--) | 755 (rwxr-xr-x) | Default, shared system |
| 027 | 640 (rw-r-----) | 750 (rwxr-x---) | Group collaboration |
| 077 | 600 (rw-------) | 700 (rwx------) | Maximum privacy |
| 002 | 664 (rw-rw-r--) | 775 (rwxrwxr-x) | Full group access |
Setting Permanent umask
# In ~/.bashrc or ~/.profile
umask 027
# System-wide in /etc/profile
echo "umask 022" >> /etc/profile
# For specific user
echo "umask 077" >> ~/.bashrc
Special Permission Bits
SUID (Set User ID)
When set on executable, runs with owner's permissions instead of executor's.
# Set SUID
chmod u+s /usr/bin/program
chmod 4755 /usr/bin/program
# Find all SUID files (security audit)
find / -perm -4000 -type f 2>/dev/null
# Remove SUID
chmod u-s file
Security Note: SUID root files are sensitive - audit regularly!
SGID (Set Group ID)
On executables: runs with group's permissions
On directories: new files inherit directory's group
# Set SGID on directory for group collaboration
chmod g+s /shared/project/
chmod 2775 /shared/project/
# Find SGID files
find / -perm -2000 -type f 2>/dev/null
# Remove SGID
chmod g-s directory/
Sticky Bit
Prevents users from deleting files they don't own (even in writable directories).
# Set sticky bit on shared directory
chmod +t /tmp/shared/
chmod 1777 /tmp/shared/
# Typical use: /tmp directory
ls -ld /tmp # Shows drwxrwxrwt
# Find directories with sticky bit
find / -type d -perm -1000 2>/dev/null
# Remove sticky bit
chmod -t directory/
Access Control Lists (ACLs)
ACLs provide fine-grained permission control beyond traditional Unix permissions.
Viewing ACLs
# Check if file has ACL
ls -l file.txt # Shows + at end if ACL present
# View ACL
getfacl file.txt
# View ACL for multiple files
getfacl file1.txt file2.txt
Setting ACLs
# Grant user specific permissions
setfacl -m u:john:rw file.txt
# Grant group permissions
setfacl -m g:developers:rx directory/
# Set default ACL for new files in directory
setfacl -d -m u:jane:rw directory/
# Multiple ACLs at once
setfacl -m u:user1:rw,u:user2:r file.txt
Removing ACLs
# Remove specific ACL
setfacl -x u:john file.txt
# Remove all ACLs
setfacl -b file.txt
# Remove default ACLs
setfacl -k directory/
Recursive ACL Operations
# Set ACL recursively
setfacl -R -m u:webuser:rx /var/www/
# Copy ACL from one file to another
getfacl file1.txt | setfacl --set-file=- file2.txt
# Set default ACL for directory
setfacl -R -d -m g:developers:rwx /project/
Common Use Cases and Examples
Web Server Permissions
# Set proper permissions for web directory
sudo chown -R www-data:www-data /var/www/html/
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# Make uploads directory writable
sudo chmod 775 /var/www/html/uploads/
sudo chown -R www-data:www-data /var/www/html/uploads/
Shared Project Directory
# Create shared directory
sudo mkdir /shared/project
sudo chgrp developers /shared/project
sudo chmod 2775 /shared/project # SGID + group write
sudo setfacl -d -m g:developers:rwx /shared/project
SSH Key Permissions
# Secure SSH directory
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 644 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts
Database Files
# Secure database files
sudo chown mysql:mysql /var/lib/mysql/
sudo chmod 750 /var/lib/mysql/
sudo chmod 640 /var/mysql/*.conf
Log Files
# Set log permissions
sudo chmod 640 /var/log/application.log
sudo chown app:adm /var/log/application.log
# Rotate logs with proper permissions
sudo chmod 644 /var/log/*.log.1
Security Best Practices
Principle of Least Privilege
# Don't use 777 - find better solution
# BAD:
chmod 777 directory/
# GOOD: Use specific group
chgrp webapps directory/
chmod 775 directory/
Regular Security Audits
# Find world-writable files
find / -type f -perm -002 ! -path "/proc/*" 2>/dev/null
# Find SUID/SGID files
find / -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null
# Find files with no owner
find / -nouser -o -nogroup 2>/dev/null
# Find overly permissive directories
find / -type d -perm -002 ! -perm -1000 2>/dev/null
Protecting Sensitive Files
# Private keys
chmod 600 private.key
chown user:user private.key
# Configuration with passwords
chmod 640 config.conf
chown root:appgroup config.conf
# Executable scripts
chmod 750 script.sh
chown user:group script.sh
Troubleshooting Permission Issues
Permission Denied Errors
# Check current permissions
ls -l file.txt
# Check ownership
stat file.txt
# Verify your permissions
groups # See what groups you're in
id # See your user and group IDs
# Fix common issues
sudo chmod 644 file.txt
sudo chown $USER:$USER file.txt
Cannot Delete File
# Check directory permissions
ls -ld directory/
# Check file attributes
lsattr file.txt
# Remove immutable flag
sudo chattr -i file.txt
# Verify you own the file or directory
ls -l file.txt
Script Won't Execute
# Add execute permission
chmod +x script.sh
# Check shebang
head -1 script.sh # Should be #!/bin/bash or similar
# Verify interpreter exists
which bash
Web Server 403 Forbidden
# Check file permissions
ls -l /var/www/html/index.html
# Check directory permissions
ls -ld /var/www/html/
# Fix common Apache/Nginx permissions
sudo chown -R www-data:www-data /var/www/html/
sudo chmod -R 755 /var/www/html/
sudo chmod -R 644 /var/www/html/*.html
Advanced Techniques
Bulk Permission Fixes
# Reset all files in web root
sudo find /var/www -type d -exec chmod 755 {} \;
sudo find /var/www -type f -exec chmod 644 {} \;
sudo find /var/www -name "*.sh" -exec chmod 755 {} \;
# Fix home directory permissions
chmod 755 ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
chmod 644 ~/.ssh/*.pub
Conditional Permissions
# Add execute only if any execute bit is set
chmod a+X file # Capital X
# Set permission based on file type
find . -type f -name "*.sh" -exec chmod 755 {} \;
find . -type f -name "*.conf" -exec chmod 644 {} \;
Permission Inheritance
# Set default ACL for directory
setfacl -d -m u::rwx,g::rx,o::--- /data/project/
# All new files will inherit these ACLs
touch /data/project/newfile.txt
getfacl /data/project/newfile.txt
Quick Reference
Permission Calculation
Octal = Sum of:
- Read (r) = 4
- Write (w) = 2
- Execute (x) = 1
Example: rwxr-xr-- = 754
- Owner: rwx = 4+2+1 = 7
- Group: r-x = 4+0+1 = 5
- Others: r-- = 4+0+0 = 4
Essential Commands
# View permissions
ls -l file
stat file
# Change permissions
chmod 644 file
chmod u+x file
# Change owner
chown user:group file
# Change group
chgrp group file
# View/set umask
umask
umask 022
# ACLs
getfacl file
setfacl -m u:user:rw file
# Find by permission
find / -perm 777
find / -perm -4000