Permissions

Permissions

All this time we have been talking about finding and executing commands, but there is one issue that I haven’t mentioned. That is the concept of permissions. To access a file, you need to have permission to do so. If you want to read a file, you need to have read permission. If you want to write to a file, you need to have write permission. If you want to execute a file, it must have execute permission.

Permissions are set on a file using the chmod command or when the file is created (the details of which I will save for later). You can read the permissions on a file by using either the l command or ls -l. At the beginning of each line will be ten characters, which can either be dashes or letters. The first position is the type of the file, whether it is a regular file (-), a directory (d), a block device file (b), and so on. Below are some examples of the various file types.

Image – Various file types. (interactive) man-page.

The next nine positions are broken into three groups. Each group consists of three characters indicating the permissions. They are, in order, read(r), write(w), and execute(x). The first set of characters indicates what permissions the owner of the file has. The second set of characters indicates the permissions for the group of that file. The last set of characters indicates the permissions for everyone else.

If a particular permission has not been given, a dash (-) will appear here. For example, rwx means all three permissions have been given. In our example above, the symbolic link /usr/bin/vi has read, write, and execute permissions for everyone. The device nodes /dev/tty1 and /dev/hda1 have permissions rw- for the owner and group, meaning only read and write, but not execute permissions have been given. The directory /bin has read and execute permissions for everyone (r-x), but only the owner can write to it (rwx).

For directories, the situation is slightly different than for regular files. If you do not have read permission on a directory, you cannot read the contents of that directory. Also, if you do not have write permission on a directory, you cannot write to it. This means that you cannot create a new file in that directory. Execute permissions on a directory mean that you can search it or list its contents. That is, if the execution bit is not set on a directory but the read bit is, you can see what files are in the directory but cannot execute any of the files or even change into that directory. If you have execution permission but no read permission, you can execute the files, change directories, but not see what is in the files.

Write permission on a directory also has an interesting side effect. Because you need to have write permission on a directory to create a new file, you also need to have write permission to remove an existing file. Even if you do not have write permission on the file itself, if you can write to the directory, you can erase the file.

At first this sounds odd. However, remember that a directory is nothing more than a file in a special format. If you have write permission to a directory-file, you can remove the references to other files, thereby removing the files themselves.

If we were to set the permissions for all users so that they could read, write, and execute a file, the command would look this:

chmod 777 filename

You can also use symbolic permissions to accomplish the same thing. We use the letters u, g, and o to specify the user(owner), group, and others for this file, respectively. The permissions are then r for read, w for write, and x for execute. So to set the permissions so that the owner can read and write a file, the command would look like this:

chmod u=rw filename

Note that in contrast to the absolute numbers, setting the permissions symbolically is additive. So, in this example, we would just change the user’s permissions to read and write, but the others would remain unchanged. If we changed the command to this

chmod u+w filename

we would be adding write permission for the user of that file. Again, the permissions for the others would be unchanged.

To make the permissions for the group and others to be the same as for the user, we could set it like this

chmod go=u filename

which simply means “change the mode so that the permissions for the group and others equals the user.” We also could have set them all explicitly in one command, like this

chmod u=rw,g=rw,o=rw filename

which has the effect of setting the permissions for everyone to read and write. However, we don’t need to write that much.

Combining the commands, we could have something that looks like this:

chmod u=rw, go=u filename

This means “set the permissions for the user to read and write, then set the permissions for group and others to be equal to the user.”

Note that each of these changes is done in sequence. So be careful what changes are made. For example, let’s assume we have a file that is read-only for everyone. We want to give everyone write permission for it, so we try

chmod u+w,gu=o filename

This is a typo because we meant to say go=u. The effect is that we added read permissions for the user, but then set the permissions on the group and user to the same as others.

We might want to try adding the write permissions like this:

chmod +w filename

This works on some systems, but not some Linux distributions that I have seen. According to the man-page, this will not change those permissions where the bits in the UMASK are set. (More on this later. See the chmod man-page for details.)

To get around this, we use a to specify all users. Therefore, the command would be

chmod a+w filename

There are a few other things that you can do with permissions. For example, you can set a program to change the UID of the process when the program is executed. For example, some programs need to run as root to access other files. Rather than giving the user the root password, you can set the program so that when it is executed, the process is run as root. This is a Set-UID, or SUID program. If you want to run a program with a particular group ID, you would use the SGID program with the s option to chmod, like this

