Complete Guide to Bash File Permissions and Ownership

Introduction to File Permissions

File permissions and ownership are fundamental concepts in Unix/Linux systems that control access to files and directories. Understanding these concepts is crucial for system security, multi-user environments, and proper file management.

Key Concepts

  • Ownership: Every file has a user owner and group owner
  • Permissions: Read (r), Write (w), Execute (x) for three classes
  • Classes: User (owner), Group, Others (everyone else)
  • Special Permissions: Setuid, Setgid, Sticky bit
  • UMASK: Default permission mask for new files

1. Viewing Permissions and Ownership

Using ls -l

# View file permissions ls -l file.txt # -rw-r--r-- 1 user group 1024 Jan 1 10:00 file.txt # View directory permissions ls -ld directory/ # drwxr-xr-x 2 user group 4096 Jan 1 10:00 directory/ # View all files including hidden ls -la # View with human-readable sizes ls -lh # Recursive listing ls -lR # Explanation of output: # -rw-r--r-- # ││││││││└─ Others permissions (r--) # ││││││└── Group permissions (r--) # │││││└─── User permissions (rw-) # ││││└──── Number of hard links # │││└───── Special permissions (if any) # ││└────── Group owner # │└─────── User owner # └──────── File type (- = file, d = directory, l = symlink)

Using stat

# Detailed file information stat file.txt # Output: # File: file.txt # Size: 1024 Blocks: 8 IO Block: 4096 regular file # Device: 801h/2049d Inode: 1234567 Links: 1 # Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ group) # Access: 2024-01-01 10:00:00.000000000 # Modify: 2024-01-01 10:00:00.000000000 # Change: 2024-01-01 10:00:00.000000000 # Custom stat output stat -c "%a %A %n" * # Permissions in octal, symbolic, and name # Get specific information stat -c "%U" file.txt # Get owner stat -c "%G" file.txt # Get group stat -c "%a" file.txt # Get permissions in octal stat -c "%A" file.txt # Get permissions in symbolic

Understanding Permission Notation

# Symbolic notation (rwx) # r = read (4) # w = write (2) # x = execute (1) # - = no permission # Examples: # rw------- (600) - Owner can read/write, nothing for others # rw-r--r-- (644) - Owner read/write, others read only # rwxr-xr-x (755) - Owner all, others read/execute # rwx------ (700) - Only owner has all permissions # Octal notation # 0 = --- (no permissions) # 1 = --x (execute only) # 2 = -w- (write only) # 3 = -wx (write and execute) # 4 = r-- (read only) # 5 = r-x (read and execute) # 6 = rw- (read and write) # 7 = rwx (read, write, execute) # Examples: chmod 755 script.sh # rwxr-xr-x chmod 644 file.txt # rw-r--r-- chmod 700 private/ # rwx------

2. Changing Permissions (chmod)

Symbolic Mode

# Basic symbolic syntax # u = user (owner) # g = group # o = others # a = all (ugo) # + = add permission # - = remove permission # = = set exactly # Add execute permission for user chmod u+x script.sh # Remove write permission for others chmod o-w file.txt # Add read and execute for group chmod g+rx directory/ # Set exactly rwx for user, rx for group, nothing for others chmod u=rwx,g=rx,o= file.txt # Add execute for all chmod a+x script.sh # Remove write from all chmod a-w file.txt # Multiple changes chmod u+x,g-w,o=r file.txt # Recursive changes chmod -R u+x directory/ # Examples chmod u+x,g+x script.sh # Add execute for user and group chmod go-w file.txt # Remove write from group and others chmod a=rw file.txt # Set read/write for everyone

Numeric (Octal) Mode

# Three-digit octal (owner, group, others) chmod 755 script.sh # rwxr-xr-x chmod 644 file.txt # rw-r--r-- chmod 700 private/ # rwx------ chmod 777 public/ # rwxrwxrwx (dangerous!) chmod 600 secret.txt # rw------- # Four-digit octal (includes special permissions) chmod 4755 script.sh # rwsr-xr-x (setuid) chmod 2755 directory/ # rwxr-sr-x (setgid) chmod 1777 /tmp # rwxrwxrwt (sticky bit) # Common permission sets chmod 755 script.sh # Executable scripts chmod 644 *.txt # Regular text files chmod 600 .ssh/id_rsa # Private SSH key chmod 700 .ssh # SSH directory chmod 755 public_html # Web directory chmod 640 config.cfg # Configuration readable by group # Calculate permissions # To get 754: 7 (rwx) for owner, 5 (r-x) for group, 4 (r--) for others chmod 754 file.txt

