Skip to content

Basic Permissions

Every file has an owner, a group and three permission sets (user, group, other), each with read, write and execute bits. Most "Permission denied" errors come from the directory bits, not the file bits, because x on a directory controls access to everything inside it.

Track: Core · Interview weight: High


Must-Know Facts

Fact Value Verify with
Permission string Type, then rwx for user, group, other ls -l
Octal values r 4, w 2, x 1; 640 = rw-r----- stat -c '%a %A' f
File r, w, x Read content, change content, run as a program cat, echo >>, ./f
Directory r List names ls dir
Directory w Create, delete and rename entries (with x) touch dir/f
Directory x Enter and reach entries by name cd dir
Deleting a file Needs w and x on the directory, not on the file rm dir/f
Check order Owner match, else group match, else other; only the first match applies ls -l
Root Bypasses read and write checks; needs at least one x bit to execute sudo cat f
chown Only root changes the owner sudo chown user:group f
chgrp Owner may change to a group they belong to chgrp devs f
Capital X Execute only for directories and already-executable files chmod -R u=rwX,go=rX dir
Every parent matters Each directory on the path needs x namei -l /path/to/file

Reading and Changing Modes

sudo touch report.txt
ls -l report.txt
stat -c '%A %a %U %G %n' report.txt
sudo chmod 640 report.txt; ls -l report.txt
sudo chmod u+x,g-r,o=r report.txt; ls -l report.txt
sudo chmod a=r report.txt; ls -l report.txt

Output:

-rw-r--r-- 1 root root 0 Sep 16 14:33 report.txt
-rw-r--r-- 644 root root report.txt
-rw-r----- 1 root root 0 Sep 16 14:33 report.txt
-rwx---r-- 1 root root 0 Sep 16 14:33 report.txt
-r--r--r-- 1 root root 0 Sep 16 14:33 report.txt
Octal Symbolic Typical use
644 rw-r--r-- Normal files
640 rw-r----- Config files readable by a service group
600 rw------- Private keys, credentials
755 rwxr-xr-x Programs, normal directories
750 rwxr-x--- Directories shared with one group
700 rwx------ Home directories, ~/.ssh
777 rwxrwxrwx Almost never correct

Symbolic mode uses u, g, o, a with +, - or =, and changes only what it names; octal mode sets all bits at once.


Ownership

sudo chown amor report.txt
sudo chown amor:devs report.txt
sudo chgrp devs report.txt
ls -l report.txt
chown ibtisam report.txt
echo "rc=$?"

Output:

-rw-r----- 1 amor devs 0 Sep 16 14:33 report.txt
chown: changing ownership of 'report.txt': Operation not permitted
rc=1

Only root can give a file away; otherwise users could evade disk quotas or plant files that appear to belong to someone else.


Directory Permissions

User ibtisam falls into "other" for three directories owned by root: d-rw (other rw-), d-x (other --x) and d-rx (other r-x). Each holds a readable file f.

sudo -u ibtisam ls -l d-rw
sudo -u ibtisam cat d-rw/f
sudo -u ibtisam ls d-x
sudo -u ibtisam cat d-x/f
sudo -u ibtisam ls d-rx
sudo -u ibtisam cat d-rx/f

Output:

ls: cannot access 'd-rw/f': Permission denied
total 0
-????????? ? ? ? ?            ? f
cat: d-rw/f: Permission denied
ls: cannot open directory 'd-x': Permission denied
secret
f
secret
Directory bits for the user ls dir cat dir/f (known name) touch dir/new
r-- or rw- Names only, metadata shown as ? Denied Denied
--x Denied Allowed Denied
r-x Allowed Allowed Denied
-wx Denied Allowed Allowed
rwx Allowed Allowed Allowed

Write on a directory lets anyone delete files in it

In a directory with mode 777, ibtisam deleted a file owned by amor with mode 400: the file's own permissions do not matter for deletion. The sticky bit (/tmp) prevents this; see Special Permissions.

sudo mkdir shared && sudo chmod 777 shared
sudo -u amor touch shared/amor.txt
sudo chmod 400 shared/amor.txt
sudo -u ibtisam rm -f shared/amor.txt; echo "rc=$?"
ls shared

Output:

rc=0

namei -l shows every directory on a path, which finds the component that blocks access:

namei -l /srv/perm/d-x/f

Output:

f: /srv/perm/d-x/f
drwxr-xr-x root root /
drwxr-xr-x root root srv
drwxr-xr-x root root perm
drwx-----x root root d-x
-rw-r--r-- root root f

How the Kernel Chooses a Permission Set

Only one set applies: the owner set if the UID matches, otherwise the group set if any group matches, otherwise the other set. An owner with fewer rights than the group is still limited to the owner bits.

sudo touch order.txt; sudo chown amor:devs order.txt; sudo chmod 070 order.txt
sudo -u amor cat order.txt; echo "rc=$?"
sudo install -d -m 755 -o amor dir-owner
sudo -u amor touch dir-owner/f
sudo chmod 000 dir-owner/f; ls -l dir-owner/f
sudo -u amor cat dir-owner/f
sudo -u amor chmod 600 dir-owner/f; sudo -u amor cat dir-owner/f; echo "rc=$?"
sudo cat dir-owner/f; echo "root rc=$?"

