Unix File Permission Primer

WARNING: This documentation is not yet complete.

Most of the computers available on our network run Linux, which uses the standard Unix file permission system. Understanding file permissions can help when you want to share files with others or use our webserver to host your own webpages.

The first thing to know is that you don't need to do anything special if you don't want anyone else to see your files. By default, files that you create will only be accessible by you and no one else.

That said, let's get started.

Viewing File Permissions

You can view file permissions from the Unix command line with the command ls -l . That will show you something like the following:

drwx------. 2 account users    3 Sep 12 15:47 Desktop
drwx------. 4 account users    4 Aug 26  2008 Mail
-rw-------. 1 account users 4153 Apr 16  2013 README
drwx---r-x. 3 account users    4 Sep 12 15:47 public_html

The last column gives you the name of the file or directory. The first column shows the permissions. The third and fourth columns ("account" and "users" in this example) give the owning account and group, respectively. (We're going to ignore the other columns.)

The Basics

In Unix, every file (and directory) belongs to one account and one group. That gives three sets of permissions: one for the owning account (often shortened to "u", for user), one for its group ("g"), and one for everyone else ("o", for other).

There are three basic permissions in each set: read, write, and execute. For files, those are pretty straightforward: "read" lets you see the file's contents; "write" lets you change the file's contents; and "execute" lets you run the file as a program. For directories, the meanings are a little less obvious: "read" lets you see what the contents of the directory are; "write" lets you add and remove (and rename) files in the directory; and "execute" lets you access files in the directory.

Note: There are a couple of common but not necessarily obvious combinations of permissions here. First, in order to read a file, you must have read permission for the file and execute permission for the directory containing the file (and for the directory containing that directory, and so on). Second, you can have a directory that gives you execute permission but not read permission. In that case, you could access files in the directory, but only if you already knew what the files' names were, since you couldn't get a list of files in the directory.

In the output of ls -l, the permissions column is a string of ten characters that might look something like "drwx---r-x". The first character isn't really a permission--it's an indication of the type of file ("-" for a regular file, or block special file, character special file, directory, symbolic link, named pipe, socket, or a "?" for something else). The remaining characters are in three groups of three. Each group corresponds, from left to right, to the user, group, and other permission sets. Within each group, the first character is an "r" if that set contains the read permission and a "-" if it does not. The next two characters are either "w" or "-" for the write permission and "x" or "-" for the execute permission.

Putting all of that together lets us explain these permissions: "drwx---r-x". That's a directory that gives all three permissions to the owning account, no access to members of the owning group, and read and execute permission to everyone else.

It can sometimes help to think of the permissions in terms of a matrix, like this:

read write execute
user r w x
group - - -
other r - x

Note: When the system checks permissions on a file (or directory), it first checks to see if you're the owner of the file; if so, it uses the "user" permissions. Otherwise, it checks to see if you're a member of the file's group; if so, it uses the group permissions. Otherwise, it uses the global permissions. This means that you can have a situation like the above example where members of a particular group actually have fewer permissions than people who are not members of the group.

Permission Representations

ls -l is the most common way to view file permissions. Unfortunately, when you want to change permissions, the programs for that use completely different ways of writing permissions. There are two different ways to describe permissions; most programs will accept either way and we'll cover both of them here.

Symbolic Representation

In the symbolic representation, each permission set and permission is shortened to a single character; the "r", "w", and "x" you might expect for the permissions, and "u", "g", and "o" for the "user", "group", and "other" sets. You can either specify permissions as a change from the current or default value with "+" or "-", or you can specify them exactly with "=". Different sets are separated by commas. As a special case, you can use the "a" character to represent "all" sets; it will apply its permissions to all three of the "user", "group", and "other" permission sets.

Here are some examples:

  • u=rwx,g=,o=rx - This specifies permissions exactly and would be shown by ls -l as "-rwx---r-x". The owning account has full permissions, members of the owning group have no permissions, and everyone else has read and execute permissions.
  • g-w,o-rwx - This is a modification of an existing set of permissions. Write permission is being removed from the "group" permission set and all permissions are being removed from the "other" set.
  • u-w,g+r - Also a modification of an existing set of permissions. The owner no longer has write access, but members of the owning group can now read the file.
  • a+r,a-w - Another modification of an existing set of permissions. Anyone can now read the file, but no one (not even the owner) can write to it.

Octal Representation

The symbolic representation for permissions is generally easy to read, but it can get a little long. The octal representation is the opposite: it's short, but harder to read until you get used to it.

Octal representations of the basic permissions are three digits long and look something like this: "705". The first digit represents the user permissions, the second digit is the group permissions, and the third digit shows the "other" permissions. Each digit is the sum of up to three numbers: 4 for read permission, 2 for write permission, and 1 for execute permission. The digit zero means that no permissions are given to that set.

Thus, the permissions with the octal representation "705" are the same as the symbolic representation "u=rwx,g=,o=rx" and would be shown by ls -l as "-rwx---r-x". To put that into our matrix representation:

read write execute sum
user 4 2 1 7
group 0 0 0 0
other 4 0 1 5

Here are some other example octal modes:

Octal Symbolic ls -l
000 u=,g=,o= ----------
644 u=rw,g=r,o=r -rw-r--r--
750 u=rwx,g=rx,o= -rwxr-x---

Default Permissions

On our systems, the default permissions for files are 600 (u=rw,g=,o=) and the default permissions for directories are 700 (u=rwx,g=,o=). Here's how those defaults are set (and how you can change them):

When you log in to a system, your default permissions are set by your shell's umask. The umask serves as a kind of limit on the permissions given to new files and directories. Without a umask, files would all have permissions 666 (a=rw or u=rw,g=rw,o=rw) and directories would all have permissions 777 (a=rwx or u=rwx,g=rwx,o=rwx). In actuality, when a file or directory is created, the system starts with those values (666 for files and 777 for directories), but then applies the umask, which removes some of those starting permissions to arrive at the actual defaults.

You can view your umask with the umask command, which will show the umask in its octal representation. Many shells (but not the default shell on our systems, tcsh) also support running umask -S to show the umask in symbolic representation.

Unfortunately, the meaning of the umask is different between the octal and symbolic representation. (Unix is full of such unfortunate contradictions.) The symbolic representation works as a limit on the permissions. In symbolic terms, our default umask is u=rwx,g=,o=. The process of applying the symbolic umask is logical intersection; only permissions that are in the starting set and the umask will be applied to the file or directory being created.

For example, a file (starting permissions: a=rw (666)) plus a umask of u=rwx,g=rx,o= will give actual permissions of u=rw,g=r,o= (640).

The octal representation for the umask works as a list of permissions that will be taken away from the starting permissions. In octal terms, our default umask is 077. The process of applying an octal umask is logical difference; any permissions in the umask are removed from the starting permissions to arrive at the final permissions.

For example, a directory (starting permissions: 777 (a=rwx)) plus a umask of 027 will give actual permissions of 750 (u=rwx,g=rx,o=).

To change your umask, you use the umask command like this:

umask new-permissions

To make the change permanent, you'll have to add that command to your shell's initialization file. On our systems, if you haven't changed your shell, that file will be ~/.cshrc .

Warning: The default shell on our systems (tcsh) only understands octal notation for permissions. Symbolic notation will not work.

Changing Permissions

The chmod program is used to change permissions on a file or directory. Its invocation looks roughly like this:

chmod permissions file [file ...]

The "permissions" parameter can be in either octal or symbolic representation. If you use symbolic representation, you can use the "+" and "-" characters to add and remove permissions from the file without having to specify the full permissions. For example, if you just want to add execute permission to a file for yourself, and not worry about the other particular permissions on the file, you can run:

chmod u+x file

When using octal notation, you muct specify the full permissions for the file every time.

Advanced Topics

Most people won't need to delve too deeply into these topics, but they're here for completeness.

Extra Properties

In addition to the basic permissions mentioned above, there are three other properties that can be applied to files or directories in the same way as the basic permissions. Those are:

  • Set UID
    • On a file: When the file is run as a program, it runs under the account of the file owner, not the account of the person running it. This is often used for controlled access to things with restricted permissions.
      • e.g. Only root can edit the password database (otherwise you could change someone else's password), but the passwd program is set UID to root so that it can change your password (and only your password) for you.
    • On a directory: Any file created in the directory (by someone who has write access to the directory) will be owned by the account that owns the directory. (Under normal circumstances, when you create a file, your account will automatically own that file.)
  • Set GID
    • On a file: When the file is run as a program, it runs under the group of the file, not the group of the person running it. Obviously, this is analogous to the set UID property, but for groups.
    • On a directory: Files created in the directory are owned by the directory's group. (Under normal circumstances, when you create a file, it will, by default, belong to your primary group. On our systems, every person's primary group is the users group.)
      • This is often used when collaborating with others. The way it works is that the sysadmins will create a system group for the collaboration and add all of the collaborators to it. Then one of the collaborators creates a directory, changes its group (with chgrp) to the collaboration group, gives the directory group write permission, and adds the set GID property. Then any files created in the directory will belong to the collaboration group.
  • Sticky bit
    • On a file: Basically not used. It used to do some things on old versions of Unix, but it has no effect on our Linux systems.
    • On a directory: Without the sticky bit, if you have write access to a directory, you can delete any file in that directory (alongside being able to create files in the directory). With the sticky bit, if you have write access to a directory you can only delete files that you own.
      • This is used for directories like /tmp where everyone should be able to create files as needed but people shouldn't be able to mess with other people's files.

Extra Property Representations

In ls -l output, set UID and set GID are represented by putting an "s" in place of the user or group "x" character. (If for some reason the object has set UID or set GID without the corresponding execute permission--which is almost always a mistake--the character used is a capital "S".) The sticky bit is represented with a "t" in place of the "other" execute permission. (Like the other properties, an object with the sticky bit but without "other" execute permission will have a capital "T".) For example:

  • -rw-r----- is an ordinary file with no extra properties.
  • -rwsr-xr-x is a set UID program. (This is what passwd looks like on our systems.)
  • -rwxr-sr-x is a set GID program. (This is what screen looks like on our systems.)
  • drwxrwxrwt is a directory with the sticky bit. (This is what /tmp looks like on our systems.)

In octal notation, a fourth digit is added at the beginning of the permission string. The constituent numbers for that fourth digit are: 4 for set UID, 2 for set GID, and 1 for the sticky bit. A three digit number is assumed to have a zero for the extra fourth digit. Examples:

  • 0640 (or 640) is our ordinary file with no extra properties again.
  • 4755 is a set UID program. (This is passwd again.)
  • 2755 is a set GID program. (This is screen again.)
  • 1777 is a directory with the sticky bit. (This is /tmp again.)

In symbolic notation, set UID and set GID are given by using an "s" with either the "u" or "g" sets. The sticky bit is given by using a "t" with the "o" set. Using the "s" with "o" or using the "t" with "u" or "g" isn't an error, but won't have any effect either. Examples:

  • u=rw,g=r,o= is our ordinary file with no extra properties again.
  • u=rwxs,g=rx,o=rx is a set UID program. (This is passwd again.)
  • u=rwx,g=rxs,o=rx is a set GID program. (This is screen again.)
  • u=rwx,g=rwx,o=rwxt (or a=rwxt) is a directory with the sticky bit. (This is /tmp again.)

Access Control Lists

Our filesystems also support POSIX Access Control Lists (ACLs). We don't recommend using them unless you have a specific reason to do so, because they can easily add a confusing amount of complexity to your file permissions. Still, we're mentioning them, if briefly, for completeness.

The standard Unix permissions allow you to specify permissions for exactly one account (which is almost always your account), exactly one group, and "everyone else". Sometimes you might want more flexibility than that. You might, for example, want members of one group to be able to change a file, members of another group to be able to read it, and no access for everyone else. The standard Unix file permissions can't do that.

Enter ACLs.

ACLs are things you attach to files and directories that basically just list additional accounts and groups with permissions specific to each account and group. You look at ACLs with the getfacl command and set them with the setfacl command. If a file or directory has ACLs, it will show a "+" symbol at the end of the ls -l permission listing, like the README file here:

-rw-r-----+ 1 account users 4153 Apr 16  2013 README

ACLs (unlike standard Unix permissions) have only one format, which is used for both setting and displaying them:

permission-set:account-or-group:permissions

"permission-set" is one of "user", "group", and "other". (When setting ACLs, you can abbreviate those to "u", "g", and "o".) "account-or-group" is the account name for "user" ACLs and the group name for "group" ACLs. If you leave the "account-or-group" section empty, you'll affect the equivalent standard Unix permission set. (So setfacl -m group::rw file is the same as chmod g=rw file.) "permissions" is some combination of "r", "w", and "x", for read, write, and execute permissions, or a "-" to signify no permissions. ACLs don't have the extra properties for set UID, set GID, and sticky bit.

The output of getfacl will look something like this:

# file: README
# owner: account
# group: users
user::rw-
user:bob:r--
group::---
mask::r--
other::---

That shows that the "bob" account has read access to the file, even though no one (aside from the owner) has any permissions for it. (We'll cover the "mask" line shortly.)

To add an ACL to a file (or to change the permissions on an existing ACL), use setfacl -m :

setfacl -m u:bob:rw file

To remove an ACL, use setfacl -x, without the permission section of the ACL:

setfacl -x u:bob file

One nonintuitive thing that comes up with ACLs is the ACL mask. As soon as you add an ACL to a file, you will see a "mask" line show up in the getfacl output in addition to the ACL you added. The works a little like the symbolic representation of a umask: it gives the maximum permissions allowed to any account or group with its own ACL. It is also what's shown in the "group" section of the output of ls -l.

To repeat that for emphasis: Once you add an ACL to an object, ls -l will show the ACL mask in its middle set of permissions, not the permissions corresponding to the group that owns the object. The README example above shows this: the users group has no permissions for the file even though ls -l shows "-rw-r-----+".

Normally, setfacl will set the mask appropriately for the ACLs on the file. In some circumstances, especially if you use chmod on a file with ACLs, the mask may get out of sync with the other ACLs, in which case getfacl will show things like this:

user:bob:rw-                    #effective:r--
mask::r--

That means, roughly, "bob has an ACL that should give him read and write permissions, but because of the mask, he'll really only have read permissions."

To reset the mask, you can run:

setfacl --mask -m m::- file

Finally, directories can have "default ACLs". They have the same format as regular ACLs, but with "default:" at the beginning. (You can shorten that to "d:" if you want.) When a file is created in a directory with default ACLs, it automatically gets ACLs based on the defaults. When a directory is created in a directory with default ACLs, it gets ACLs based on the defaults (just like a file) and also gets its own copies of the default ACLs. Here's an example:

$ mkdir example
$ setfacl -m default:user:bob:rw example
$ touch example/foo
$ getfacl -c example/foo
user::rw-
user:bob:rw-
group::---
mask::rw-
other::---

In summary, ACLs are useful, but can be potentially confusing (especially if you set them and then forget about them later). We don't really recommend using them unless you absolutely need to do so.

SELinux

Keen-eyed viewers might have noticed that the output of ls -l includes a "." at the end of the permission listing. (Except for files with ACLs, where the ACL "+" takes precedence over the ".".) That dot serves as an indication that the file has an SELinux security context.

Fortunately, you should never need to worry about SELinux. We use it on our systems, but the systems should be configured in such a way that SELinux never prevents you from doing something that you should be allowed to do. (We're mentioning it here just so you know what that little dot means.)