Common Permission Scenarios

#!/bin/bash # Make script executable make_executable() { local file="$1" if [ -f "$file" ]; then chmod +x "$file" echo "✓ Made executable: $file" fi } # Secure private key secure_ssh_key() { local key="$HOME/.ssh/id_rsa" if [ -f "$key" ]; then chmod 600 "$key" chmod 700 "$HOME/.ssh" echo "✓ SSH key secured" fi } # Set up shared directory setup_shared() { local dir="$1" local group="$2" mkdir -p "$dir" chgrp -R "$group" "$dir" chmod -R 775 "$dir" chmod g+s "$dir" # Setgid for inheritance echo "✓ Shared directory setup: $dir" } # Reset permissions to safe defaults safe_permissions() { local dir="$1" # Directories: 755 find "$dir" -type d -exec chmod 755 {} \; # Files: 644 find "$dir" -type f -exec chmod 644 {} \; # Executable scripts: 755 find "$dir" -name "*.sh" -type f -exec chmod 755 {} \; echo "✓ Safe permissions applied to $dir" }

3. Changing Ownership (chown, chgrp)

chown - Change Owner

# Change owner only sudo chown user file.txt # Change owner and group sudo chown user:group file.txt # Change group only (with colon) sudo chown :group file.txt # Change owner and group (using dot) sudo chown user.group file.txt # Legacy syntax # Recursive change sudo chown -R user:group directory/ # Change only if current owner matches sudo chown --from=current_user user file.txt # Change only if current group matches sudo chown --from=:current_group :group file.txt # Reference another file's ownership sudo chown --reference=ref_file target_file # Verbose output sudo chown -v user:group file.txt # Examples sudo chown www-data:www-data /var/www/html/ -R sudo chown user:users /home/user/documents/ -R sudo chown :developers project/ -R

chgrp - Change Group Only

# Change group sudo chgrp group file.txt # Recursive change sudo chgrp -R group directory/ # Verbose output sudo chgrp -v group file.txt # Reference file sudo chgrp --reference=ref_file target_file # Preserve root directory sudo chgrp -hR group symbolic_link/ # Don't follow symlinks # Examples sudo chgrp developers project/ sudo chgrp -R www-data /var/www/html/ sudo chgrp users /home/shared/ -R

Advanced Ownership Management

#!/bin/bash # Reset ownership to user's primary group fix_ownership() { local dir="$1" local user="$2" # Get user's primary group group=$(id -gn "$user") sudo chown -R "$user:$group" "$dir" echo "✓ Ownership fixed for $dir" } # Set up shared project setup_project() { local project="$1" local group="$2" local users=("${@:3}") # Create project directory sudo mkdir -p "/projects/$project" # Set group ownership sudo chgrp -R "$group" "/projects/$project" # Set setgid bit for inheritance sudo chmod g+s "/projects/$project" # Set permissions sudo chmod 2775 "/projects/$project" # Add users to group for user in "${users[@]}"; do sudo usermod -a -G "$group" "$user" done echo "✓ Project $project created for group $group" } # Transfer files to another user transfer_files() { local src="$1" local from_user="$2" local to_user="$3" # Change ownership sudo chown -R "$to_user" "$src" # Update home directory permissions if needed if [[ "$src" == "/home/$from_user"* ]]; then sudo chmod 700 "/home/$to_user" fi echo "✓ Files transferred from $from_user to $to_user" } # Audit ownership audit_ownership() { local dir="$1" echo "Ownership audit for $dir" echo "========================" find "$dir" -printf "%u:%g %p\n" 2>/dev/null | sort | uniq -c | while read count owner path; do echo "$count files owned by $owner" done }

4. Special Permissions

Setuid (Set User ID) - 4xxx

# Setuid bit (user gets owner's permissions when executing) chmod u+s program chmod 4755 program # rwsr-xr-x # Remove setuid chmod u-s program chmod 755 program # rwxr-xr-x # Example: /usr/bin/passwd has setuid ls -l /usr/bin/passwd # -rwsr-xr-x 1 root root Jan 1 10:00 /usr/bin/passwd # Find setuid files find / -perm -4000 -type f 2>/dev/null # Check for setuid if [ -u "$file" ]; then echo "$file has setuid bit" fi

Setgid (Set Group ID) - 2xxx

