Permissions on directories
◈ 11 cardsWhat r, w and x mean on a directory, why r without x is nearly useless, and how to derive the minimal mode for a given operation.
A directory is a file of names, and that fixes the meanings
A directory is a file whose contents are a list of (name, inode) pairs. Once you accept that, the three bits stop being metaphors:
r— read the list. You may see the names in the directory.w— write the list. You may create, delete or rename entries in it.x— search it. You may traverse it:cdinto it, or resolve a pathname that passes through it, orstatany entry in it.
All the counter-intuitive behaviour follows from x being search rather than execute. Nothing about a directory is executable, and the bit is only called x because it shares a column with the file case.
Worked example — three broken directories, four different failures
Make three directories and set each to a deliberately incomplete mode:
$ chmod 600 alpha # drw------- read the names, cannot search
$ chmod 500 beta # dr-x------ read and search, cannot write
$ chmod 300 gamma # d-wx------ write and search, cannot read
Now watch four commands fail for four different reasons.
$ cd alpha
-bash: cd: alpha: Permission denied
No x. cd is a traversal, and traversal needs search permission, which 600 does not grant. On Linux ls alpha will still print the names — reading the list only needs r — but ls -l alpha cannot stat a single one of them, so the fields come back as errors. Names and nothing else is the whole of what r alone buys you, which is why the rule of thumb is that r without x accomplishes nothing useful.
$ touch beta/notes.txt
touch: cannot touch 'beta/notes.txt': Permission denied
No w. Creating an entry writes the directory’s list, and 500 is read-and-search only. cd beta and ls beta both work perfectly — this failure is nothing to do with reaching the directory.
$ ls gamma
ls: cannot open directory 'gamma': Permission denied
$ echo gamma/*
gamma/*
No r. 300 lets you go into gamma and create files there, but you cannot list what is already inside. The second line is the same failure wearing different clothes: globbing is done by the shell, and the shell needs r on the directory to read the names it is matching against. With no r, the pattern matches nothing and the shell hands the literal gamma/* through unchanged.
Now fix exactly one bit and re-run the first command:
$ chmod u+x alpha
$ ls -ld alpha
drwx------ 2 ada dev 4096 Sep 1 11:40 alpha
$ cd alpha
$
One bit. That is the shape of every directory-permission problem: name the operation, name the bit it needs, add that bit and nothing else.
Deletion is the directory’s business, not the file’s
Deleting alpha/report.txt does not modify report.txt — it removes a name from alpha’s list. So the permissions consulted are alpha’s, and they must include w (to edit the list) and x (to reach the entry at all). The minimum is therefore wx, which is octal 300 — d-wx------. The file’s own mode is irrelevant to whether the deletion is permitted: a file you cannot read, cannot write and do not own will disappear happily from a directory you have wx on. (rm will prompt before removing a file you lack w on, but that is a courtesy in the tool, not a permission check in the kernel — rm -f skips it.)
The reverse holds too. A file at mode 777 inside a home directory at 700 is unreachable by anyone but its owner: the traversal fails at the home directory, and the kernel never gets far enough to look at the file’s generous bits.
Every component, not just the last
A pathname is resolved one component at a time, and each directory in it needs x. /home/ada/projects/notes.txt requires search on /, on /home, on /home/ada and on /home/ada/projects. Setting chmod 755 projects achieves nothing if ada is 700 and you are not ada. That is why 711 is such a common mode for a home directory: it grants search without granting the ability to list what is inside.