Skip to content
File Permissions Advanced — chmod, chown, ACLs, setuid, Sticky Bit, umask

File Permissions Advanced — chmod, chown, ACLs, setuid, Sticky Bit, umask

DodaTech Updated Jun 20, 2026 10 min read

Linux file permissions control who can read, write, and execute files and directories. Beyond the basic rwx model, Linux supports Access Control Lists (ACLs), special permission bits (setuid, setgid, sticky), and default permission masks (umask). This guide covers everything you need for production multi-user systems.

What You’ll Learn

You’ll understand the full Linux permission model — symbolic and numeric modes, recursive ownership changes, ACL-based fine-grained access control, the security implications of setuid/setgid binaries, how the sticky bit protects shared directories, and how umask prevents accidentally exposed files. You’ll also learn how Durga Antivirus Pro uses restricted permissions and ACLs to isolate threat analysis sandboxes.

Why File Permissions Matter

Every security breach investigation starts with file permissions. A world-readable private SSH key, a setuid shell script, or a directory with 777 permissions are common attack vectors. In multi-user systems — like DodaTech’s shared build servers — misconfigured permissions let users read each other’s data. Mastering permissions is the foundation of Linux security.

Learning Path

    flowchart LR
  A[Essential Commands] --> B[Networking Commands]
  B --> C[File Permissions<br/>You are here]
  C --> D[Process Management]
  D --> E[Security Hardening]
  style C fill:#f90,color:#fff
  

Understanding File Permissions

Every file and directory in Linux has three permission sets:

SetApplies toExample
User (u)The file’s ownerrwx
Group (g)Members of the file’s groupr-x
Others (o)Everyone elser--

Each set has three permissions: r (read), w (write), x (execute).

Numeric (Octal) Mode

Permissions are represented as octal numbers:

r = 4, w = 2, x = 1
rwx = 4+2+1 = 7
r-x = 4+0+1 = 5
r-- = 4+0+0 = 4
--- = 0

Common modes:

  • 755 — rwxr-xr-x (owner full, group/others read+execute)
  • 644 — rw-r–r– (owner read/write, others read-only)
  • 700 — rwx—— (owner only)
  • 600 — rw——- (owner read/write)
  • 777 — rwxrwxrwx (everyone full access — avoid this)

chmod — Changing Permissions

# Symbolic mode
chmod u+x script.sh        # Add execute for owner
chmod g-w file.txt         # Remove write for group
chmod o+r file.txt         # Add read for others
chmod a+rx script.sh       # Add read+execute for all
chmod u=rwx,g=rx,o= file   # Set precisely

# Numeric mode (most common)
chmod 755 script.sh
chmod 644 config.json
chmod 600 .ssh/id_rsa      # Private key — must be 600!
chmod 700 ~/.ssh           # SSH directory

# Recursive (use with caution)
chmod -R 755 /path/to/dir  # All files get execute — wrong!
find /path -type f -exec chmod 644 {} \;    # Files
find /path -type d -exec chmod 755 {} \;    # Directories

Expected output for ls -l after chmod 600 private.key:

-rw------- 1 alice devops 1675 Jun 20 10:00 private.key

chown and chgrp — Ownership

# Change owner
chown alice file.txt

# Change owner and group
chown alice:devops file.txt

# Change group only
chgrp devops file.txt

# Recursive with different users and groups
chown -R alice:devops /projects/myapp

# Use reference file
chown --reference=template.txt target.txt

umask — Default Permission Mask

Umask defines the default permissions for newly created files and directories. It subtracts from the maximum permissions (666 for files, 777 for directories).

# Show current umask
umask

# The math: default_perms = max_perms - umask
# umask 022: files get 644 (666-022), dirs get 755 (777-022)
# umask 077: files get 600, dirs get 700
# umask 002: files get 664, dirs get 775

# Set umask (temporary, for current shell)
umask 027

# Set permanently (add to ~/.bashrc or /etc/profile)
echo "umask 027" >> ~/.bashrc

Umask comparison:

umaskFile PermsDirectory PermsUse Case
022644 (rw-r–r–)755 (rwxr-xr-x)Default — public readable
027640 (rw-r—–)750 (rwxr-x—)Team — group readable
077600 (rw——-)700 (rwx——)Private — owner only
002664 (rw-rw-r–)775 (rwxrwxr-x)Collaborative — group writable

Special Permission Bits

setuid (SUID) — chmod u+s

When set on an executable, the process runs with the file owner’s privileges, not the user who ran it. This is how passwd lets regular users edit /etc/shadow.

# Set SUID
chmod u+s /usr/bin/myapp
chmod 4755 /usr/bin/myapp     # Numeric: 4 = SUID