# Setgid on files (executes with group privileges) chmod g+s program chmod 2755 program # rwxr-sr-x # Setgid on directories (new files inherit group) chmod g+s directory/ chmod 2775 directory/ # drwxrwsr-x # Remove setgid chmod g-s directory/ # Find setgid files find / -perm -2000 -type f 2>/dev/null # Find setgid directories find / -perm -2000 -type d 2>/dev/null # Example: Shared directory setup mkdir shared chgrp developers shared chmod 2775 shared touch shared/file.txt # Inherits 'developers' group

Sticky Bit - 1xxx

# Sticky bit on directories (only owner can delete files) chmod +t directory/ chmod 1777 /tmp # drwxrwxrwt # Remove sticky bit chmod -t directory/ # Find directories with sticky bit find / -perm -1000 -type d 2>/dev/null # Example: /tmp has sticky bit ls -ld /tmp # drwxrwxrwt 1 root root Jan 1 10:00 /tmp # Check for sticky bit if [ -k "$dir" ]; then echo "$dir has sticky bit" fi # Safe shared directory with sticky bit setup_shared_with_sticky() { local dir="$1" local group="$2" mkdir -p "$dir" chgrp "$group" "$dir" chmod 1777 "$dir" # All can write, only owner can delete echo "✓ Shared directory with sticky bit: $dir" }

Combined Special Permissions

# All special permissions chmod 7777 file # rwsrwsrwt (very dangerous!) # Common combinations chmod 4755 file # rwsr-xr-x (setuid) chmod 2755 file # rwxr-sr-x (setgid) chmod 1777 dir # rwxrwxrwt (sticky) chmod 6777 file # rwsrwsrwx (all special + full permissions) # Safe shared directory with inheritance chmod 2770 shared/ # rwxrws--- (group inheritance, no others) # Check special permissions check_special_perms() { local file="$1" perms=$(stat -c "%a" "$file") if [ ${#perms} -eq 4 ]; then case "${perms:0:1}" in 4) echo "Setuid set" ;; 2) echo "Setgid set" ;; 1) echo "Sticky bit set" ;; 6) echo "Setuid and setgid set" ;; 5) echo "Setuid and sticky set" ;; 3) echo "Setgid and sticky set" ;; 7) echo "All special permissions set" ;; esac fi }

5. Default Permissions (umask)

Understanding umask

# View current umask umask # Output: 0022 # View in symbolic form umask -S # Output: u=rwx,g=rx,o=rx # How umask works: # Default file permissions: 666 (rw-rw-rw-) # Default directory permissions: 777 (rwxrwxrwx) # umask subtracts permissions # umask 022: # Files: 666 - 022 = 644 (rw-r--r--) # Directories: 777 - 022 = 755 (rwxr-xr-x) # umask 002: # Files: 666 - 002 = 664 (rw-rw-r--) # Directories: 777 - 002 = 775 (rwxrwxr-x) # umask 077: # Files: 666 - 077 = 600 (rw-------) # Directories: 777 - 077 = 700 (rwx------)

Setting umask

# Set numeric umask umask 022 umask 002 umask 077 # Set symbolic umask umask u=rwx,g=rx,o=rx # Same as 022 umask u=rwx,g=rwx,o=r # Same as 002 umask u=rwx,g=,o= # Same as 077 # Set in shell configuration (~/.bashrc) echo "umask 022" >> ~/.bashrc # Set system-wide (/etc/profile) echo "umask 022" >> /etc/profile # Different umask for different users setup_umask() { case $(whoami) in root) umask 022 ;; developer) umask 002 ;; guest) umask 077 ;; esac }

Practical umask Examples

#!/bin/bash # Secure environment secure_umask() { umask 077 # Only owner can access new files echo "✓ Secure umask set: $(umask)" } # Collaborative environment collab_umask() { umask 002 # Group can write new files echo "✓ Collaborative umask set: $(umask)" } # Calculate effective permissions calculate_perms() { local base="${1:-666}" # Default for files local umask_val="${2:-$(umask)}" # Remove leading zeros if present umask_val=$(echo "$umask_val" | sed 's/^0*//') # Calculate result=$((base - umask_val)) echo "Base: $base, Umask: $umask_val, Result: $result" # Show symbolic echo "Permissions: $(stat -c "%A" <(exit) 2>/dev/null | sed "s/........./$result/")" } # Test different umasks test_umask() { local test_file="/tmp/umask_test.$$" for mask in 000 022 002 077 027; do umask $mask touch "$test_file" perms=$(ls -l "$test_file" | cut -d' ' -f1) echo "umask $mask: $perms" rm "$test_file" done }

6. Advanced Permission Management

Access Control Lists (ACL)

