TT Lab
Get started
Learn Learning paths Courses

Linux Fundamentals

Permissions Attach to Actions, Not Files

Continue in TT Lab

In one sentence

The three letters rwx mean different things on a file and on a directory. If you do not know this difference, you will keep running into incidents such as "why was a read-only file deleted?"

Why this matters

A team decided to create one shared directory and use it together. Everyone uploads their own files and promises not to touch anyone else's. Then one day someone's file disappeared. The file's permissions were 644, and the owner was unchanged.

If you ask here, "how was it deleted when the permissions are 644?", there is no answer. Deleting is not an action on the file; it is an action on the directory. Deleting a file means detaching one name from a directory, and for that you only need write permission on that directory. It does not matter whether the file itself is read-only or belongs to someone else.

Unix added one more bit for exactly this problem: the sticky bit.

How it works

First, here is how the same letter changes depending on what it is applied to.

Bit On a file On a directory
r You can read the content You can list the entries (ls)
w You can modify the content You can create and delete entries
x You can execute it You can enter it and pass through the path

If a directory has only r and no x, you can see the names but cannot read information about the files inside. Conversely, if it has only x and no r, you cannot list it but can access an entry if you know its exact name.

Three special bits are layered on top. They are the leading digit of the four octal digits.

So the standard form of a team shared directory is 2770 (group inheritance plus blocking anyone outside the group), and if you want anyone to upload but not delete other people's files, it is 1777.

What you see in the field

First, you added a group but it has no effect. Even if you run usermod -aG devs alice, it is not reflected in a shell that alice was already logged in to. The group list is fixed when a process is created. A new login session is needed. If you leave out -a (append) here, all existing supplementary groups are wiped out, which is an incident that often happens on production servers.

Second, octal and symbolic notation. There is the absolute style, such as chmod 750 run.sh, and the relative style, such as chmod g+x,o-rwx run.sh. In deployment scripts the result must be the same regardless of the current state, so absolute values are safer. Conversely, when you touch a large number of files, symbolic notation reduces mistakes.

Third, check permissions with a command, not with your eyes. In the output of ls -l, counting the letters of -rwxr-x--- by eye is less accurate than running stat -c %a. When you write grading scripts or check scripts, always use stat.

Who decides the permissions of a newly created file

Many people have typed chmod but do not know where the permissions of a file at the moment it is first created come from. What decides this is umask.

When a program creates a file, it tells the kernel the permissions it wants; regular files usually request 666 and directories 777. The kernel then removes the bits that are set in umask and creates the file. With a umask of 022, a file becomes 644 and a directory becomes 755. So umask is not an "allow" list but a "forbid" list, and if you get that direction wrong when reading the value, the calculation comes out backwards.

Two things often cause trouble here. First, the execute bit is never added by umask. The request is 666, so there is no execute bit to begin with, which is why a newly created script always needs chmod +x. Second, umask exists per process and is inherited by children, so a service's umask is decided by the environment that started it. The value differs between when a person starts it from a shell and when the system starts it at boot, so you can end up with only the files created by a manually restarted service having different permissions. For such services it is safer to state the umask explicitly in the configuration.

It also helps to fix an order of checks for when permissions look strange: who created it → what was the umask at that time → is setgid set on the directory → who ran chmod afterward. In particular, for the third one, as we saw earlier, the group changes, so if the file's owning group differs from the creator's primary group, look at that directory first.

Finally, a note on access control lists (ACLs). With only owner, group, and others, you cannot express "give read access to just this one person," so in that case you layer individual permissions on with setfacl. However, in ls -l only a single + is added at the end, which is easy to miss, so when the permissions cannot be explained, check with getfacl.

What you will do in the next lab

You create users and groups yourself, set up a shared directory with setgid and sticky set, and finally write a check script that inspects whether "this file has the permissions we expect" and reports the result through its exit code.