Nandishwar Singh

Home / Learn Linux / Lesson 14

File permissions: chmod and chown

Read rwx, set permissions with letters and numbers, and change who owns a file.

Lesson
14 of 30
Time
About 45 minutes

On this page

  1. Reading permissions
  2. chmod with letters
  3. chmod with numbers
  4. Permissions on directories
  5. Changing the owner: chown and chgrp
  6. Fixing a whole tree: find with chmod
  7. Common mistakes
  8. Practice
  9. Cheat sheet

Reading permissions

Every file and directory has an owner, a group, and three sets of permissions. You've seen them at the start of every ls -l line:

$ cd /srv/perm-lab
$ echo "hello" > note.txt
$ ls -l note.txt
-rw-rw-r-- 1 ubuntu ubuntu 6 Oct 21 11:37 note.txt

The ten characters -rw-rw-r-- break down like this:

-  rw-  rw-  r--
│   │    │    └── others: everyone else
│   │    └─────── group: members of the file's group
│   └──────────── user: the owner
└──────────────── type: - file, d directory, l link

Each set of three is r (read), w (write) and x (execute), or - where that permission is missing. So note.txt can be read and changed by ubuntu and by members of the ubuntu group, and only read by everyone else. The ubuntu group has nobody in it but ubuntu, which is why Ubuntu is happy to let the group write (lesson 15 explains this default).

We're working in /srv/perm-lab rather than your home directory, because your home directory is closed to other users (lesson 13), and the examples need other users to be able to reach these files.

What r, w and x mean

They mean slightly different things for files and for directories, and the directory meanings trip everyone up at first:

On a fileOn a directory
rRead the contentsList the names inside (ls)
wChange the contentsCreate, delete and rename things inside
xRun it as a programEnter it (cd) and reach anything inside

Notice that deleting a file is a w on the directory, not on the file. A read-only file in a directory you can write to can still be deleted.

How Linux decides

When someone touches a file, Linux checks one set only, the first that applies:

  1. Are you the owner? Use the user set.
  2. Otherwise, are you in the file's group? Use the group set.
  3. Otherwise, use the others set.

Root skips all of this and can do anything.

You can test as another user with sudo -u name command, which runs one command as that user. ravi from lesson 13 is in the "others" set for this file, so he can read it but not change it:

$ sudo -u ravi cat note.txt
hello
$ sudo -u ravi sh -c 'echo "hacked" >> note.txt'
sh: 1: cannot create note.txt: Permission denied

sh -c '...' runs the whole command line, redirection included, as Ravi.

Try it

  1. What can the group do with a file showing -rwxr-x---? And others?
  2. What are the permissions on /etc/shadow, and who can read it?
Answer
  1. The group can read and run it. Others can do nothing.

2.

$ ls -l /etc/shadow
-rw-r----- 1 root shadow 952 Oct 21 11:37 /etc/shadow

The owner (root) can read and write it, and the shadow group can read it. Everyone else gets nothing, which is why ubuntu needed sudo in lesson 3.

chmod with letters

chmod (change mode) changes permissions. The letter form reads like a sentence: who, then + (add), - (remove) or = (set exactly), then which:

WhoMeans
uUser (owner)
gGroup
oOthers
aAll three
$ chmod o-r note.txt
$ ls -l note.txt
-rw-rw---- 1 ubuntu ubuntu 6 Oct 21 11:37 note.txt
$ chmod g-w note.txt
$ ls -l note.txt
-rw-r----- 1 ubuntu ubuntu 6 Oct 21 11:37 note.txt
$ chmod a+r note.txt
$ ls -l note.txt
-rw-r--r-- 1 ubuntu ubuntu 6 Oct 21 11:37 note.txt
$ chmod u=rw,g=r,o= note.txt
$ ls -l note.txt
-rw-r----- 1 ubuntu ubuntu 6 Oct 21 11:37 note.txt

o-r took read away from others. g-w took write away from the group. a+r gave read back to all three. u=rw,g=r,o= set all three exactly in one go, and o= with nothing after it means none.

Now Ravi can't even read it:

$ sudo -u ravi cat note.txt
cat: note.txt: Permission denied

Making a script runnable

A script needs x before you can run it:

$ printf '#!/bin/bash\necho "it works"\n' > hello.sh
$ ./hello.sh
bash: ./hello.sh: Permission denied
$ chmod u+x hello.sh
$ ./hello.sh
it works
$ ls -l hello.sh
-rwxrw-r-- 1 ubuntu ubuntu 28 Oct 21 11:37 hello.sh