# Install ACL tools (if not present) sudo apt install acl # Debian/Ubuntu sudo yum install acl # RHEL/CentOS # View ACL getfacl file.txt # Set ACL setfacl -m u:user:rwx file.txt # Add for specific user setfacl -m g:group:rx file.txt # Add for specific group setfacl -m o::r file.txt # Set for others setfacl -m m::rwx file.txt # Set mask # Remove ACL setfacl -x u:user file.txt # Remove specific user setfacl -b file.txt # Remove all ACLs # Recursive ACL setfacl -R -m u:user:rwx directory/ setfacl -R -m g:group:rx directory/ # Default ACL (inherited) setfacl -d -m u:user:rwx directory/ # Examples # Give user john read/write access to project setfacl -m u:john:rw project/ # Give web server read access to logs setfacl -m g:www-data:r /var/log/app/ # Set up shared directory with ACL setup_acl_share() { local dir="$1" shift local users=("$@") mkdir -p "$dir" # Set base permissions setfacl -b "$dir" setfacl -m g::rwx "$dir" setfacl -m o::--- "$dir" # Add users for user in "${users[@]}"; do setfacl -m "u:$user:rwx" "$dir" done # Set defaults for new files setfacl -d -m g::rwx "$dir" for user in "${users[@]}"; do setfacl -d -m "u:$user:rwx" "$dir" done echo "✓ ACL shared directory: $dir" }

File Attributes (chattr)

# View attributes lsattr file.txt # Set attributes sudo chattr +i file.txt # Immutable - cannot modify/delete sudo chattr +a file.txt # Append only sudo chattr +c file.txt # Compressed sudo chattr +s file.txt # Secure deletion sudo chattr +u file.txt # Undeletable # Remove attributes sudo chattr -i file.txt # Common attributes # i - immutable (even root can't modify) # a - append only (for logs) # d - no dump (exclude from backup) # c - compressed # s - secure deletion # u - undeletable # Examples # Protect critical configuration sudo chattr +i /etc/passwd /etc/shadow # Log file that can only be appended sudo chattr +a /var/log/app.log # Find immutable files find / -type f -exec lsattr {} \; 2>/dev/null | grep "^....i" # Check if file is immutable if lsattr "$file" 2>/dev/null | grep -q "^....i"; then echo "$file is immutable" fi

7. Permission Management Scripts

Permission Audit Script

#!/bin/bash # Comprehensive permission audit audit_permissions() { local dir="${1:-.}" local report="/tmp/audit_$(date +%Y%m%d).txt" { echo "Permission Audit Report - $(date)" echo "===================================" echo echo "Audit directory: $dir" echo # World-writable files echo "World-writable files:" find "$dir" -type f -perm -002 -ls 2>/dev/null | while read line; do echo " $line" done echo # World-writable directories echo "World-writable directories:" find "$dir" -type d -perm -002 -ls 2>/dev/null | while read line; do echo " $line" done echo # Files with setuid echo "Setuid files:" find "$dir" -type f -perm -4000 -ls 2>/dev/null | while read line; do echo " $line" done echo # Files with setgid echo "Setgid files:" find "$dir" -type f -perm -2000 -ls 2>/dev/null | while read line; do echo " $line" done echo # Directories with sticky bit echo "Directories with sticky bit:" find "$dir" -type d -perm -1000 -ls 2>/dev/null | while read line; do echo " $line" done echo # Files without owner in passwd echo "Files with no owner:" find "$dir" -nouser -ls 2>/dev/null | while read line; do echo " $line" done echo # Files without group in group echo "Files with no group:" find "$dir" -nogroup -ls 2>/dev/null | while read line; do echo " $line" done } > "$report" echo "Audit report saved to: $report" cat "$report" } # Fix common permission issues fix_permissions() { local dir="$1" # Fix directory permissions find "$dir" -type d -exec chmod 755 {} \; # Fix file permissions find "$dir" -type f -exec chmod 644 {} \; # Fix executable scripts find "$dir" -name "*.sh" -type f -exec chmod 755 {} \; # Remove world-writable bits find "$dir" -type f -perm -002 -exec chmod o-w {} \; find "$dir" -type d -perm -002 -exec chmod o-w {} \; echo "✓ Permissions fixed in $dir" }

Permission Comparison Script