# Find SUID binaries (potential security risk)
find / -perm -4000 -type f 2>/dev/null

# Remove SUID
chmod u-s /usr/bin/myapp

Security warning: Never set SUID on shell scripts — they can be exploited via shell injection. SUID binaries must be carefully audited.

setgid (SGID) — chmod g+s

On executables: runs with the group of the file. On directories: new files inherit the directory’s group, not the creator’s primary group.

# Set SGID on directory — new files inherit group
chmod g+s /shared/project
chmod 2755 /shared/project    # Numeric: 2 = SGID

# Verify — directory shows 's' in group execute position
ls -ld /shared/project
# drwxr-sr-x 2 alice devops 4096 Jun 20 10:00 /shared/project

Sticky Bit — chmod o+t

Restricts deletion: only the owner of a file (or root) can delete or rename it, even if the directory is world-writable. Essential for /tmp.

# Set sticky bit
chmod o+t /shared/temp
chmod 1777 /shared/temp       # Numeric: 1 = sticky

# Verify — shows 't' in others execute position
ls -ld /shared/temp
# drwxrwxrwt 2 root root 4096 Jun 20 10:00 /shared/temp

# Common sticky bit directories
ls -ld /tmp /var/tmp
# drwxrwxrwt 10 root root 4096 Jun 20 10:00 /tmp

Access Control Lists (ACLs)

ACLs provide fine-grained permissions beyond the traditional owner/group/others model. You can grant permissions to specific users or groups.

# Install ACL tools
sudo apt install acl         # Debian/Ubuntu
sudo yum install acl         # RHEL/CentOS

# Check if a filesystem supports ACLs
mount | grep acl

Managing ACLs

# View ACLs on a file
getfacl file.txt

# Grant read/write to a specific user
setfacl -m u:bob:rw file.txt

# Grant read/execute to a specific group
setfacl -m g:qa:rx file.txt

# Remove a specific user entry
setfacl -x u:bob file.txt

# Remove all ACL entries (revert to basic)
setfacl -b file.txt

# Recursive with default ACLs (new files inherit)
setfacl -R -m g:devops:rx /shared/project
setfacl -R -d -m g:devops:rx /shared/project   # Default ACL

Expected output for getfacl /shared/project/data.txt:

# file: data.txt
# owner: alice
# group: devops
user::rw-
user:bob:rw-          # Bob has explicit read/write
group::r-x             # devops group has read/execute
mask::rwx              # Maximum permissions ACL can grant
other::---             # No access for others
default:user::rwx      # Default ACLs inherited by new files
default:group::r-x

ACL Best Practices

  1. Use ACLs sparingly — Too many ACL entries make auditing difficult
  2. Prefer groups over user ACLs — Adding users to a group is cleaner than per-user ACLs
  3. Understand the mask — The ACL mask limits the maximum permissions ACL entries can grant
  4. Document ACLs — ACLs aren’t visible in ls -l (shows +), so document why they exist

Permission Inheritance and Best Practices

Directory vs File Permissions

PermissionFile EffectDirectory Effect
r (read)Read contentList entries
w (write)Modify contentCreate/delete entries
x (execute)Run as programAccess (cd into)

Security Checklist

  1. SSH keys must be 600chmod 600 ~/.ssh/id_rsa
  2. Directories should not be world-writable — Avoid 777
  3. Remove SUID from unused binariesfind / -perm -4000 -type f
  4. Set restrictive umask (027) on servers
  5. Use groups, not individual user ACLs
  6. Regularly audit permission changesfind /etc -mtime -7 -ls

Common Permission Errors

1. “Permission Denied” on a Readable File

The directory containing the file must have execute (x) permission. Without it, you can’t traverse the directory to reach the file.

2. chmod -R 755 on All Files

Applying chmod -R 755 sets execute on every file, including text files. This is unnecessary and a security risk. Use find to separate files and directories.

3. SSH Key with Wrong Permissions

Permissions 0644 for '/home/alice/.ssh/id_rsa' are too open.

SSH requires private keys to be readable only by the owner (600 or 400).

4. SUID on Shell Scripts

