File Permission Issues
Introduction
File permission problems are among the most common yet frustrating issues system administrators encounter. When permissions are incorrect, applications fail to read files, web servers can't serve content, databases won't start, and users can't access their data. Understanding Linux file permissions and how to diagnose and fix permission issues is fundamental to effective system administration.
This comprehensive guide provides practical approaches to diagnosing and resolving file permission problems. You'll learn to read permission notation, use diagnostic commands, identify permission-related errors, and implement proper permission schemes for web servers, applications, and multi-user environments.
File permissions control who can read, write, and execute files on Linux systems. Incorrect permissions create security vulnerabilities or prevent legitimate access. This guide teaches you to balance security with functionality using proper permission management techniques.
Understanding Linux Permissions
Permission Basics
Linux uses a three-tier permission system:
Owner (User): File creator/owner permissions Group: Group member permissions Others: Everyone else permissions
Each tier has three permission types:
Read (r/4): View file contents or list directory Write (w/2): Modify file or directory contents Execute (x/1): Run file as program or access directory
Permission Notation
# Example: -rwxr-xr--
# - = File type (- file, d directory, l link)
# rwx = Owner: read, write, execute
# r-x = Group: read, no write, execute
# r-- = Others: read only
# Numeric notation
# 7 (rwx) = 4+2+1
# 6 (rw-) = 4+2
# 5 (r-x) = 4+1
# 4 (r--) = 4
Special Permissions
SUID (4000): Execute as file owner SGID (2000): Execute as group owner, inherit group on new files Sticky Bit (1000): Only owner can delete files in directory
Initial Permission Diagnostics
Quick Permission Check
# Check specific file
ls -l /path/to/file
# Check directory and contents
ls -la /path/to/directory
# Show numeric permissions
stat -c '%a %n' /path/to/file
# Show full details
stat /path/to/file
# Find files with specific permissions
find /path -type f -perm 0777
# Check ownership
ls -l /path/to/file | awk '{print $3, $4}'
# Check your current permissions
id
groups
# Test if you can read
cat /path/to/file > /dev/null 2>&1 && echo "Can read" || echo "Cannot read"
# Test if you can write
touch /path/to/directory/.test 2>/dev/null && rm /path/to/directory/.test && echo "Can write" || echo "Cannot write"
Step 1: Common Permission Errors
Permission Denied Errors
# Error: Permission denied
# Common causes:
# 1. No read permission on file
# 2. No execute permission on directory in path
# 3. Not owner and strict permissions
# Example scenario
$ cat /var/log/private.log
cat: /var/log/private.log: Permission denied
# Check permissions
ls -l /var/log/private.log
# Output: -rw------- 1 root root 1234 Jan 11 10:00 /var/log/private.log
# Solution: Change permissions or ownership
sudo chmod 644 /var/log/private.log
# or become root
sudo cat /var/log/private.log
Cannot Create/Write Errors
# Error: cannot create regular file: Permission denied
# Check directory permissions
ls -ld /path/to/directory
# Directory needs write permission
# rwxr-xr-x = Others can't write
chmod 775 /path/to/directory
# Check directory ownership
ls -ld /path/to/directory
# Change if needed
chown user:group /path/to/directory
# Check parent directory execute permission
ls -ld /path/to
# Need x permission to access subdirectories
Cannot Execute Errors
# Error: Permission denied when running script
# Check execute permission
ls -l script.sh
# Output: -rw-r--r-- (no execute)
# Add execute permission
chmod +x script.sh
# or specifically
chmod 755 script.sh
# Verify
ls -l script.sh
# Output: -rwxr-xr-x
# Alternative: run with interpreter
bash script.sh # Doesn't need execute permission
Step 2: Web Server Permission Issues
Apache/Nginx File Permissions
# Standard web directory permissions
# Directories: 755
# Files: 644
# Fix web directory permissions
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# Check web server user
ps aux | grep apache2 | head -1
ps aux | grep nginx | head -1
# Common web users
# apache, www-data, nginx, httpd
# Set ownership
chown -R www-data:www-data /var/www/html
# For upload directories
chmod 775 /var/www/html/uploads
chown -R www-data:www-data /var/www/html/uploads
# Check what user web server runs as
# Apache
grep "^User\|^Group" /etc/apache2/apache2.conf
# Nginx
grep "^user" /etc/nginx/nginx.conf
WordPress Permissions
# Standard WordPress permissions
cd /var/www/html/wordpress
# Directories
find . -type d -exec chmod 755 {} \;
# Files
find . -type f -exec chmod 644 {} \;
# wp-content permissions (for uploads)
chmod 775 wp-content
chmod 775 wp-content/uploads
# Set ownership
chown -R www-data:www-data /var/www/html/wordpress
# wp-config.php security
chmod 640 wp-config.php
chown www-data:www-data wp-config.php
# Verify
ls -la wp-config.php
Step 3: Database Permission Issues
MySQL Data Directory
# Check MySQL data directory
ls -ld /var/lib/mysql
# Should be owned by mysql user
# drwx------ mysql mysql
# Fix ownership
chown -R mysql:mysql /var/lib/mysql
chmod 700 /var/lib/mysql
# Individual database directories
chmod 700 /var/lib/mysql/database_name
# Table files
chmod 660 /var/lib/mysql/database_name/*
# MySQL socket
ls -l /var/run/mysqld/mysqld.sock
chmod 777 /var/run/mysqld/mysqld.sock
chown mysql:mysql /var/run/mysqld/mysqld.sock
PostgreSQL Permissions
# Check PostgreSQL data directory
ls -ld /var/lib/postgresql/*/main
# Should be 700 or 750
# drwx------ postgres postgres
# Fix ownership
chown -R postgres:postgres /var/lib/postgresql
chmod 700 /var/lib/postgresql/*/main
# Configuration files
chmod 640 /etc/postgresql/*/main/postgresql.conf
chown postgres:postgres /etc/postgresql/*/main/postgresql.conf
Step 4: SSH/User Permission Issues
SSH Key Permissions
# SSH is very strict about permissions
# Home directory: 755 or 700
chmod 755 /home/username
# or more secure:
chmod 700 /home/username
# .ssh directory: 700
chmod 700 /home/username/.ssh
# private keys: 600
chmod 600 /home/username/.ssh/id_rsa
chmod 600 /home/username/.ssh/id_ed25519
# public keys: 644
chmod 644 /home/username/.ssh/id_rsa.pub
# authorized_keys: 600
chmod 600 /home/username/.ssh/authorized_keys
# known_hosts: 644 or 600
chmod 644 /home/username/.ssh/known_hosts
# Ownership must be correct
chown -R username:username /home/username/.ssh
# Verify all SSH permissions
ls -la /home/username/.ssh/
# SSH won't work if permissions are wrong
# Check SSH logs for permission errors
tail -f /var/log/auth.log | grep sshd
User Home Directory Issues
# Check home directory permissions
ls -ld /home/username
# Should typically be 755
chmod 755 /home/username
# Ownership
chown username:username /home/username
# Fix all files in home directory
chown -R username:username /home/username
# Find files not owned by user
find /home/username ! -user username
# Fix specific permissions
chmod 644 /home/username/.bashrc
chmod 644 /home/username/.profile
chmod 700 /home/username/.config
Step 5: Application Permission Issues
PHP-FPM Session Directory
# Session directory permissions
ls -ld /var/lib/php/sessions
# Should be writable by php-fpm user
chmod 1733 /var/lib/php/sessions
# or
chmod 770 /var/lib/php/sessions
chown root:www-data /var/lib/php/sessions
# Check PHP-FPM user
ps aux | grep php-fpm | head -1
# Clean old sessions
find /var/lib/php/sessions -type f -mtime +7 -delete
Application Upload Directories
# Create upload directory
mkdir -p /var/www/html/uploads
# Set permissions
chmod 775 /var/www/html/uploads
chown www-data:www-data /var/www/html/uploads
# Set SGID to inherit group
chmod g+s /var/www/html/uploads
# Verify
ls -ld /var/www/html/uploads
# Should show: drwxrwsr-x www-data www-data
# New files will inherit group ownership
Log File Permissions
# Application log directory
mkdir -p /var/log/myapp
chmod 755 /var/log/myapp
chown myapp:adm /var/log/myapp
# Log files
touch /var/log/myapp/app.log
chmod 640 /var/log/myapp/app.log
chown myapp:adm /var/log/myapp/app.log
# Logrotate permissions
# Create in /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0640 myapp adm
}
Step 6: Finding Permission Problems
Find Files with Wrong Permissions
# Find world-writable files (security risk)
find / -type f -perm -002 2>/dev/null
# Find world-writable directories
find / -type d -perm -002 2>/dev/null
# Find files with no owner
find / -nouser -o -nogroup 2>/dev/null
# Find SUID files
find / -perm -4000 -type f 2>/dev/null
# Find SGID files
find / -perm -2000 -type f 2>/dev/null
# Find files owned by specific user
find / -user username 2>/dev/null
# Find files modified recently
find / -type f -mtime -1 2>/dev/null
# Find executable files
find / -type f -perm -111 2>/dev/null
Permission Audit Script
cat > /tmp/permission-audit.sh << 'EOF'
#!/bin/bash
echo "Permission Security Audit"
echo "========================"
echo -e "\nWorld-writable files:"
find / -type f -perm -002 ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | head -20
echo -e "\nWorld-writable directories:"
find / -type d -perm -002 ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | head -20
echo -e "\nSUID files:"
find / -perm -4000 -type f 2>/dev/null
echo -e "\nFiles with no owner:"
find / -nouser -o -nogroup 2>/dev/null | head -20
echo -e "\nSSH permission issues:"
for user in $(ls /home); do
if [ -d "/home/$user/.ssh" ]; then
echo "User: $user"
ls -la /home/$user/.ssh/ | grep -E "authorized_keys|id_rsa"
fi
done
EOF
chmod +x /tmp/permission-audit.sh
/tmp/permission-audit.sh
Step 7: Access Control Lists (ACL)
Using ACLs for Complex Permissions
# Check if ACLs are supported
tune2fs -l /dev/sda1 | grep "Default mount options:"
# View ACLs
getfacl /path/to/file
# Set ACL for specific user
setfacl -m u:username:rw /path/to/file
# Set ACL for specific group
setfacl -m g:groupname:rwx /path/to/directory
# Set default ACL for directory (inherited by new files)
setfacl -d -m u:username:rw /path/to/directory
# Remove specific ACL
setfacl -x u:username /path/to/file
# Remove all ACLs
setfacl -b /path/to/file
# Copy ACLs
getfacl /source/file | setfacl --set-file=- /dest/file
# Recursive ACL
setfacl -R -m u:username:rwx /path/to/directory
Solutions and Best Practices
Standard Permission Schemes
# Web server directories
find /var/www -type d -exec chmod 755 {} \;
find /var/www -type f -exec chmod 644 {} \;
chown -R www-data:www-data /var/www
# User home directories
chmod 755 /home/username
chown -R username:username /home/username
# Application directories
mkdir -p /opt/myapp
chmod 755 /opt/myapp
chown -R myapp:myapp /opt/myapp
# Configuration files
chmod 640 /etc/myapp/config.conf
chown root:myapp /etc/myapp/config.conf
# Executable scripts
chmod 755 /usr/local/bin/script.sh
chown root:root /usr/local/bin/script.sh
# Log directories
chmod 755 /var/log/myapp
chown myapp:adm /var/log/myapp
Permission Reset Script
cat > /usr/local/bin/fix-web-permissions.sh << 'EOF'
#!/bin/bash
WEB_ROOT="/var/www/html"
WEB_USER="www-data"
WEB_GROUP="www-data"
echo "Fixing permissions for $WEB_ROOT"
# Set directory permissions
find "$WEB_ROOT" -type d -exec chmod 755 {} \;
# Set file permissions
find "$WEB_ROOT" -type f -exec chmod 644 {} \;
# Set ownership
chown -R $WEB_USER:$WEB_GROUP "$WEB_ROOT"
# Special directories
if [ -d "$WEB_ROOT/uploads" ]; then
chmod 775 "$WEB_ROOT/uploads"
chmod g+s "$WEB_ROOT/uploads"
fi
if [ -d "$WEB_ROOT/cache" ]; then
chmod 775 "$WEB_ROOT/cache"
chmod g+s "$WEB_ROOT/cache"
fi
echo "Permissions fixed"
ls -la "$WEB_ROOT"
EOF
chmod +x /usr/local/bin/fix-web-permissions.sh
Monitoring Permissions
cat > /usr/local/bin/monitor-permissions.sh << 'EOF'
#!/bin/bash
LOG="/var/log/permission-monitor.log"
# Check for new SUID files
CURRENT_SUID=$(find / -perm -4000 -type f 2>/dev/null | sort)
if [ -f /tmp/suid_baseline.txt ]; then
BASELINE=$(cat /tmp/suid_baseline.txt)
if [ "$CURRENT_SUID" != "$BASELINE" ]; then
echo "$(date): SUID files changed!" >> "$LOG"
diff /tmp/suid_baseline.txt <(echo "$CURRENT_SUID") >> "$LOG"
echo "SUID files changed on $(hostname)" | mail -s "Security Alert" [email protected]
fi
fi
echo "$CURRENT_SUID" > /tmp/suid_baseline.txt
# Check for world-writable files
WRITABLE=$(find /var/www -type f -perm -002 2>/dev/null)
if [ -n "$WRITABLE" ]; then
echo "$(date): World-writable files found:" >> "$LOG"
echo "$WRITABLE" >> "$LOG"
fi
EOF
chmod +x /usr/local/bin/monitor-permissions.sh
echo "0 */6 * * * /usr/local/bin/monitor-permissions.sh" | crontab -
Conclusion
File permission issues are common but manageable with proper understanding and tools. Key takeaways:
- Understand the basics: Owner, group, others and read, write, execute
- Check permissions first: Use ls -l and stat
- Know standard schemes: Web servers, databases, SSH all have specific requirements
- Balance security and functionality: Don't use 777 unless absolutely necessary
- Use proper ownership: Ensure files owned by correct user and group
- Monitor changes: Watch for unexpected permission modifications
- Document standards: Maintain permission schemes for your applications
Regular permission audits, proper initial configuration, and understanding these diagnostic techniques ensure secure and functional file access across your Linux systems.