#!/bin/bash # Compare permissions between two files/directories compare_permissions() { local path1="$1" local path2="$2" echo "Comparing:" echo " $path1" echo " $path2" echo # Get permissions perm1=$(stat -c "%a %A" "$path1" 2>/dev/null) perm2=$(stat -c "%a %A" "$path2" 2>/dev/null) if [ $? -ne 0 ]; then echo "Error: Cannot stat one of the paths" return 1 fi echo "Permissions:" echo " $path1: $perm1" echo " $path2: $perm2" if [ "$perm1" = "$perm2" ]; then echo "✓ Permissions match" else echo "✗ Permissions differ" fi echo # Compare ownership owner1=$(stat -c "%U:%G" "$path1") owner2=$(stat -c "%U:%G" "$path2") echo "Ownership:" echo " $path1: $owner1" echo " $path2: $owner2" if [ "$owner1" = "$owner2" ]; then echo "✓ Ownership matches" else echo "✗ Ownership differs" fi } # Synchronize permissions from reference sync_permissions() { local reference="$1" local target="$2" # Get reference permissions and ownership perms=$(stat -c "%a" "$reference") owner=$(stat -c "%U" "$reference") group=$(stat -c "%G" "$reference") # Apply to target if [ -d "$target" ]; then find "$target" -type d -exec chmod "$perms" {} \; find "$target" -type f -exec chmod "$(stat -c "%a" "$reference")" {} \; else chmod "$perms" "$target" fi chown -R "$owner:$group" "$target" echo "✓ Permissions synced from $reference to $target" }

Permission Backup and Restore

#!/bin/bash # Backup permissions backup_permissions() { local dir="$1" local backup_file="${2:-perms_backup.txt}" find "$dir" -printf "%p %m %u %g\n" 2>/dev/null > "$backup_file" echo "Permissions backed up to: $backup_file" } # Restore permissions from backup restore_permissions() { local backup_file="$1" local dir="${2:-.}" if [ ! -f "$backup_file" ]; then echo "Error: Backup file not found" return 1 fi while read path perms user group; do # Check if file exists if [ -e "$path" ]; then chmod "$perms" "$path" 2>/dev/null chown "$user:$group" "$path" 2>/dev/null echo "Restored: $path" fi done < "$backup_file" echo "✓ Permissions restored" } # Create permission snapshot snapshot_permissions() { local dir="$1" local snapshot="/tmp/perms_snapshot_$(date +%Y%m%d_%H%M%S).txt" { echo "Permission Snapshot - $(date)" echo "Directory: $dir" echo "=================================" echo find "$dir" -exec stat -c "%n %a %u %g" {} \; 2>/dev/null | sort } > "$snapshot" echo "Snapshot saved: $snapshot" }

8. Permission Testing and Validation

Test Permission Functions

#!/bin/bash # Test if user has specific permissions test_permissions() { local file="$1" echo "Testing permissions for: $file" echo "==============================" # Read test if [ -r "$file" ]; then echo "✓ Read permission" else echo "✗ No read permission" fi # Write test if [ -w "$file" ]; then echo "✓ Write permission" else echo "✗ No write permission" fi # Execute test if [ -x "$file" ]; then echo "✓ Execute permission" else echo "✗ No execute permission" fi # Special bits if [ -u "$file" ]; then echo "✓ Setuid set" fi if [ -g "$file" ]; then echo "✓ Setgid set" fi if [ -k "$file" ]; then echo "✓ Sticky bit set" fi } # Validate permission requirements validate_permissions() { local file="$1" local required_perms="$2" current=$(stat -c "%a" "$file" 2>/dev/null) if [ "$current" = "$required_perms" ]; then echo "✓ Permissions OK: $file ($current)" return 0 else echo "✗ Permission mismatch: $file (have $current, need $required_perms)" return 1 fi } # Check secure permissions check_secure() { local file="$1" local issues=0 # World-writable check if [ "$(stat -c "%a" "$file" | cut -c3)" -eq 7 ] || \ [ "$(stat -c "%a" "$file" | cut -c3)" -eq 6 ]; then echo "⚠ World-writable: $file" issues=$((issues + 1)) fi # Group-writable check for sensitive files if [[ "$file" == *"ssh"* ]] || [[ "$file" == *"config"* ]]; then if [ "$(stat -c "%a" "$file" | cut -c2)" -eq 7 ] || \ [ "$(stat -c "%a" "$file" | cut -c2)" -eq 6 ]; then echo "⚠ Group-writable sensitive file: $file" issues=$((issues + 1)) fi fi # Owner check if [ "$(stat -c "%U" "$file")" != "$USER" ] && [ "$(stat -c "%U" "$file")" != "root" ]; then echo "⚠ Wrong owner: $file" issues=$((issues + 1)) fi return $issues }