chmod u+s program

or

chmod g+s program

As in other cases, you can set permissions nurmerically, using the octal mode of the permissions. Since the SUID or SGID permissions are not part of the standard “rwx”, you need to add an extra digit, so you need four places. For SUID, you use the digit 4 and SGID you use 2. So, in the previous example, to make the file SUID, you might have this:

chmod 4755 program

There are a few other special cases, but I will leave it up to you to check out the chmod man-page if you are interested.

When you create a file, the access permissions are determined by their file creation mask. This is defined by the UMASK variable and can be set using the umask command. One thing to keep in mind is that this is a mask. That is, it masks out permissions rather than assigning them. If you remember, permissions on a file can be set using the chmod command and a three-digit value. For example

chmod 600 letter.john

explicitly sets the permissions on the file letter.john to 600 (read and write permission for the user and nothing for everyone else). If we create a new file, the permissions might be 660 (read/write for user and group). This is determined by the UMASK. To understand how the UMASK works, you need to remember that the permissions are octal values, which are determined by the permissions bits. Looking at one set of permissions we have

bit:2 10
value: 421
symbol:rw x

which means that if the bit with value 4 is set (bit 2), the file can be read; if the bit with value 2 is set (bit 1), the file can be written to; and if the bit with value 1 is set (bit 0), the file can be executed. If multiple bits are set, their values are added together. For example, if bits 2 and 1 are set (read/write), the value is 4+2=6. Just as in the example above, if all three are set, we have 4+2+1=7. Because there are three sets of permissions (owner, group, others), the permissions are usually used in triplets, just as in the chmod example above.

The UMASK value masks out the bits. The permissions that each position in the UMASK masks out are the same as the file permissions themselves. So, the left-most position masks out the owner permission, the middle position the group, and the right most masks out all others. If we have UMASK=007, the permissions for owner and group are not touched. However, for others, we have the value 7, which is obtained by setting all bits. Because this is a mask, all bits are unset. (The way I remember this is that the bits are inverted. Where it is set in the UMASK, it will be unset in the permissions, and vice versa.)

The problem many people have is that the umask command does not force permissions, but rather limits them. For example, if we had UMASK=007, we could assume that any file created has permissions of 770. However, this depends on the program that is creating the file. If the program is creating a file with permissions 777, the umask will mask out the last bits and the permissions will, in fact, be 770. However, if the program creates permissions of 666, the last bits are still masked out. However, the new file will have permissions of 660, not 770. Some programs, like the C compiler, do generate files with the execution bit (bit 0) set. However, most do not. Therefore, setting the UMASK=007 does not force creation of executable programs, unless the program creating the file does itself).

Lets look at a more complicated example. Assume we have UMASK=047. If our program creates a file with permissions 777, then our UMASK does nothing to the first digit, but masks out the 4 from the second digit, giving us 3. Then, because the last digit of the UMASK is 7, this masks out everything, so the permissions here are 0. As a result, the permissions for the file are 730. However, if the program creates the file with permissions 666, the resulting permissions are 620. The easy way to figure out the effects of the UMASK are to subtract the UMASK from the default permissions that the program sets. (Note that all negative values become 0.)

As I mentioned, one way the UMASK is set is through the environment variable UMASK. You can change it anytime using the umask command. The syntax is simply

umask <new_umask>

Here the <new_umask> can either be the numeric value (e.g., 007) or symbolic. For example, to set the umask to 047 using the symbolic notation, we have

umask u=,g=r,o=rwx

This has the effect of removing no permissions from the user, removing read permission from the group, and removing all permissions from others.

Being able to change the permissions on a file is often not enough. What if the only person that should be able to change a file is not the owner? Simple! You change the owner. This is accomplished with the chown command, which has the general syntax:

chown new_owner filename

Where “new_owner” is the name of the user account we want to sent the owner of the file to, and “filename” is the file we want to change. In addition, you can use chown to change not only the owner, but the group of the file as well. This has the general syntax:

chown new_owner.new:group filename

Another useful trick is the ability to set the owner and group to the same ones as another file. This is done with the –reference= option, which sets to the name of the file you are referencing. If you want to change just the group, you can use the chgrp command, which has the same basic syntax as chown. Not that both chgrp and chmod can also take the –reference= option. Further, all three of these commands take the -R option, which recursively changes the permissions, owner or group.