Skip to content
0xrcosRyan Camargo — home
All posts
linux~6min readRyan Camargo

Linux File Permissions, Without the Magic

A grounded tour of rwx, octal notation, chmod, chown, umask, and the special bits — explained the way I wish someone had explained them to me.

Read this in:PT-BRES

Note: This is sample placeholder content created to demonstrate the blog. Replace it with your own writing.

File permissions are one of those Linux topics that gets introduced once, badly, and then never revisited. You learn chmod 755, you copy-paste it forever, and at some point you realize you don't actually know what the 4 in chmod 4755 does. This post is the explanation I would have wanted in my first year.

The ls -l Output, Decoded

Start with the source of truth. ls -l prints the metadata that the filesystem stores for each entry:

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59944 Feb  7  2025 /usr/bin/passwd

Reading left to right:

  • - — file type (- regular file, d directory, l symlink, c/b character/block device, p pipe, s socket).
  • rws — permissions for the owner (the s here is a special bit, more on that later).
  • r-x — permissions for the group.
  • r-x — permissions for others (everyone else).
  • 1 — hard link count.
  • root root — owner and group.
  • 59944 — size in bytes.
  • Date and name.

The nine permission characters split into three triplets: owner / group / other. Within each triplet, the positions are fixed: r (read), w (write), x (execute). A dash means "not set."

Symbolic vs. Octal

There are two ways to talk about permissions: symbolic (rwxr-xr-x) and octal (755). They describe the same thing; octal is just more compact.

Each triplet maps cleanly to three bits:

Symbolic Binary Octal Meaning
--- 000 0 no access
--x 001 1 execute only
-w- 010 2 write only
-wx 011 3 write + execute
r-- 100 4 read only
r-x 101 5 read + execute
rw- 110 6 read + write
rwx 111 7 read + write + execute

So 755 is rwxr-xr-x: the owner can do anything, the group and others can read and execute but not write. 644 is rw-r--r--, the default for most regular files. 600 is rw-------, common for private keys.

chmod: Symbolic and Absolute Modes

chmod accepts either form. Symbolic mode is friendlier when you only want to change one bit:

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

# Remove write access for "others".
chmod o-w notes.txt

# Make a file readable and writable for group and owner, nothing for others.
chmod ug=rw,o= shared.log

Octal mode sets all three triplets at once — anything you don't mention gets cleared:

# Tighten a private key.
chmod 600 ~/.ssh/id_ed25519

# A directory that the team can read and traverse, but not write to.
chmod 755 /srv/public

A common gotcha: on a directory, r lets you list the entries; x lets you traverse into the directory and access a named entry. Removing x from a directory usually breaks more than people expect.

chown and chgrp

chown changes the owner (and optionally the group). chgrp changes only the group; in practice chown is used for both because it can take owner:group form.

# Change owner only.
sudo chown ryan app.log

# Change owner and group.
sudo chown ryan:devs app.log

# Recursive, with explicit group change.
sudo chown -R ryan:devs /srv/app

Use -R carefully. Recursive chown across a directory tree that includes symlinks can produce surprising results; add -h to operate on the symlinks themselves rather than their targets.

umask and Default Permissions

When a new file is created, the kernel applies a default mode, and then the shell's umask removes bits from it. The default creation mode is typically 0666 for files and 0777 for directories.

$ umask
022

A umask of 022 means: don't strip anything from owner; strip write from group; strip write from others. So:

  • New file: 0666 & ~022 = 0644 → rw-r--r--
  • New directory: 0777 & ~022 = 0755 → rwxr-xr-x

To make new files group-writable by default, set umask 002 (often used on shared servers where a group of people write to the same tree).

The Special Bits: setuid, setgid, and Sticky

Three additional bits sit in front of the nine you already know. They're easy to miss because they show up in the owner-execute, group-execute, and other-execute positions, replacing the x with s or t.

setuid (4xxx)

When set on an executable, the process runs with the effective UID of the file's owner rather than the user who invoked it. The canonical example is passwd:

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59944 Feb  7  2025 /usr/bin/passwd

That s in the owner triplet is setuid. It's how a normal user can edit /etc/shadow (which only root can read) without being root. setuid is powerful and dangerous — every privileged setuid-root binary is a privilege escalation waiting to happen if it has a bug. Audit them:

$ find /usr -perm -4000 -type f -exec ls -l {} \;

setgid (2xxx)

On an executable, setgid does the same thing but for the group. On a directory, setgid has a different and very useful meaning: any file created inside that directory inherits the directory's group, rather than the creating user's group. This is the standard mechanism for shared project directories.

sudo mkdir /srv/team
sudo chgrp devs /srv/team
sudo chmod 2775 /srv/team   # setgid on a directory

Sticky Bit (1xxx)

The sticky bit on a directory says: only the owner of a file (or the owner of the directory, or root) may rename or delete that file. /tmp is the textbook example:

$ ls -ld /tmp
drwxrwxrwt 25 root root 4096 Mar 22 09:12 /tmp

That t at the end is the sticky bit. Without it, any user could delete any other user's files in /tmp — which would be a mess.

Setting the Special Bits

Combine them with the rest of the octal mode. The first digit is the special-bits byte:

# setuid + rwxr-xr-x → 4755
sudo chmod 4755 /opt/app/bin/privileged-helper

# setgid on a directory, with rwxrwsr-x → 2775
sudo chmod 2775 /srv/team

# Sticky bit on /tmp (already set by default) → 1777
sudo chmod 1777 /tmp

Symbolic mode is arguably clearer:

chmod u+s helper        # setuid
chmod g+s /srv/team     # setgid
chmod +t /tmp           # sticky

A Quick Mental Model

  • rwx is three bits per triplet, three triplets per file.
  • Octal packs each triplet into one digit; the leading fourth digit (if present) carries the special bits.
  • On directories, r lets you list, x lets you traverse, w lets you create/delete/rename.
  • The special bits (setuid, setgid, sticky) modify how the file executes or how files are created inside a directory.

Where to Read More

The canonical reference is man 2 chmod and man 1 chmod. The Linux chmod man page is unusually thorough, and the File permissions section of the kernel docs explains the corner cases (capabilities, ACLs, what happens on symlink chains) that this post deliberately skips. If you're working with ACLs (getfacl / setfacl), the model extends cleanly — but that's a separate post.

On this page

Related