9. Permission Best Practices

Security Guidelines

#!/bin/bash # Secure file creation secure_create() { local file="$1" # Set restrictive umask local old_umask=$(umask) umask 077 # Create file touch "$file" # Restore umask umask "$old_umask" echo "✓ Securely created: $file" } # Secure directory for web application secure_web_dir() { local dir="$1" # Create directories mkdir -p "$dir"/{public,private,logs,tmp} # Public web root chmod 755 "$dir/public" # Private files (config, includes) chmod 700 "$dir/private" # Logs - writable by web server chmod 770 "$dir/logs" chgrp www-data "$dir/logs" # Temp - writable by all, sticky bit chmod 1777 "$dir/tmp" echo "✓ Secure web directory created: $dir" } # Production deployment permissions deploy_permissions() { local app_dir="$1" local web_user="${2:-www-data}" # Set ownership chown -R "deploy:$web_user" "$app_dir" # Base permissions find "$app_dir" -type d -exec chmod 755 {} \; find "$app_dir" -type f -exec chmod 644 {} \; # Make executables find "$app_dir" -name "*.sh" -exec chmod 755 {} \; # Writable directories for dir in cache logs uploads tmp; do if [ -d "$app_dir/$dir" ]; then chmod 775 "$app_dir/$dir" chgrp "$web_user" "$app_dir/$dir" fi done echo "✓ Deployment permissions set" }

Permission Templates

#!/bin/bash # Common permission templates declare -A PERM_TEMPLATES=( ["private"]="700" ["private_group"]="750" ["shared"]="775" ["public"]="755" ["public_readonly"]="755" ["public_write"]="777" ["config"]="640" ["config_private"]="600" ["script"]="755" ["document"]="644" ["upload_dir"]="1777" ) apply_template() { local template="$1" local target="$2" if [ -z "${PERM_TEMPLATES[$template]}" ]; then echo "Unknown template: $template" return 1 fi perms="${PERM_TEMPLATES[$template]}" if [ -d "$target" ]; then chmod -R "$perms" "$target" else chmod "$perms" "$target" fi echo "✓ Applied template '$template' ($perms) to $target" } # Usage # apply_template "private" ~/.ssh # apply_template "shared" /projects/shared # apply_template "upload_dir" /tmp/uploads

10. Permission Troubleshooting

Common Permission Issues

#!/bin/bash # Diagnose permission issues diagnose_permission() { local path="$1" local user="${2:-$USER}" echo "Diagnosing permissions for: $path" echo "User: $user" echo "=================================" # Check if path exists if [ ! -e "$path" ]; then echo "✗ Path does not exist" return 1 fi # Show current permissions ls -ld "$path" # Check ownership owner=$(stat -c "%U" "$path") group=$(stat -c "%G" "$path") echo "Owner: $owner" echo "Group: $group" # Check user's group membership groups=$(id -Gn "$user") echo "User's groups: $groups" # Determine access if [ "$user" = "$owner" ]; then echo "✓ User owns the file" elif echo "$groups" | grep -q "$group"; then echo "✓ User is in the file's group" else echo "User is 'other' for this file" fi # Check specific permissions echo -n "Read access: " if [ -r "$path" ]; then echo "✓"; else echo "✗"; fi echo -n "Write access: " if [ -w "$path" ]; then echo "✓"; else echo "✗"; fi echo -n "Execute access: " if [ -x "$path" ]; then echo "✓"; else echo "✗"; fi } # Fix common permission problems fix_common_issues() { local dir="$1" # Fix home directory if [[ "$dir" == "/home/"* ]]; then chmod 755 "$dir" echo "✓ Fixed home directory permissions" fi # Fix SSH directory if [ -d "$dir/.ssh" ]; then chmod 700 "$dir/.ssh" chmod 600 "$dir/.ssh/id_rsa" 2>/dev/null chmod 644 "$dir/.ssh/id_rsa.pub" 2>/dev/null chmod 600 "$dir/.ssh/authorized_keys" 2>/dev/null echo "✓ Fixed SSH permissions" fi # Fix web directories if [[ "$dir" == *"public_html" ]] || [[ "$dir" == *"www"* ]]; then find "$dir" -type d -exec chmod 755 {} \; find "$dir" -type f -exec chmod 644 {} \; echo "✓ Fixed web directory permissions" fi }

Permission Recovery

