Unix File Permission Primer

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, since they don't have anything to do with file permissions.)

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 members of the file's 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. ("-" means it's a regular file. Other types include (with their signifying characters in bold) block special file, character special file, directory, symbolic link, named pipe, and socket. Anything else gets a "?", but you'll probably never see that character.) 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 and permission set 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 an existing 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 all of the 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 three 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:

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 tcsh, which is used by many accounts on our systems) 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 used to be tcsh, which only understands octal notation for permissions. Symbolic notation will not work. Many of our accounts still use tcsh. To determine which shell you're using please see our shells page.

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

Access Control Lists (ACLs) are a more complex way of managing permissions that work in addition to the standard permissions described above. They are capable of handing certain situations that are simply not possible with the standard permissions. Unfortunately, they add a significant amount of complexity, so we don't recommend using them unless there's no other way to accomplish your goals. (And remember, when in doubt, you can always email support@cs.jhu.edu for help with our systems.)

That said, we do have a limited amount of documentation about using ACLs on our systems. Please see our page on NFSv4 Access Control Lists.


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.)