env.dev

Linux File Permissions: chmod, chown, umask & ACLs

Linux file permissions reference: chmod octal/symbolic, chown, umask, SUID/SGID/sticky bits, POSIX ACLs (setfacl/getfacl), and Linux capabilities.

Last updated:

Linux file permissions control who can read, write, and execute files and directories. Every file has an owner, a group, and a set of permission bits. Understanding chmod, chown, umask, and special bits (SUID, SGID, sticky) is fundamental to Linux system administration and application security — see the Linux cheat sheet for the broader command reference.

How Do Linux Permissions Work?

Each file has three permission groups — owner (u), group (g), and others (o) — and three permission types — read (r), write (w), and execute (x). The ls -l command displays them as a 10-character string.

Reading permission strings
-rwxr-xr-- 1 alice devs 4096 Apr 12 10:00 deploy.sh
│└┬┘└┬┘└┬┘
│ │  │  └── others:  r-- (read only)
│ │  └───── group:   r-x (read + execute)
│ └──────── owner:   rwx (read + write + execute)
└────────── file type: - (regular file), d (directory), l (symlink)

Permission values:
  r (read)    = 4
  w (write)   = 2
  x (execute) = 1

Octal sum per group:
  rwx = 4+2+1 = 7
  r-x = 4+0+1 = 5
  r-- = 4+0+0 = 4
  → 754 in octal notation

How Do You Use chmod?

chmod changes file permissions using either octal notation (numeric) or symbolic notation (letters). Octal is more concise; symbolic is more readable for targeted changes.

chmod with octal notation
# Common octal permission values
chmod 755 script.sh    # rwxr-xr-x — executable by everyone, writable by owner
chmod 644 config.yaml  # rw-r--r-- — readable by everyone, writable by owner
chmod 600 id_ed25519   # rw------- — owner only (SSH private keys)
chmod 700 .ssh/        # rwx------ — owner only (SSH directory)
chmod 666 shared.txt   # rw-rw-rw- — readable/writable by everyone (rarely correct)
chmod 400 secrets.env  # r-------- — read-only by owner

# Recursive — apply to all files and directories
chmod -R 755 /var/www/html/

Strict chmod 600 on private keys is mandatory — OpenSSH refuses to load a key that is group- or world-readable. The SSH keys guide covers the full ~/.ssh permission map.

chmod with symbolic notation
# Symbolic format: [ugoa][+-=][rwxXsst]
# u=owner, g=group, o=others, a=all

# Add execute permission for the owner
chmod u+x deploy.sh

# Remove write permission from group and others
chmod go-w config.yaml

# Set exact permissions — owner rw, group r, others nothing
chmod u=rw,g=r,o= secret.conf

# Add execute only to directories (capital X)
chmod -R a+X /var/www/    # Adds execute to dirs but not files

# Make a file immutable to group write
chmod g-w important.log

# Multiple operations in one command
chmod u+rwx,g+rx,o-rwx deploy.sh

How Do You Change Ownership with chown?

chown changes the owner and/or group of a file. Only root can change the owner; regular users can change the group to one they belong to.

chown examples
# Change owner
sudo chown alice deploy.sh

# Change owner and group
sudo chown alice:devs deploy.sh

# Change group only (note the colon)
sudo chown :devs deploy.sh

# Alternative: change group with chgrp
sudo chgrp devs deploy.sh

# Recursive — change ownership of all contents
sudo chown -R www-data:www-data /var/www/html/

# Common pattern: set web server ownership
sudo chown -R nginx:nginx /usr/share/nginx/html/

What Is umask and How Does It Work?

umask sets the default permission mask for newly created files and directories. It subtracts permissions from the maximum defaults (666 for files, 777 for directories).

umask explained
# View current umask
umask         # e.g., 0022
umask -S      # symbolic: u=rwx,g=rx,o=rx

# How umask works:
#   Files:       666 - 022 = 644 (rw-r--r--)
#   Directories: 777 - 022 = 755 (rwxr-xr-x)

# Common umask values
umask 022   # Default — files 644, dirs 755 (readable by all)
umask 027   # Restrictive — files 640, dirs 750 (no access for others)
umask 077   # Private — files 600, dirs 700 (owner only)

# Set in shell profile (~/.bashrc or ~/.zshrc) for persistence
echo 'umask 027' >> ~/.bashrc

# Temporary umask for a single command
(umask 077 && touch secret.key)  # Created with 600 permissions

What Are SUID, SGID, and Sticky Bit?

Special permission bits modify how files and directories behave beyond the standard read/write/execute model.

BitOctalOn FilesOn Directories
SUID4000Runs as file owner (e.g., passwd runs as root)No effect
SGID2000Runs as file groupNew files inherit directory's group
Sticky1000No effect (modern Linux)Only file owner can delete their files
Special permission bits
# SUID — the 's' in owner execute position
chmod u+s /usr/bin/passwd
ls -l /usr/bin/passwd
# -rwsr-xr-x  ← 's' means SUID is set

# SGID on a directory — new files inherit group
chmod g+s /shared/projects/
ls -ld /shared/projects/
# drwxrwsr-x  ← 's' in group execute position

# Sticky bit — commonly set on /tmp
chmod +t /tmp/
ls -ld /tmp/
# drwxrwxrwt  ← 't' in others execute position

# Using octal — prepend the special bit
chmod 4755 program       # SUID + rwxr-xr-x
chmod 2775 shared-dir/   # SGID + rwxrwxr-x
chmod 1777 /tmp/         # Sticky + rwxrwxrwx

# Find all SUID files on the system (security audit)
find / -perm -4000 -type f 2>/dev/null

What are Linux capabilities (and how do they replace SUID)?

Capabilities split the all-or-nothing power of root into ~40 independent privileges. Instead of running a service as root or marking the binary SUID, grant only the one capability it needs. Binding a non-root web server to port 80 used to require SUID or a privileged user — with cap_net_bind_service the binary keeps every other restriction.

getcap, setcap, and capsh
# Inspect capabilities on a binary
getcap /usr/bin/ping
# /usr/bin/ping cap_net_raw=ep

# Let a non-root binary bind to ports < 1024
sudo setcap cap_net_bind_service=+ep /usr/bin/myapp

# Drop all capabilities from a binary
sudo setcap -r /usr/bin/myapp

# Show the current shell's capability set
capsh --print

# Find every file with capabilities set (audit)
sudo getcap -r / 2>/dev/null
CapabilityWhat it grants
CAP_NET_BIND_SERVICEBind sockets to TCP/UDP ports below 1024
CAP_SYS_ADMINThe "kitchen sink" — mount, swapon, namespaces. Avoid; usually too broad.
CAP_DAC_OVERRIDEBypass file read/write/execute permission checks
CAP_CHOWNMake arbitrary changes to file UIDs and GIDs

How do you make a file immutable with chattr?

Beyond the standard mode bits, ext4/XFS/Btrfs expose extended attributes via chattr. The two most useful are +i (immutable — even root cannot delete or modify the file without clearing the bit first) and +a (append-only — useful for log files an attacker should not be able to truncate).

chattr and lsattr
# Make a file immutable — no rename, delete, or write (even by root)
sudo chattr +i /etc/resolv.conf

# Inspect attributes
lsattr /etc/resolv.conf
# ----i--------e------- /etc/resolv.conf

# Append-only — cannot truncate or overwrite, only append
sudo chattr +a /var/log/audit.log

# Remove the immutable / append-only bit
sudo chattr -i /etc/resolv.conf
sudo chattr -a /var/log/audit.log

How Do ACLs Extend Standard Permissions?

POSIX Access Control Lists (ACLs) let you grant permissions to specific users or groups beyond the single owner/group model. They are essential when multiple teams need different access levels to the same directory.

ACL management with getfacl and setfacl
# View ACLs on a file
getfacl project/

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

# Grant read to a specific group
setfacl -m g:auditors:r project/report.txt

# Set default ACL on a directory (inherited by new files)
setfacl -d -m g:devs:rwx /shared/code/

# Remove a specific ACL entry
setfacl -x u:bob project/report.txt

# Remove all ACLs (revert to standard permissions)
setfacl -b project/report.txt

# Recursive — apply ACL to all existing contents
setfacl -R -m g:devs:rwx /shared/code/

# The '+' in ls -l indicates ACLs are present
ls -l report.txt
# -rw-rw-r--+ 1 alice devs 1024 Apr 12 10:00 report.txt

Note: ACLs require a filesystem that supports them (ext4, XFS, Btrfs). Mount with acl option if not enabled by default. The effective mask (mask::rwx) limits the maximum ACL permissions — check it when permissions seem wrong despite correct ACL entries.

How do permissions interact with Docker bind mounts?

Containers and the host share the kernel UID space. Bind-mount a host directory and files inside the container appear owned by whatever UID the container process uses — usually 0 (root) by default — which leaves files on the host owned by root after the container exits. Run the container as your own user with --user $(id -u):$(id -g) (or set USER in the Dockerfile) so created files match your host account. For a fuller treatment of dev-loop file ownership and bind mounts, see the dev containers guide.

References

Key Takeaways

  • • Permissions are expressed as three groups (owner, group, others) with read (4), write (2), execute (1)
  • • Use chmod 755 for executables, 644 for config files, 600 for secrets
  • umask 022 is the standard default — use 027 or 077 for tighter security
  • • SGID on directories ensures new files inherit the directory's group ownership
  • • Sticky bit on shared directories prevents users from deleting each other's files
  • • ACLs extend the owner/group model to support fine-grained per-user and per-group permissions
  • • Audit SUID files regularly — they run with elevated privileges and are a common attack vector

Translate between octal, symbolic, and human-readable permissions with the chmod calculator tool.

Was this helpful?

Read next

tmux: Sessions, Panes, .tmux.conf, and Neovim Integration

tmux is the BSD-licensed terminal multiplexer (3.6a, 2026) that survives SSH drops and reboots. Sessions, panes, .tmux.conf, scripting, and the Neovim handshake.

Continue →

Frequently Asked Questions

What does chmod 755 mean?

Owner gets read+write+execute (7), group gets read+execute (5), others get read+execute (5). In symbolic form: rwxr-xr-x. This is the standard permission for directories and executable scripts.

What is the sticky bit?

The sticky bit (chmod +t) on a directory prevents users from deleting files they do not own. The /tmp directory uses this: drwxrwxrwt. Set with chmod 1777 or chmod +t.

What is umask?

umask sets default permissions for new files and directories. It specifies which permissions to remove. umask 022 means new files get 644 (666-022) and directories get 755 (777-022).

When should I use Linux capabilities instead of SUID?

Capabilities split root's power into ~40 specific privileges. Bind a non-root service to port 80 with `setcap cap_net_bind_service=+ep /usr/bin/myapp` instead of running it as root or making it SUID — the binary keeps only the one privilege it needs.

Stay up to date

Get notified about new guides, tools, and cheatsheets.