#!/bin/bash # Emergency permission recovery emergency_recovery() { local dir="$1" local log="/tmp/permission_recovery_$(date +%s).log" { echo "Emergency Permission Recovery - $(date)" echo "========================================" echo "Directory: $dir" echo # Backup current permissions echo "Backing up current permissions..." find "$dir" -printf "%p %m %u %g\n" > "${log}.backup" # Reset to safe defaults echo "Resetting to safe defaults..." # Directories: 755 find "$dir" -type d -exec chmod 755 {} \; -print # Files: 644 find "$dir" -type f -exec chmod 644 {} \; -print # Executable scripts: 755 find "$dir" -name "*.sh" -type f -exec chmod 755 {} \; -print echo echo "Recovery complete. Backup saved to: ${log}.backup" } 2>&1 | tee "$log" echo "Recovery log saved to: $log" } # Restore from backup restore_from_backup() { local backup="$1" if [ ! -f "$backup" ]; then echo "Error: Backup file not found" return 1 fi while read -r path perms owner group; do if [ -e "$path" ]; then chmod "$perms" "$path" 2>/dev/null chown "$owner:$group" "$path" 2>/dev/null echo "Restored: $path" fi done < "$backup" echo "✓ Restore complete" }

11. Permission Monitoring

Monitor Permission Changes

#!/bin/bash # Watch for permission changes watch_permissions() { local watch_dir="$1" inotifywait -m -r --format '%w%f %e' "$watch_dir" 2>/dev/null | while read path event; do if [[ "$event" == *"ATTRIB"* ]]; then perms=$(stat -c "%a" "$path" 2>/dev/null) owner=$(stat -c "%U:%G" "$path" 2>/dev/null) echo "$(date '+%Y-%m-%d %H:%M:%S') - Permission change: $path ($perms) $owner" fi done } # Log permission changes to syslog log_permission_changes() { local dir="$1" # Create baseline find "$dir" -printf "%p %m %u %g\n" > "/tmp/perms_baseline.txt" # Monitor for changes while true; do find "$dir" -printf "%p %m %u %g\n" > "/tmp/perms_current.txt" diff "/tmp/perms_baseline.txt" "/tmp/perms_current.txt" | while read line; do if [[ "$line" == ">"* ]]; then logger -t perm_monitor "Permission changed: ${line:2}" fi done mv "/tmp/perms_current.txt" "/tmp/perms_baseline.txt" sleep 60 done }

12. Permission Command Reference

Quick Reference

# View permissions ls -l file stat file getfacl file # Change permissions (symbolic) chmod u+x file # Add execute for user chmod g-w file # Remove write from group chmod o=r file # Set others to read-only chmod a+x file # Add execute for all # Change permissions (numeric) chmod 755 file # rwxr-xr-x chmod 644 file # rw-r--r-- chmod 700 file # rwx------ chmod 600 file # rw------- # Change ownership chown user file # Change owner chown user:group file # Change both chgrp group file # Change group only chown -R user:group directory/ # Recursive # Special permissions chmod u+s file # Setuid chmod g+s file # Setgid chmod +t dir # Sticky bit # Default permissions umask # View current umask umask 022 # Set umask umask -S # View symbolic umask # ACLs getfacl file setfacl -m u:user:rwx file setfacl -b file # File attributes lsattr file chattr +i file

Permission Tables

# Numeric to Symbolic Conversion Table # 0 = --- # 1 = --x # 2 = -w- # 3 = -wx # 4 = r-- # 5 = r-x # 6 = rw- # 7 = rwx # Common Permission Combinations # 400 = r-------- # 600 = rw------- # 644 = rw-r--r-- # 654 = rw-r-xr-- # 664 = rw-rw-r-- # 700 = rwx------ # 744 = rwxr--r-- # 750 = rwxr-x--- # 755 = rwxr-xr-x # 777 = rwxrwxrwx # Directory Permissions # 755 = drwxr-xr-x (typical) # 750 = drwxr-x--- (group access) # 700 = drwx------ (private) # 2775 = drwxrwsr-x (with setgid) # 1777 = drwxrwxrwt (with sticky)

Conclusion

File permissions and ownership are fundamental to Unix/Linux security:

Key Takeaways

  1. Three permission classes: User (owner), Group, Others
  2. Three permission types: Read (r=4), Write (w=2), Execute (x=1)
  3. Special permissions: Setuid (4), Setgid (2), Sticky bit (1)
  4. Default permissions: Controlled by umask
  5. ACLs: Fine-grained permissions beyond standard POSIX
  6. File attributes: Additional security features with chattr

Best Practices Summary