./ means "the one in this directory" (lesson 27 explains why it's needed). chmod +x with no "who" adds it for everyone, which is usual for scripts.

Try it

  1. Make hello.sh runnable by everyone, but writable only by you.
  2. Remove all permissions for others from hello.sh.
Answer
$ chmod a+x,go-w hello.sh
$ ls -l hello.sh
-rwxr-xr-x 1 ubuntu ubuntu 28 Oct 21 11:37 hello.sh
$ chmod o= hello.sh
$ ls -l hello.sh
-rwxr-x--- 1 ubuntu ubuntu 28 Oct 21 11:37 hello.sh

chmod with numbers

Each permission has a value: r is 4, w is 2, x is 1. Add them up for each set and you get one digit per set:

DigitsLettersTypical use
7rwx4+2+1
6rw-4+2
5r-x4+1
4r--4
0---nothing

Three digits make a full mode. These five cover almost everything you'll do:

ModeLettersUse it for
644rw-r--r--Normal files: you edit, everyone reads
600rw-------Private files: SSH keys, passwords
755rwxr-xr-xPrograms, scripts and normal directories
700rwx------Private directories, like ~/.ssh
750rwxr-x---Shared with a group, closed to everyone else
$ chmod 600 note.txt
$ chmod 755 hello.sh
$ ls -l
total 8
-rwxr-xr-x 1 ubuntu ubuntu 28 Oct 21 11:37 hello.sh
-rw------- 1 ubuntu ubuntu  6 Oct 21 11:37 note.txt
$ stat -c "%a %A %n" note.txt hello.sh
600 -rw------- note.txt
755 -rwxr-xr-x hello.sh

stat -c %a prints the number form, which is handy when you want to check exactly what's set.

Numbers are quicker once you know them, and they set everything at once, so there's no doubt about the result. Letters are better for one small change, like +x, because they leave everything else alone.

Try it

  1. What does chmod 640 give, in letters?
  2. Set note.txt so you can read and write, your group can read, and others get nothing, using a number.
Answer
  1. rw-r-----: 6 is rw-, 4 is r--, 0 is ---.

2.

$ chmod 640 note.txt
$ stat -c "%a %A" note.txt
640 -rw-r-----

Permissions on directories

Directories are where x and r really matter. Make one to experiment with:

$ mkdir shared
$ echo "plans" > shared/plan.txt
$ chmod 644 shared/plan.txt
$ ls -ld shared
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 21 11:37 shared

Take away x from others and Ravi can't get in at all, even though he could read plan.txt itself:

$ chmod o-x shared
$ sudo -u ravi cat shared/plan.txt
cat: shared/plan.txt: Permission denied
$ sudo -u ravi ls shared
plan.txt

With r but no x, Ravi can see the names in the directory but nothing else about them, which is a strange half-state you'll rarely want. Now give it back and take away r instead:

$ chmod o+x,o-r shared
$ sudo -u ravi ls shared
ls: cannot open directory 'shared': Permission denied
$ sudo -u ravi cat shared/plan.txt
plans

x without r lets Ravi open a file he already knows the name of, but he can't list what's there. The rule to remember: **x on every directory along the path** is what lets someone reach a file. That's why a website in /home/ubuntu/site doesn't load: the web server can't get through /home/ubuntu, which is 750.

$ chmod 755 shared

Try it

  1. Make shared so the owner can do anything, the group can list and enter it, and others can't do anything.
Answer
$ chmod 750 shared
$ ls -ld shared
drwxr-x--- 2 ubuntu ubuntu 4096 Oct 21 11:37 shared
$ sudo -u ravi ls shared
ls: cannot open directory 'shared': Permission denied

Changing the owner: chown and chgrp

Only root can give a file away, so chown (change owner) needs sudo. Give it user, user:group, or :group:

$ sudo chown ravi note.txt
$ ls -l note.txt
-rw-r----- 1 ravi ubuntu 6 Oct 21 11:37 note.txt
$ sudo chown ravi:devs note.txt
$ ls -l note.txt
-rw-r----- 1 ravi devs 6 Oct 21 11:37 note.txt
$ sudo chown :ubuntu note.txt
$ ls -l note.txt
-rw-r----- 1 ravi ubuntu 6 Oct 21 11:37 note.txt

chgrp devs file changes only the group, and is the same as chown :devs file. Add -R to change a whole directory tree:

$ sudo chown -R ravi:devs shared
$ ls -la shared
total 12
drwxr-xr-x 2 ravi   devs   4096 Oct 21 11:37 .
drwxr-xr-x 3 ubuntu ubuntu 4096 Oct 21 11:37 ..
-rw-r--r-- 1 ravi   devs      6 Oct 21 11:37 plan.txt

The classic use: you copied files into a website directory with sudo, so root owns them and the web server's user can't write its uploads there. sudo chown -R www-data:www-data /var/www/site/uploads hands them over.

Try it

  1. Give note.txt back to ubuntu:ubuntu, then check.
  2. Make shared and everything in it belong to ubuntu and the group devs.
Answer
$ sudo chown ubuntu:ubuntu note.txt
$ sudo chown -R ubuntu:devs shared
$ ls -l note.txt
-rw-r----- 1 ubuntu ubuntu 6 Oct 21 11:37 note.txt
$ ls -la shared
total 12
drwxr-xr-x 2 ubuntu devs   4096 Oct 21 11:37 .
drwxr-xr-x 3 ubuntu ubuntu 4096 Oct 21 11:37 ..
-rw-r--r-- 1 ubuntu devs      6 Oct 21 11:37 plan.txt

Fixing a whole tree: find with chmod

chmod -R 755 dir sets the same mode on files and directories, which is wrong: it makes every file executable. Directories and files usually want different modes, so use find to treat them separately:

$ mkdir -p site/css site/img
$ touch site/index.html site/css/main.css site/img/logo.png
$ chmod -R 777 site
$ find site -type d -exec chmod 755 {} +
$ find site -type f -exec chmod 644 {} +
$ find site -exec stat -c "%a %n" {} +
755 site
755 site/img
644 site/img/logo.png
644 site/index.html
755 site/css
644 site/css/main.css

There's also a shortcut: a capital X means "execute, but only for directories (and files that are already executable)", so chmod -R u=rwX,go=rX site does both jobs in one command.

Common mistakes

Practice

  1. Check every directory on the way to /etc/ssh/sshd_config, with its permissions, in one command.
Answer
$ namei -l /etc/ssh/sshd_config
f: /etc/ssh/sshd_config
drwxr-xr-x root root /
drwxr-xr-x root root etc
drwxr-xr-x root root ssh
-rw-r--r-- root root sshd_config

namei walks the path and shows the permissions and owner of each part, which makes it the fastest way to find which directory is blocking someone.

  1. Create /srv/perm-lab/secret.txt that only you can read or write, and prove Ravi can't read it.
Answer
$ echo "pin 4321" > secret.txt
$ chmod 600 secret.txt
$ ls -l secret.txt
-rw------- 1 ubuntu ubuntu 9 Oct 21 11:37 secret.txt
$ sudo -u ravi cat secret.txt
cat: secret.txt: Permission denied
  1. Create /srv/perm-lab/team owned by ubuntu and the group devs, so members of devs can create files in it and everyone else can't even look. Then show that Ravi (in devs) can create a file there.
Answer
$ mkdir team
$ sudo chown ubuntu:devs team
$ chmod 770 team
$ sudo -u ravi touch team/ravi-was-here
$ ls -l team
total 0
-rw-r--r-- 1 ravi ravi 0 Oct 21 11:37 ravi-was-here

Lesson 15's SGID bit makes this work better: right now, Ravi's file belongs to his own group, not devs.

  1. Use letters to remove write permission for the group and others from every file in site, without touching anything else.
Answer
$ find site -type f -exec chmod go-w {} +
$ find site -type f -exec stat -c "%a %n" {} +
644 site/img/logo.png
644 site/index.html
644 site/css/main.css
  1. Find every file under /srv/perm-lab that others can write to.
Answer
$ find /srv/perm-lab -perm -o+w -type f
/srv/perm-lab/site/index.html

-perm -o+w matches files where at least the others-write bit is set.

  1. What's the number form of rwxr-x--x?
Answer

751: rwx is 7, r-x is 5, --x is 1.

Cheat sheet

CommandWhat it does
-rwxr-xr-xtype, user, group, others
r w x on a directoryList, create/delete inside, enter
chmod u+x fileAdd execute for the owner
chmod go-w fileRemove write from group and others
chmod u=rw,g=r,o= fileSet exactly
chmod 644 / 600 / 755 / 700 / 750The five modes you'll use most
stat -c "%a %A" fileMode as a number and as letters
sudo chown user:group fileChange owner and group
sudo chown -R user:group dirThe whole tree
chgrp group fileChange the group
find dir -type d -exec chmod 755 {} +Fix directories only
chmod -R u=rwX,go=rX dirFiles 644, directories 755 in one go
sudo -u user commandTest as another user
namei -l /pathPermissions of every directory on the way