Classic Shell Scripting - Arnold Robbins [242]
When permissions are checked, the order is user, then group, then other. The first of these to which the process belongs determines which set of permission bits is used. Thus, it is possible to have a file that belongs to you, but which you cannot read, even though fellow group members, and everyone else on your system, can. Here's an example:
$ echo 'This is a secret' > top-secret
Create one-line file
$ chmod 044 top-secret
Remove all but read for group and other
$ ls -l
Show our changes
----r--r-- 1 jones devel 17 2002-10-11 14:59 top-secret
$ cat top-secret
Try to display file
cat: top-secret: Permission denied
$ chmod u+r top-secret
Allow owner to read file
$ ls -l
Show our changes
-r--r--r-- 1 jones devel 17 2002-10-11 14:59 top-secret
$ cat top-secret
This time, display works!
This is a secret
All Unix filesystems contain additional permission bits, called set-user-ID, set-group-ID, and sticky bits. For compatibility with older systems, and to avoid increasing the already large line length, ls does not show these permissions with three extra permission characters, but instead, changes the letter x to other letters. For the details, see the chmod(1), chmod(2), and ls(1) manual pages. For security reasons, shell scripts should never have the set-user-ID or set-group-ID permission bits set: an astonishing number of subtle security holes have been found in such scripts. We cover these permission bits and shell-script security in Chapter 15.
Execute-only permission (--x--x--x) is sometimes used for commercial software to discourage copying, debugging, and tracing, but still allow the programs to be run.
Directory permissions
So far, we have discussed permissions only of ordinary files. For directories, the permissions are given slightly different meaning. Read access for a directory means that you can list its contents with, for example, ls. Write access means that you can create or delete files in the directory, even though you cannot write the directory file yourself: that privilege is reserved for the operating system in order to preserve filesystem integrity. Execute access means that you can access files and subdirectories in the directory (subject, of course, to their own permissions); in particular, you can follow a pathname through that directory.
Since the distinction between execute and read access on a directory is subtle, here is an experiment to clarify things:
$ umask
Show the current permission mask
22
$ mkdir test
Create a subdirectory
$ ls -Fld test
Show the directory permissions
drwxr-xr-x 2 jones devel 512 Jul 31 13:34 test/
$ touch test/the-file
Create an empty file there
$ ls -l test
List the directory contents verbosely
-rw-r--r-- 1 jones devel 0 Jul 31 13:34 test/the-file
So far, this is just normal behavior. Now remove read access, but leave execute access:
$ chmod a-r test
Remove directory read access for all
$ ls -lFd test
Show the directory permissions
d-wx--x--x 2 jones devel 512 Jan 31 16:39 test/
$ ls -l test
Try to list the directory contents verbosely
ls: test: Permission denied
$ ls -l test/the-file
List the file itself
-rw-r--r-- 1 jones devel 0 Jul 31 13:34 test/the-file
The second ls failed because of the lack of read permission, but execute permission allowed the third ls to succeed. In particular, this shows that removing read permission from a directory cannot prevent access to a file contained therein, if its filename is already known.
Here is what happens when we remove execute access, without restoring read access:
$ chmod a-x test
Remove directory execute access for all
$ ls -lFd test
List the directory
d-w------- 3 jones devel 512 Jul 31 13:34 test/
$ ls -l test
Try to list the directory contents verbosely
ls: test: Permission denied
$ ls -l test/the-file
Try to list the file
ls: test/the-file: Permission denied
$ cd test
Try to change to the directory
test: Permission denied.
The directory tree has been effectively cut off from view by any user, except root.