ScenarioRecommended Permissions
Regular files644 (rw-r--r--)
Executable scripts755 (rwxr-xr-x)
Private files600 (rw-------)
Private directories700 (rwx------)
Shared directories775 (rwxrwxr-x)
SSH private keys600 (rw-------)
Web directories755 (rwxr-xr-x)
Upload directories1777 (rwxrwxrwt)
Configuration files640 (rw-r-----)

Security Guidelines

  1. Principle of least privilege: Give minimum permissions needed
  2. Regular audits: Check for world-writable files and setuid binaries
  3. Secure defaults: Use appropriate umask (022 for system, 077 for personal)
  4. Protect sensitive files: SSH keys, config files should be 600/700
  5. Use groups: Manage team access through group permissions
  6. Avoid 777: Never use full permissions unless absolutely necessary
  7. Monitor changes: Track permission changes on critical files
  8. Backup permissions: Save permission metadata with backups

Understanding and properly managing file permissions is essential for system security and multi-user environments. The concepts may seem complex at first, but they become intuitive with practice.

Complete Bash Exercises with Solutions

Practice Bash scripting with solved exercises to improve your command-line and scripting skills.
Link: https://macronepal.com/complete-bash-exercises-with-solutions/

Complete Guide to Bash Crontab Command

Learn how to schedule and automate tasks efficiently using the Bash crontab command.
Link: https://macronepal.com/complete-guide-to-bash-crontab-command-schedule-tasks/

Complete Guide to Bash Arrays

Understand how to create, manage, and use arrays in Bash scripting.
Link: https://macronepal.com/complete-guide-to-bash-arrays/

Bash Quiz: Test Your Knowledge

Test your Bash scripting knowledge with quizzes and practical questions.
Link: https://macronepal.com/bash-quiz-test-your-knowledge/

Complete Guide to Bash Functions

Learn how to write reusable Bash functions for cleaner and efficient scripts.
Link: https://macronepal.com/complete-guide-to-bash-functions/

Complete Guide to Bash Loops

Master loops in Bash for repetitive tasks and automation.
Link: https://macronepal.com/complete-guide-to-bash-loops/

Complete Guide to Bash If-Else Statements

Learn decision-making in Bash using conditional statements.
Link: https://macronepal.com/complete-guide-to-bash-ifelse-statements/

Complete Guide to Bash Operators

Explore arithmetic, logical, and comparison operators in Bash.
Link: https://macronepal.com/complete-guide-to-bash-operators/

Complete Guide to Bash Data Types

Understand variables and different data types used in Bash scripting.
Link: https://macronepal.com/complete-guide-to-bash-data-types/

Complete Guide to Bash Variables

Learn how to declare, assign, and use variables in Bash scripts.
Link: https://macronepal.com/complete-guide-to-bash-variables/

Complete Guide to Bash Scripting

A complete introduction to writing Bash scripts for automation.
Link: https://macronepal.com/complete-guide-to-bash-scripting/

Complete Guide to Basic Bash Syntax

Learn the fundamental syntax needed to write Bash commands and scripts.
Link: https://macronepal.com/complete-guide-to-basic-bash-syntax/

Complete Guide to Bash Chgrp Command

Learn how to change group ownership of files and directories.
Link: https://macronepal.com/complete-guide-to-bash-chgrp-command-change-group-ownership-2/

Complete Guide to Bash Chgrp Command (Alternate)

Another detailed explanation of Bash group ownership management.
Link: https://macronepal.com/complete-guide-to-bash-chgrp-command-change-group-ownership/

Complete Guide to Bash File Permissions and Ownership

Understand Linux file permissions and ownership management.
Link: https://macronepal.com/complete-guide-to-bash-file-permissions-and-ownership/

Complete Guide to Bash Chmod Command

Learn how to modify file permissions using chmod.
Link: https://macronepal.com/complete-guide-to-bash-chmod-command-change-file-permissions/

Complete Guide to Bash Chown Command

Change file ownership using the Bash chown command.
Link: https://macronepal.com/complete-guide-to-bash-chown-command-change-file-ownership/

Complete Guide to Bash SCP Command

Securely transfer files between systems using SCP.
Link: https://macronepal.com/complete-guide-to-bash-scp-command-secure-copy/

Complete Guide to Bash SSH Command

Learn secure remote access and server management using SSH.
Link: https://macronepal.com/complete-guide-to-bash-ssh-command/

Bash Wget Command Complete Guide

Download files from the internet using the wget command.
Link: https://macronepal.com/bash-wget-command-complete-guide-to-non-interactive-network-downloader/

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper