Linux File Permissions Explained

In short
  • Every Linux file has an owner, a group and a set of permissions for owner / group / everyone else.
  • Permissions are three flags: read, write, execute. They mean slightly different things for directories than for regular files.
  • chmod changes permissions; chown changes ownership; umask controls the default permissions on newly-created files.
  • Where the classic model is too coarse, ACLs let you grant access to specific users on top of the owner/group/other scheme.

The model

Every file and directory on a Linux filesystem carries the same handful of metadata: an owner (a user ID), a primary group (a group ID), and a 9-bit set of permissions split into three triples.

Running ls -l shows this metadata for the current directory:

$ ls -l
-rw-r--r-- 1 alice staff  1284 May  3 09:12 notes.md
drwxr-xr-x 2 alice staff  4096 May  3 09:14 archive/
-rwxr-xr-x 1 alice staff   864 May  3 09:15 build.sh

Reading the first column from left to right:

  • Position 1 — file type. - is a regular file, d is a directory, l is a symlink, c and b are character and block devices, and so on.
  • Positions 2–4 — the owner triple: read, write, execute permissions for the file's owner.
  • Positions 5–7 — the group triple: same flags, but for members of the file's group.
  • Positions 8–10 — the other triple: same flags, for everyone else (often called "world", though that name is misleading).

So -rw-r--r-- means: regular file; owner can read and write; group can read; everyone else can read.

What each flag actually means

The three flags — r, w, x — behave a little differently on files than on directories.

On a regular file
  • r — you can read the file's contents.
  • w — you can modify the file's contents.
  • x — you can execute the file (run it as a program).
On a directory
  • r — you can list the names of files in the directory.
  • w — you can create, delete and rename files in the directory.
  • x — you can enter the directory and access the files inside (if you know their names).

One consequence worth pausing on: deleting a file is a write permission on the directory that contains it, not on the file itself. You can delete a read-only file inside a writable directory; you cannot delete a writable file inside a read-only one. That asymmetry catches people out surprisingly often.

chmod: changing permissions

The chmod command has two equivalent forms: symbolic and octal.

Symbolic form

The symbolic form names the triple (u/g/o/a for user, group, other, all), an operator (+ to add, - to remove, = to set exactly) and the flag.

# Make a script executable by everyone
chmod a+x build.sh

# Remove write permission from group and other
chmod go-w secrets.txt

# Set permissions exactly: owner read+write, group read, no access for other
chmod u=rw,g=r,o= notes.md

Octal form

The octal form expresses each triple as a number 0–7, where read is 4, write is 2 and execute is 1.

Octal Symbolic Meaning
0---no access
4r--read only
5r-xread + execute
6rw-read + write
7rwxfull access

A complete mode is three digits, one per triple. The common patterns:

# A normal data file (-rw-r--r--)
chmod 644 notes.md

# A normal script you and your group can run (-rwxr-xr--)
chmod 754 build.sh

# A directory only you can use (drwx------)
chmod 700 private/

# A directory everyone can read and traverse (drwxr-xr-x)
chmod 755 public/

People tend to develop a preference: symbolic for one-off tweaks ("add execute"), octal for setting an exact mode you have in mind.

chown: changing ownership

Ownership is changed with chown. You need to be root to change a file's owner; you can usually change a file's group to one you belong to without being root.

# Change owner
sudo chown alice file.txt

# Change owner and group
sudo chown alice:staff file.txt

# Change group only
chgrp staff file.txt

# Change recursively, including everything inside a directory
sudo chown -R alice:staff project/

The recursive form is convenient but powerful — running it from the wrong directory is a classic way to break a system. Double-check the target path before pressing return.

Default permissions: umask

When a process creates a new file, the permissions it ends up with are determined by two things: the permissions the program asks for, and a per-process umask that masks bits out. The umask is set per shell session and inherited by everything you launch from that session.

# Show the current umask
umask

# Common umask values
umask 022   # default for most distributions; new files get 644, dirs 755
umask 077   # restrictive; new files only accessible to the owner

Most users don't need to change umask manually. It's worth knowing about because it's the answer to "why did this file end up with these permissions even though I didn't set any?"

Special permission bits

Beyond the standard nine permission bits, three special bits show up occasionally and are worth recognising in the wild.

  • setuid (4000) — when set on an executable, the program runs with the user ID of the file's owner rather than the user who launched it. Used by sudo, passwd and a small set of other tools. Visible as a lowercase s in the owner's execute position. Setuid on a non-root program is a common attack target; treat it with care.
  • setgid (2000) — analogous, but for the group. On a directory, setgid causes new files to inherit the directory's group rather than the creating user's primary group — useful for shared project directories.
  • sticky bit (1000) — on a directory, prevents users from deleting files they don't own, even if the directory is world-writable. Used on /tmp. Visible as a lowercase t in the world-execute position.

ACLs: when the model isn't enough

The owner/group/other model has one user and one group per file. If you want to grant access to several specific users without lumping them into a group, you need access-control lists (ACLs). Most modern filesystems support them.

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

# Inspect ACLs
getfacl file.txt

# Remove the entry
setfacl -x u:bob file.txt

Files with ACLs show a trailing + in ls -l:

-rw-r--r--+ 1 alice staff  1284 May  3 09:12 notes.md

ACLs are useful when a project needs more nuanced sharing than the standard model allows, but they make the access story harder to read at a glance — they should be reached for when needed, not as the default.

Common mistakes

  • chmod 777 as a fix. Almost never the right answer. If a program can't write to a file, the question is which user it's running as and what the file's permissions should be — not how to make every user able to do everything.
  • Forgetting that delete is a directory-level permission. "I can't delete this file even though I own it" usually means the directory is read-only.
  • Recursive chmod on a tree that contains executables. chmod -R 644 will turn off the execute bit on directories and scripts, which usually breaks things. Use find to apply permissions selectively: find . -type d -exec chmod 755 {} + for directories, find . -type f -exec chmod 644 {} + for files.
  • Confusing user with group. The numeric uid and gid spaces are separate. The user "alice" and the group "alice" are distinct entities on most distributions, even if many distributions create them in pairs.

Related reading