Output:

cat: order.txt: Permission denied
rc=1
---------- 1 amor amor 0 Sep 16 14:33 dir-owner/f
cat: dir-owner/f: Permission denied
rc=0
root rc=0

amor is in devs, but as the owner only the empty owner bits applied. An owner can always chmod their own file back; root reads it regardless of mode.


Recursive Changes and Execute

sudo chmod -R 644 tree
sudo -u amor ls -l tree
sudo -u amor cat tree/sub/b.txt
sudo chmod -R u=rwX,go=rX tree
sudo -u amor cat tree/sub/b.txt && echo "readable again"
ls -ld tree tree/a.sh

Output:

ls: cannot access 'tree/a.sh': Permission denied
ls: cannot access 'tree/sub': Permission denied
total 0
-????????? ? ? ? ?            ? a.sh
d????????? ? ? ? ?            ? sub
cat: tree/sub/b.txt: Permission denied
readable again
drwxr-xr-x 3 root root 4096 Sep 16 14:33 tree
-rw-r--r-- 1 root root    0 Sep 16 14:33 tree/a.sh

chmod -R 644 removes execute from directories

Directories without x cannot be entered, so the whole tree becomes unusable. Use capital X, or find dir -type d -exec chmod 755 {} + and find dir -type f -exec chmod 644 {} +.

A script without x fails when run directly, but works through its interpreter, which only needs to read it:

printf '#!/bin/bash\necho hi\n' | sudo tee run.sh >/dev/null
sudo chmod 644 run.sh
sudo -u amor bash -c 'cd /srv/perm && ./run.sh'; echo "rc=$?"
sudo -u amor bash /srv/perm/run.sh

Output:

bash: line 1: ./run.sh: Permission denied
rc=126
hi

Common Errors

chown: changing ownership of 'report.txt': Operation not permitted

Cause: a non-root user tried to change the owner.

Fix: sudo chown.

ls: cannot access 'd-rw/f': Permission denied

Cause: the directory has r but not x for the caller, so names are readable but metadata is not; the listing shows -?????????.

Fix: add x on the directory (chmod o+x), or u=rwX recursively.

bash: line 1: ./run.sh: Permission denied

Cause: the file lacks x for the caller, or its filesystem is mounted noexec; the exit status is 126.

Fix: chmod +x, or check findmnt -no OPTIONS -T <file>.


Interview Checkpoints

L1: What do read, write and execute mean on a directory?

Say first: r lists names, w creates and deletes entries (together with x), and x lets a process enter the directory and reach entries by name.

Proof: with --x, ls dir fails but cat dir/f works.

Follow-up: Which permission is needed to delete a file?

L1: What does chmod 750 mean?

Say first: owner rwx, group r-x, others nothing: 7 = 4+2+1, 5 = 4+1, 0.

Proof: chmod 750 dir; stat -c '%a %A' dir

Follow-up: Why is 750 a common mode for application directories?

L1: If a user is the owner and also in the file's group, which permissions apply?

Say first: only the owner bits; the kernel stops at the first matching class.

Proof: mode 070 with owner amor in group devs: amor gets Permission denied.

Follow-up: How can the owner regain access? (chmod u+r.)

L2: Give group devs read and write access to /srv/app without giving it to others.

Say first: set the group, then the mode.

Proof:

sudo chgrp -R devs /srv/app
sudo chmod -R u=rwX,g=rwX,o= /srv/app

Follow-up: How do you make new files there inherit the group? (SGID on the directory.)

L2: Fix a tree where someone ran chmod -R 644.

Say first: restore x on directories only.

Proof: sudo find /srv/app -type d -exec chmod 755 {} +

Follow-up: Why is chmod -R 755 wrong for the files?

L2: Find which directory on a long path blocks access.

Say first: list each component's permissions.

Proof: namei -l /var/www/app/static/index.html

Follow-up: What else besides mode bits can deny access? (ACLs, SELinux, chattr, mount options.)

L3: A web server returns 403 for a file whose mode is 644.

Say first: check every parent directory, then ownership and the security layers.

Proof: namei -l shows a home directory with mode 700 on the path; the nginx user cannot traverse it.

Follow-up: What is the safer fix than chmod 755 /home/user?

L3: Files a user wrote to a shared directory keep disappearing.

Say first: check the directory mode for world or group write without the sticky bit.

Proof: ls -ld /shared shows drwxrwxrwx; anyone with w on the directory can delete any file in it.

Follow-up: Which bit fixes it?


  • Special Permissions: SUID, SGID and the sticky bit
  • umask: the default mode of new files
  • ACL: permissions for more than one user or group
  • Groups: group membership that the group bits check

Captured on Rocky Linux 10.2 and Ubuntu 24.04.4 LTS (iximiuz Labs microVMs, kernel 6.1.167), 2026-09.