Modern Linux kernels ignore SUID on interpreted scripts (starting with #!) for security reasons. Use a compiled wrapper or capabilities instead.

5. umask Forgotten in Scripts

Scripts that create temporary files inherit the umask from the calling shell. Always set umask 077 at the start of scripts that handle sensitive data.

6. ACL Mask Limiting Permissions

If ACLs aren’t working, check the mask. setfacl -m m::rwx file updates the mask to allow full ACL permissions.

7. Sticky Bit on Non-Shared Directories

Applying the sticky bit on a private directory provides no benefit and can confuse users who expect group collaboration.

Practice Questions

1. What do permissions 4755 mean? Setuid (4) + owner rwx (7) + group r-x (5) + others r-x (5). The binary runs with the file owner’s privileges.

2. How do you allow two specific users to write to a directory without giving all group members write access? Use ACLs: setfacl -m u:alice:rwx,d:u:alice:rwx /shared/dir and similarly for bob. The d: prefix sets default ACLs for new files.

3. What does the sticky bit do on /tmp? It prevents users from deleting each other’s files. Without it, anyone could rm /tmp/alice-temp-file since /tmp is world-writable.

4. What is the result of umask 027 on a new file? 666 - 027 = 640 (rw-r—–). New files are readable by owner and group, writable by owner, with no access for others.

5. Challenge: A shared project directory has users from two teams who need different access levels — Team A needs read/write, Team B needs read-only. New files should automatically get the right permissions. Design the solution. Answer: Create two groups (team-a, team-b). Set SGID on the directory. Use default ACLs: setfacl -d -m g:team-a:rwx /project and setfacl -d -m g:team-b:rx /project. Set umask to 007. New files inherit group and ACLs automatically.

Mini Project: Permission Audit Script

Create a script that scans a directory for permission security issues:

#!/bin/bash
# perm_audit.sh — Scan for permission security issues
# Usage: ./perm_audit.sh /path/to/scan

SCAN_DIR="${1:-.}"
REPORT_FILE="perm_audit_$(date +%Y%m%d_%H%M%S).log"

echo "=== Permission Security Audit ===" | tee "$REPORT_FILE"
echo "Scan target: $SCAN_DIR" | tee -a "$REPORT_FILE"
echo "Report: $REPORT_FILE"
echo ""

# World-writable files
echo "--- World-Writable Files ---" | tee -a "$REPORT_FILE"
find "$SCAN_DIR" -type f -perm -o+w -ls 2>/dev/null >> "$REPORT_FILE"

# World-writable directories
echo "--- World-Writable Directories ---" | tee -a "$REPORT_FILE"
find "$SCAN_DIR" -type d -perm -o+w -ls 2>/dev/null >> "$REPORT_FILE"

# SUID binaries
echo "--- SUID Binaries ---" | tee -a "$REPORT_FILE"
find "$SCAN_DIR" -type f -perm -4000 -ls 2>/dev/null >> "$REPORT_FILE"

# Files with no permissions for owner
echo "--- Owner Without Access ---" | tee -a "$REPORT_FILE"
find "$SCAN_DIR" ! -perm -u+r -ls 2>/dev/null >> "$REPORT_FILE"

# Summary
echo "" | tee -a "$REPORT_FILE"
echo "=== Summary ===" | tee -a "$REPORT_FILE"
echo "World-writable files: $(find "$SCAN_DIR" -type f -perm -o+w 2>/dev/null | wc -l)" | tee -a "$REPORT_FILE"
echo "World-writable dirs: $(find "$SCAN_DIR" -type d -perm -o+w 2>/dev/null | wc -l)" | tee -a "$REPORT_FILE"
echo "SUID binaries: $(find "$SCAN_DIR" -type f -perm -4000 2>/dev/null | wc -l)" | tee -a "$REPORT_FILE"

Expected output:

=== Permission Security Audit ===
Scan target: /home/alice
Report: perm_audit_20260620_100000.log
--- World-Writable Files ---
--- World-Writable Directories ---
--- SUID Binaries ---
--- Owner Without Access ---
=== Summary ===
World-writable files: 3
World-writable dirs: 0
SUID binaries: 1

This script is modeled after the permission checks Durga Antivirus Pro runs during its security scan to identify files with insecure permissions that malware might exploit.

FAQ

What’s the difference between chmod 777 and chmod a+rwx?
They’re identical — both give full access to everyone. Never use either in production. The minimum permission principle applies: grant only what’s needed.
How do I make a file readable only by its owner?
chmod 600 filename (or chmod u=rw,go=). The owner can read and write; everyone else has no access.
Can ACLs replace traditional permissions?
ACLs extend traditional permissions. Basic permissions still apply as the foundation. ACLs add per-user and per-group entries on top.
What does the + at the end of permissions mean in ls -l?
It means the file has extended ACL entries. Run getfacl filename to see them.
Why does /tmp have 777 permissions?
Because any program needs to create temporary files there, and the sticky bit prevents users from deleting each other’s files.
How do I prevent users from seeing each other’s home directories?
Set chmod 750 /home/* to make each home directory group-readable only. Or set chmod 700 /home/* for complete privacy.

What’s Next

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-20.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro