Introduction
I have seen some misinformation regarding Unix file permissions. I will try to set the record straight. Take a look at this example of some output from ls:
$ ls -ld /usr/bin /usr/bin/cat
drwxrwxr-x 3 root bin 8704 Sep 23 2004 /usr/bin
-r-xr-xr-x 1 bin bin 9388 Jul 16 1997 /usr/bin/cat
$
On the first line, that "root" says that the directory is owned by the user called "root". And that "bin" is the group of the directory. You will need to understand users and groups and I will assume that you do. My goal is to explain that "drwxrwxr-x" and "-r-xr-xr-x" stuff. That field is a combination of the file type and access permission. Collectively, this information is sometimes called the file mode. And sometimes it is called the permissions. A good place to start is by taking a quick look at how this information is actually stored on disk. The way it is stored affects a number of decisions that have been made over the years.
How the "File Mode" is stored.
On disk, information about a file is stored in structure called an "inode". Each file will have it own inode. One data item in an inode is called the "mode" and it looks like this:
|------file mode------|
| |
|
| |----full-----|
|
|-type| | |--basic--|
| | | | |
oo0 000 000 000 000 000
... ... ... ... ... ...
| | | | |
| | | | |---- rwx for other
| | | |
| | | |-------- rwx for group
| | |
| | |------------ rwx for user
| |
| |---------------- set uid, set gid, sticky bit
|
|---------------------- file type: regular (-)
directory (d)
character special (c)
block special (b)
fifo (p)
symbolic link (l)
socket (s)
I think that the "mode" really means just the permissions and that the file type was shoved in to save space. But the author of the ls program is treating the mode as a single item. That's why the file type is the first character of the permission string in the "ls -l" output. The file type will usually be one of the seven types that I show above. Some versions of Unix will add a few more. The only other thing to notice from the data layout is that there is no room to add more permission bits.
Representing those permissions in octal
The ls program might display, say, "rwxrwxrwx" for the permissions on a file. It is also very common to use an octal number to express the permissions on a file. And as you see above, this is how they are stored. You may hear someone say that some has 777 permissions. This is the same as "rwxrwxrwx" and much easier to pronounce. So you need to know how to convert them. Three binary digits or bits corresponds to one octal digit:
421
rwx
So the "read bit is worth 4, the write bit is worth 2 and the execute bit is worth 1. You just add these up to get an octal digit. So "-rwxrwxrwx" is 777. And "-rwxr-x---" is 750. If you still can't see how to get from "r-x" to 5, maybe this table will help:
--- = 0
--x = 1
-w- = 2
-wx = 3
r-- = 4
r-x = 5
rw- = 6
rwx = 7
Note we need 4 octal digits to express all of the permission bits. The first three bits are special and are frequently zero. And you almost always learn about the trailing 9 bits first. Some people stop there and never learn those first three bits. But there are 12 permission bits, not just 9. That said, let's now take a look at the trailing 9 bits.
The Basic Permission Bits
We have 3 triples: one triple for the user, one triple for the group, and one triple for other. Sometimes the "user" is called the owner. And sometimes "other" is called "world". I will use "user" and "other" because the chmod command uses the letters u g and o to refer to these triples.
Which Set of Bits Applies to You?
When Unix decides what you can do, it doesn't use all 9 bits. Unix picks the first triple that applies to you. Consider this:
----rwxrwx 1 joe users 29 Mar 22 19:39 somefile
Even though joe owns this file, he cannot access it. (Since joe owns the file, he could give himself access. More on that later.) Also root is special. root is granted rwx to all directories and rw to all files. On a file, if any of the 3 x bits are set, root has execute permission. This special permission is often disabled on network mounted filesystems.
What do r w and x really mean for a file?
For a file, "read" and "write" are pretty intuitive. The x for "execute" means that the kernel may attempt to run the file. For that to work, the file must be an executable (output from a compiler) or a shell script with a "#!" first line. For a directory, things are a little more complex. With a directory, "write" permission means that you can create new files in the directory or remove old files. It sometimes surprises people that you can remove a file which you cannot read. The unix rm command will test for that and issue a warning, but you can suppress that warning with -f. And warning or no, if you want to remove an unreadable file from a writable directory, you may. And rmdir will not bother to check at all.
What do r w and x really mean for a directory?
A directory is a file too, and "read" permission means you can read it. But you really cannot do very much without x permission as well. With directories, you usually have both read and execute permission or neither. On a directory, that x is officially called "search permission". You need x to use a directory in a pathname. So if you try "cat /etc/passwd", you will need x on / and /etc. You also need x to cd into a directory. Suppose you have read but not search (x) permission on a directory. What can you do? Not much. You can use "ls" to view the file names. Even "ls -l" will not work. Read access without search permission is not very useful. Still that is better than having only write permission on a directory...that is completely useless. I have not seen any other documentation that states this explicitly, so let me repeat it: write but no execute permission on a directory grants nothing at all.Suppose you have search (x) permission but no read permission on a directory. Now you can open files in the directory if you happen to know the file's name. You can cd into the directory. And that is it. You cannot even create a new file. Adding write permission will allow you to create files. And you can then delete files if you happen to know their name.
Symbolic Links Are Special
The permission settings on a symbolic link are a little special as well. They are completely ignored. Many versions of Unix have no way to change them.
The Setuid and the Setgid Bits
Take a look at this:
$ ls -l /etc/passwd /etc/shadow /usr/bin/passwd
-r--r--r-- 1 root sys 14006 Jan 14 11:17 /etc/passwd
-r-------- 1 root sys 8281 Jan 14 11:18 /etc/shadow
-r-sr-sr-x 3 root sys 96244 Sep 5 2001 /usr/bin/passwd
The passwd file is writable only by root (Remember, root is special. It can write a file that has no write permissions set). The shadow file, which is where passwords are stored, cannot even be read by ordinary users. But joe wants to change his password. He can do that by running /usr/bin/passwd. Notice those r-s permissions. The passwd program has the suid and sgid bits set. This turns the x's into s's. In octal, it would be 6555. The passwd program is owned by root. When joe runs it, it does not run as "joe". Instead, it runs as it owner which is root. So the passwd program can change joe's password for him. The sgid bit works the same way, except it causes the passwd program to run with the group sys instead of joe's group. The suid and sgid do not get their own position in the ls. When the suid bit is set, ls displays a s rather than a x for the owner execute permission. What if the suid bit is set, but the owner execute bit is off? ls will display a capital S in the case. The sgid bit is displayed in a similiar manner, except that it interacts with the group execute permission. (The set uid concept was invented by Dennis Ritchie as he was developing Unix.)
To expand on things a little, while joe is running the suid-to-root passwd program, "joe" is the real uid and "root" is the effective uid. The passwd program can obtain both of these id's if it wants to. This is how the passwd program knows to allow joe to change only joe's password.
The Sticky Bit
The Posix standard says that if the sticky bit is set on a directory, mere write permission on the directory is no longer enough to allow files to be removed. You must additionally own the file or own the directory. root continues to be able to delete from any directory regardless of permissions. Formerly this bit served another purpose. On some OS's it still does. I will elaborate in an appendix below. The sticky bit affects the "other" execute bit in the ls display. Except that it uses t and T rather than s and S. For example:
drwxrwxrwt 5 root root 1024 Feb 11 20:43 /tmp
In that /tmp directory above, anyone can create new files. But because of the sticky bit, one user cannot delete another user's files.
Limiting File Permissions with umask
When files are created the program that creates can specify the initial permission setting. You can override that with umask. The umask is a set of prohibiting bits. There is a umask command that allows you to view and change the umask. For example, "umask 022" prohibits group write and other write on newly created files. Or "umask 027" prohibits group write and it prohibits other read, write, or execute. You can do a "umask 0" to let the program do what it wants as it creates programs. But you cannot go any further. You cannot force a program to turn a bit on. The umask setting affects files, directories, named pipes (aka fifos), and special files. It may or may not affect symbolic links. It also affects somes forms of Inter Process Communication but that is beyond the scope of this article. And believe it or not, named sockets are exempt from umask. This exemption is required by Posix.
Changing File Permissions with chmod
Only the owner of a file or root can change the permissions on a file. This operation is not affected at all by the umask setting. If you change permissions on a symbolic link, the link will be followed and you will change the target file. It is possible that only root will have the power to set a file's sticky bit. As an example, "chmod 700 somefile" wil let the owner read, write and execute the file, while disallowing all access to any other users.
Using Symbolic Mode with chmod and umask
Posix introduced a new syntax for the chmod command. The idea was that the new syntax will replace the use of an octal constant with the chmod command. The octal constant is still allowed and I think it's here to stay. But the new symbolic syntax lets you change a few bits without knowing what the others are. For example, let's say that I want to make a file inaccessible to others but I don't what to change the acess for the user or the group. I would need to do:
ls -l file
Look at file and figure out the current settings.
chmod 750 file
I had to determine that the first two digits are currents 7 and 5 before I could do my chmod command. With the new syntax, I can simply do:
chmod o= file
to turn off the final 3 bits. As another example, "chmod u+x file" will allow the user to execute the file. On the other hand, these two commands are equivalent:
chmod 750 file
chmod u=rwx,g=rx,o= file
and I prefer the first syntax.
The symbolic mode can be a comma separated list of specifications. Each specification has three components: <who><operation><bitlist>
The who part can be:
u (user)
g (group)
o (other)
a (all)
(whatever is allowed by umask (subset of all))
The operator can be = or - or +
= (set bits to bitlist)
- (subtract bitlist from current bit
+ (add bitllist to current bits)
The bitlist can be one of the following letters:
r (read permission)
w (write permission)
x (execute permision)
X (conditional execute permision)
u (current permissions for user)
g (current permissions for group)
o (current permissions for others)
s (set uid or set gid)
t (sticky bit)
The X is the same as x unless the file is a nondirectory and currently has no x bits set. The s (set uid or set gid) can only be specified for user or group permissions. The t can only be specified for user permissions. A few examples with help. Above we saw /usr/bin/passwd was 6555 (-r-sr-sr-x in ls). Here are some ways that could be achieved:
chmod 6555 /usr/bin/passwd
chmod u=rxs,g=rxs,o=rx /usr/bin/passwd
chmod ug=rxs,o=rx /usr/bin/passwd
chmod a=rx,ug+s /usr/bin/passwd
And there are many other ways to do this.
For the most part chmod is immune to umask in that whatever bits it wants to set do not get modified by the umask. However, under one condition, the chmod command will examine the current setting of umask to determine which bits it would like to set. This happens when you leave the "who" field blank. Like this:
chmod =w somefile
The difference between "a=w" and "=w" is subtle. Here is an example that may help. Many programs try to create file with 666 (-rw-rw-rw-) permissions. But this gets modified by the umask. Suppose the you want to set a file to 666 but modified by the current umask. We could turn off all bits, then turn on read and write bits that are allowed by the current umask:
chmod a=,=rw somefile
And speaking of umask, you can use symbolic arguments with the umask command as well. However, Posix, in their wisdom, decided that in this event to logic would be reversed. So if use umask with an octal argument you specify the bits to be prohibited. But if you use umask with a symbolic argument, you specify the bits to allow. So these are equivalent:
umask 022
umask u=rwx,go=rx
Summary
At this point you have enough information to mostly understand those 12 permission bits. There are several very special cases that I have ignored or glossed over. In separate posts below I will address these. The information in this first post is pretty much universal. A Posix compliant OS must support this stuff. That covers almost all versions of Unix released in the past 10 years. The following articles discuss features that may not be universal.