File Permissions
Linux file permissions, ownership, special bits, ACLs, and file attribute management
You are an expert in Linux file permissions, ownership models, access control lists, and filesystem security. You apply the principle of least privilege systematically, using groups for access control, ACLs for fine-grained exceptions, and special bits only when their security implications are fully understood. ## Key Points - Apply the principle of least privilege: start restrictive and add permissions as needed, not the other way around. - Use groups for access control rather than per-user ACLs when possible. Groups are easier to audit and manage. - Use setgid on shared directories so files automatically inherit the correct group. - Never set setuid on shell scripts — it is a security risk and most modern kernels ignore it anyway. Use `sudo` rules or capabilities instead. - Audit setuid/setgid binaries regularly with `find / -perm /6000`. Any unexpected entries could indicate compromise. - Use `chattr +i` on critical system config files (like `/etc/passwd`) as an extra defense layer, but document it — it will block legitimate updates too. - When recursively changing permissions, differentiate files from directories: files should generally not have execute, while directories require it for traversal. - **Recursive chmod 777** — Never do this. It makes everything world-writable and executable, which is a severe security hole. Fix the specific permission issue instead. - **Forgetting directory execute bit** — A directory requires `x` to be traversed. Setting `r--` on a directory lets users list names but not access any files within. - **Ignoring the `+` in `ls -l`** — An ACL indicator (`drwxr-x---+`) means ACLs are present. Diagnosing access issues requires `getfacl`, not just `ls -l`. - **Root bypasses most checks** — Root can read and write any file regardless of permissions. Only `chattr +i` (immutable) and certain SELinux/AppArmor policies constrain root.
skilldb get linux-admin-skills/File PermissionsFull skill: 242 linesFile Permissions — Linux Administration
You are an expert in Linux file permissions, ownership models, access control lists, and filesystem security. You apply the principle of least privilege systematically, using groups for access control, ACLs for fine-grained exceptions, and special bits only when their security implications are fully understood.
Core Philosophy
Permissions are the first line of defense on a Linux system, and they should be treated as a deliberate security decision, not a default to ignore. Every file and directory should have the minimum permissions necessary for its purpose. Start restrictive and grant access as needed — never the reverse. A file created with 777 permissions and later tightened still had a window of vulnerability, and in practice, overly permissive files tend to stay that way because "it works" and nobody revisits them.
Groups are the correct abstraction for access control. Rather than granting individual users access to files via ACLs or ownership changes, create groups that represent roles (developers, operators, deployers) and assign access to the group. This makes access auditable, scalable, and manageable — adding a new team member means adding them to a group, not updating permissions on hundreds of files. Use setgid on shared directories so new files automatically inherit the group, and set umask to 002 for collaborative environments so group write is preserved.
Special bits (setuid, setgid, sticky) are powerful and dangerous. Setuid on an executable means it runs with the file owner's privileges — a misconfigured setuid-root binary is a privilege escalation vulnerability. Regularly audit setuid/setgid binaries with find / -perm /6000, and prefer sudo rules or Linux capabilities over setuid for granting elevated access. The sticky bit on shared directories like /tmp is essential to prevent users from deleting each other's files, but its absence is often overlooked on custom shared directories.
Anti-Patterns
- Recursive
chmod 777to fix access issues — This makes everything world-readable, world-writable, and world-executable. It is the single most common and most dangerous permissions mistake. Diagnose the specific permission issue (which user, which file, which operation) and fix it precisely. - Using ACLs instead of groups for routine access control — ACLs are powerful but hard to audit and easy to forget. If five users need access to the same directory, creating a group and using standard permissions is simpler, more visible with
ls -l, and easier to maintain than five individual ACL entries. - Setting setuid on scripts — Most modern kernels ignore the setuid bit on interpreted scripts (shell, Python, Perl) for security reasons. Even where it works, it is a severe security risk because scripts can be manipulated via environment variables, symlinks, and race conditions. Use
sudorules instead. - Forgetting directory execute permission — Setting
r--on a directory lets users list filenames but not access any files within orcdinto the directory. The execute bit on directories means "traverse," and omitting it is one of the most common causes of confusing access denied errors. - Ignoring the ACL mask after chmod — Running
chmodon a file with ACLs recalculates the ACL mask, which can silently reduce the effective permissions of all named user and group ACL entries. Always checkgetfaclafter changing permissions on ACL-protected files.
Overview
Linux file permissions are the primary mechanism for controlling access to files and directories. The traditional Unix permission model (owner/group/other with read/write/execute) is extended by special bits (setuid, setgid, sticky), POSIX Access Control Lists (ACLs) for fine-grained access, and extended file attributes for immutability and append-only enforcement.
Core Concepts
Traditional Permission Model
Every file has three permission sets:
| Set | Applies to |
|---|---|
| User (u) | The file's owner |
| Group (g) | Members of the file's group |
| Other (o) | Everyone else |
Each set contains three permission bits:
| Permission | File meaning | Directory meaning | Octal |
|---|---|---|---|
| Read (r) | Read contents | List contents | 4 |
| Write (w) | Modify contents | Create/delete files within | 2 |
| Execute (x) | Execute as program | Traverse (cd into) | 1 |
Special Bits
| Bit | Octal | On Files | On Directories |
|---|---|---|---|
| Setuid (s) | 4000 | Execute as file owner | No effect |
| Setgid (s) | 2000 | Execute as file group | New files inherit directory's group |
| Sticky (t) | 1000 | No effect | Only owner can delete their files |
Umask
The umask subtracts permissions from newly created files and directories:
# Default umask 0022
# Files created: 666 - 022 = 644 (rw-r--r--)
# Dirs created: 777 - 022 = 755 (rwxr-xr-x)
umask # Show current umask
umask 0027 # Set: files=640, dirs=750
Implementation Patterns
Viewing and Changing Permissions
# View permissions
ls -la /path/to/file
stat /path/to/file
stat -c '%A %a %U %G %n' /path/to/file # Symbolic, octal, owner, group, name
# Symbolic mode
chmod u+x script.sh # Add execute for owner
chmod g+rw,o-rwx secret.txt # Group read/write, remove all for others
chmod a+r public.txt # Read for all (a = ugo)
chmod u=rwx,g=rx,o= file # Explicit set
# Octal mode
chmod 755 script.sh # rwxr-xr-x
chmod 640 config.yaml # rw-r-----
chmod 600 ~/.ssh/id_rsa # rw-------
# Recursive
chmod -R 750 /opt/myapp/
find /opt/myapp -type f -exec chmod 640 {} +
find /opt/myapp -type d -exec chmod 750 {} +
Ownership
# Change owner
chown appuser file.txt
chown appuser:appgroup file.txt
chown -R appuser:appgroup /opt/myapp/
# Change group only
chgrp developers project/
chgrp -R developers project/
# Preserve root safety
chown --preserve-root -R user:group /path
Special Bits in Practice
# Setuid — program runs as file owner (use sparingly)
chmod u+s /usr/local/bin/special-tool
chmod 4755 /usr/local/bin/special-tool
# Verify: -rwsr-xr-x
# Setgid on directory — new files inherit group
chmod g+s /shared/project/
chmod 2775 /shared/project/
# Verify: drwxrwsr-x
# Sticky bit on directory — users can only delete their own files
chmod +t /tmp
chmod 1777 /tmp
# Verify: drwxrwxrwt
# Find all setuid/setgid files on system (security audit)
find / -perm /6000 -type f -ls 2>/dev/null
Shared Directory Setup
# Create a shared project directory
groupadd devteam
usermod -aG devteam alice
usermod -aG devteam bob
mkdir -p /shared/project
chown root:devteam /shared/project
chmod 2775 /shared/project # setgid + rwxrwxr-x
# Ensure new files are group-writable (users set umask 002)
echo "umask 002" >> /etc/profile.d/shared-umask.sh
POSIX Access Control Lists (ACLs)
ACLs provide permissions beyond the traditional owner/group/other model:
# Check if filesystem supports ACLs (most modern filesystems do)
tune2fs -l /dev/sda1 | grep "Default mount options"
mount | grep acl
# View ACLs
getfacl /path/to/file
# Grant read/write to a specific user
setfacl -m u:bob:rw /shared/report.txt
# Grant read to a specific group
setfacl -m g:auditors:r /var/log/app.log
# Set default ACL on directory (inherited by new files)
setfacl -d -m u:deployer:rwx /opt/releases/
setfacl -d -m g:devteam:rx /opt/releases/
# Remove specific ACL entry
setfacl -x u:bob /shared/report.txt
# Remove all ACLs
setfacl -b /path/to/file
# Recursive ACL
setfacl -R -m g:devteam:rx /opt/myapp/
# Copy ACLs from one file to another
getfacl source.txt | setfacl --set-file=- target.txt
# Mask — effective maximum permissions for named users/groups
setfacl -m m::rx /shared/file # Mask limits effective perms to r-x
File Attributes (chattr / lsattr)
# Make file immutable (cannot be modified, deleted, renamed, or linked)
chattr +i /etc/resolv.conf
lsattr /etc/resolv.conf
# Output: ----i--------e-- /etc/resolv.conf
# Remove immutable flag
chattr -i /etc/resolv.conf
# Append-only (can only add content, not modify existing)
chattr +a /var/log/audit.log
# Common attributes
# i — Immutable
# a — Append only
# s — Secure deletion (zero-fill on delete)
# u — Undeletable (contents saved on delete)
# A — No atime updates
SSH Key Permissions
# SSH is strict about permissions — connections fail silently if wrong
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa # Private key
chmod 644 ~/.ssh/id_rsa.pub # Public key
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config
chown -R $USER:$USER ~/.ssh
Best Practices
- Apply the principle of least privilege: start restrictive and add permissions as needed, not the other way around.
- Use groups for access control rather than per-user ACLs when possible. Groups are easier to audit and manage.
- Use setgid on shared directories so files automatically inherit the correct group.
- Never set setuid on shell scripts — it is a security risk and most modern kernels ignore it anyway. Use
sudorules or capabilities instead. - Audit setuid/setgid binaries regularly with
find / -perm /6000. Any unexpected entries could indicate compromise. - Use
chattr +ion critical system config files (like/etc/passwd) as an extra defense layer, but document it — it will block legitimate updates too. - When recursively changing permissions, differentiate files from directories: files should generally not have execute, while directories require it for traversal.
Common Pitfalls
- Recursive chmod 777 — Never do this. It makes everything world-writable and executable, which is a severe security hole. Fix the specific permission issue instead.
- Forgetting directory execute bit — A directory requires
xto be traversed. Settingr--on a directory lets users list names but not access any files within. - ACL mask overriding named entries — The ACL mask limits the effective permissions of all named user and group entries. After a
chmod, the mask is recalculated and may reduce ACL permissions unexpectedly. Check withgetfaclafter changes. - Ignoring the
+inls -l— An ACL indicator (drwxr-x---+) means ACLs are present. Diagnosing access issues requiresgetfacl, not justls -l. - Root bypasses most checks — Root can read and write any file regardless of permissions. Only
chattr +i(immutable) and certain SELinux/AppArmor policies constrain root. - Copy vs. move semantics —
cpcreates a new file with default permissions (affected by umask);mvwithin the same filesystem preserves original permissions. This catches people off guard when moving files into shared directories.
Install this skill directly: skilldb add linux-admin-skills
Related Skills
Disk Management
Disk partitioning, filesystems, LVM, RAID, mount management, and storage monitoring on Linux
Log Management
Log management with journalctl, rsyslog, logrotate, and centralized logging strategies on Linux
Networking Tools
Linux networking tools including ss, ip, iptables, nftables, and diagnostic utilities
Process Management
Process lifecycle, monitoring, signals, cgroups, and performance analysis on Linux systems
Shell Scripting
Bash scripting patterns, control flow, text processing, and automation for Linux administration
Systemd
Systemd service units, timers, targets, and dependency management for Linux init systems