Unix File Permissions

Unix File Permissions

Estimated Reading Time: 12 minutes



The permissions system in Unix is one of those things that you just need to understand if you’re going to work with Linux (or indeed, any other derivatives of Unix). There are already many great articles about file permissions online; however, this is a topic that I keep getting asked about, so I’m going to write it up in my own way. If you’re struggling to understand how file permissions work in Unix then hopefully this post will be of use to you.


Basic Understanding:

At its core, the aim behind having file permissions is to limit access to a file or directory — this holds true across all operating systems. In Unix there are three basic types of permission: read, write, and execute. These are exactly as they sound: if you have permission to read a file then you can open it; if you have permission to write to a file then you can edit it; and if you have permission to execute a file then you can run it as a program (this, obviously, will only work if the file actually is a program). There permissions can be mixed and matched, so you might have permission to read and execute a particular file, but not write to it.

We format these permissions like this: rwx, for read, write and execute respectively.
If we were missing the permission to write to the file then it would look like this: r-x, with a dash replacing the w for write. Similarly, if we can only execute the file (but not read or write to it), then it would look like this: --x.

That’s all well and good, but how do you separate different types of user? For example, say you have a file that you want to share with someone, but you don’t want them to be able to write to it? You still need to be able to edit it yourself, but you don’t want everyone to be able to make changes!

For this, Unix gives us three classes of permission: owner, group and world. Once again, these are exactly as they sound. For every file, there are a separate set of permissions for the person who owns the file, the group that owns the file, and everyone else. These permissions are chained together one after the other, so you would have the three permissions of the owner, immediately followed by the three permissions of the group, and the three permissions of world.

In the end it looks like this: rwxrwxrwx. You have a full set of permissions (rwx) for the owner of the file, the group that owns the file, and everyone else.

Let’s take the example from before. You’ve got a file that you need to be able to read and edit, but you don’t want anyone else to be able to edit it. You might change the permissions to be something like this:

rw-r--r--

Here, the owner can read and write, the group can read, and everyone else (i.e. world) can also read.

Let’s take another example. You’ve got a really important document that you don’t want anyone to be able to edit. You want to be able to read it yourself, but you want to keep it completely hidden from everyone else. To be completely safe, you might want to remove your own write permission. The full permissions would look like this:

r--------

This is almost completely locked down. The owner can read (and do nothing else); everyone else can see that the file exists, but can’t actually interact with it in any way.

In this way you can specify who is allowed to access individual files (or entire directory trees). We’ll get a bit more in depth with this later on, but for now, let’s have a look at the alternative way of specifying file permissions.


Octal Format:

The octal format of specification works on the same rwx principle as with the symbolic format (which we looked at in the previous section). I personally find this method to be a lot cleaner, however, which version you prefer is obviously an individual preference.

With the octal format, each of the permissions is assigned a value:

r = 4
w = 2
x = 1

rwx
421

To specify a permission, we add these numbers together; so rwx would be 4 + 2 + 1 = 7, and r-x would be 4 + 1 = 5.

With this in mind, we can format permissions for user, group and world in exactly the same way as previously, by treating them as three sets of read, write and execute permissions that we chain together.

Let’s go back to our very first example. You’ve got a file you need to read and write to, but you want to prevent anyone else from writing to it. In symbolic format that would be rw-r--r--. In octal format we would convert each of the three “blocks” into its octal equivalent, thus giving us a permission of 644 (rw = 4 + 2 = 6, r = 4).

rw- r-- r--
420 400 400
644

Let’s try one more new example. You have a file that you want full access to. You want the group to have no access, but everyone else to be able to read and write to this file. See if you can work out what this would look like in symbolic answer. The answer is below (click to reveal):

rwx---rw-

Let’s think about how this would look in octal format.

We have our three sets of permissions:

Owner: rwx
Group: ---
World: rw-

Let’s start with the owner. All three permissions are activated, so we have 4, 2 and 1. Add them together and we get 7.

The group permissions are easy — there are none, so it’s just 0.

Everyone else can read and write, so we have 4 and 2. Add them together and we get six.

Hence rwx---rw- in symbolic format translates into 706 in octal format.


Special Bits:

You should now have a good understanding of how the basic Unix file permissions work. Let’s have a look at something slightly more advanced now.

We know about read, write, and execute — but there are some cases where we need special permissions that these don’t cover.

For example, what happens when you need to execute a file, but as the admin user (root)? A good example of this is the passwd command in Linux. As a low privileged user, you don’t have permission to access the system files which contain the passwords, but you can still change your password with the passwdcommand, so how does this work?

The answer is something called the “SUID” bit.

SUID:

Up until now we’ve seen the read (r), write (w) and execute (x) bits. Now we’re seeing the SUID (s) bit. When this bit is set, it replaces the x in the owner permissions, like so: rws------. What the SUID bit does is allow the file to be executed as the owner of the file, so, in other words, if the command is owned by root, when you execute it then you will be using the root (i.e. admin) permissions. This means that you can use passwd to edit the system password file, without actually having permission to edit it manually!

You can see this in practice here:

File permissions of the passwd command
Permissions for passwd

Notice that the passwd command is owned by root (i.e. the admin). We have permissions to read and execute it as our own user (r-x) — we need these in order to use the SUID bit. Additionally, we also have the SUID bit set (rws) which allows us to execute the command as the owner — in this case root — thus temporarily giving us the permissions of the admin.

SGID:

The SGID bit works almost identically to the SUID bit; however, rather than giving you the permissions of the user that owns the file it gives you the permissions of the group that owns the file. We’re going to discuss groups in detail in the next section, but for now all you need to understand is that the SGID does for groups what the SUID does for the owner of a file. It allows you to execute the program in question with the same permissions as if you were a member of the group that owns the file.

A good example of this is the wall command, which allows you to send messages to all logged in users:

File permissions for the /usr/bin/wall command
Permissions for wall

Notice that in this case the (s) bit is in the second block of permissions, indicating that it’s an SGID, rather than an SUID bit. The command is owned by the user root, but it’s also owned by the group tty, thus when you execute the wall command, you’re executing it with the same permissions as a user who is a member of the tty group.

Sticky Bit:

The final special permission that we’re going to look at is the sticky bit. Whereas SUID and SGID allow you to temporarily obtain greater permissions when executing a single program, the sticky bit acts as a protection mechanism. A file that has the sticky bit enabled can only be renamed or deleted by its owner, or by the root user. In all other respects, normal permissions apply; i.e. if the file is world readable and world write-able (rw-) then any user can read or write to it — they just can’t delete it, or rename it. A good example of the sticky bit is the /tmp directory, which is used to store temporary files. Any user can read and write to the /tmp directory, but they can’t delete any files belonging to another user.

File permissions for the /tmp directory.
File permissions for /tmp directory

Notice the t bit at the end of the permissions list. This signifies that the sticky bit is active. You’ll also see that the d bit at the start of the permissions list is active — this just means that we’re looking at a directory, not a file.

Octal

Unsurprisingly, the special bits can all be referred to in octal format as well. This is done by adding an extra number in front of the three-digit file permission. To reference SUID, we use the number 4. To reference SGID we use the number 2, and to reference sticky bit, we use the number 1. When adding these to a permission definition, we just add them on at the start of the three numbers we used previously.

In other words, full permissions plus the sticky bit would look like this: 1777. Adding SUID to a file that the owner can read and write to, and everyone else can read, would look like this: 4644. Adding the SGID bit to a file that can be read by everyone, and modified/executed by no one, would look like this: 2444.

As with the other octal sets, these can be added together to add more than one special permission. If you wanted to set both SUID and SGID in a file with full permissions (for example), you could use 6777. To add SUID, SGID and sticky bit to a file that is readable by everyone, but writeable and executable by no one, you could use 7444.


Unix Groups:

We’ve talked a lot about the permissions of files in Unix — hopefully you now have a better understanding of how the permission bits work. One thing that I’ve mentioned a lot but not yet covered is the concept of group permissions, so that’s what we’re doing in this section.

The purpose of groups in Unix is pretty much to allow for more advanced permissions to be set. When a new user is created, a new group with the same name is also created. The user is assigned into this group, which becomes their primary group. A user can only belong to one primary group — by default it’s this new one with the same name as them. This is why the majority of the files in the examples I showed you earlier have both the owner and group as being root.

Each user can only belong to one primary group, but they can belong to many secondary groups. Secondary groups are used to logically categorise users. For example, you might want a developer group that has access to tools which you want to prevent everyone else from using. Equally, you might want to make it so that only certain people can read a file. For this you would add the specified users to a secondary group, then change the ownership of the file so that the secondary group holds group ownership. At this point, all members of the group will have the group permissions on that file.

New groups can be added with this command:

sudo groupadd <group-name>

Users can then be added to the group like this:

usermod -aG <group-name> <user-name>

Setting Permissions:

Right, now for the fun stuff!

We’ve talked a lot about the theoretical stuff, now let’s talk about how you would set file permissions.

Permissions are set using the chmod command. We can do this in either format, however, I prefer octal, so let’s start there. Let’s say that we want to set a file so that owner can read and write, group can read, and world has no permissions at all. The octal for this is 640. Thus the command would be: chmod 640 <filename>

Say we want to give everyone full permissions, the octal for this is 777. We would edit the file like so: chmod 777 <filename>.

In many ways octal is harder to understand, but easier to implement — as you’ll see as we do the same thing symbolically.

Let’s go back to that first example. We want the owner to be able to read and write, group should be able to read, and world can’t do anything. Symbolically, it looks like this: rw-r-----.

Setting these file permissions symbolically would look like this:
chmod u=rw,g=r <filename>

For our other example (everyone can do anything), it would look like this: chmod u=rwx,g=rwx,o=rwx <filename> (o stands for “others” — i.e. world). You can specify the special bits in exactly the same way (e.g. for SUID: chmod u=s <filename>). This is the long way of doing it — please have a look at the man page for chmod to learn some of the shorthand methods.

That handles setting permissions, but what if we want to just update the current permissions?

Instead of using =, we can use + or - to modify the permissions of a file. For this I’m going to use an example:

Example image showing how to change file permissions in practice with symbolic format
Changing Perms

In this example we start with a file which has full permissions (rwxrwxrwx or 777). We first remove the owner write permission (u-w). Next we remove all permissions from the group (g-rwx). Finally we add the SUID bit, whilst simultaneously removing write and execute permissions from world (u+s,o-wx).

Let’s do the exact same thing with octal format:

Example image showing how to change file permissions in practice with octal format
Changing Perms

Notice that this is altering the permissions in exactly the same way. The first modification (-200) subtracts write permissions from the owner. The second transformation (-070) subtracts all permissions from the group. The final transformation (+4000,-003) first adds the SUID bit, then subtracts write and executre permissions from world.

The chmod command is incredibly powerful. When used with precision you can use it to get the ideal permissions for your purposes, meaning you can lock files down with as much accuracy as you need.


Changing File Ownership:

Last but not least, let’s take a quick look at changing ownership of files. As mentioned previously, all files have a group owner, as well as a user owner. The command to alter these is called chown. We use it like this:
chown <user>:<group> <filename>

If you just want to change the user then you could do:
chown <user> <filename>

Similarly, if you just want to change the group then you could use:
chown :<group> <filename>

(There is another command that could do the same thing: chgrp; however, I find that remembering one command is a lot easier)

Going back to our test file, in the following example I am first changing the owner to be bob. I am then changing the group to be dev. Finally, I am transferring full ownership back to root:

Demonstrating the chown command in Linux
chown demonstration

Worked Example

You now know how to work with file permissions in Unix. Let’s do one worked example, starting from a completely new file and locking it down appropriately.

Lets say that we’ve got a file called Diary.txt. We want to share it with Bob, but not with anyone else on the system. Bob should be able to read it, but not write to it. The root user (i.e. us) should be able to read and write to the Diary.

Let’s get started!

First we’re going to create the file. It’s got the default permissions of 644:

Created Diary.txt
Created the Diary.txt file

We don’t want this to be world readable, so let’s start by removing the r bit from world:

Removing the read permission from world
Removing read permission from world

The permissions look to be set up nicely, but how are we going to let Bob read the diary? Let’s make a new secondary group called Diary, then add Bob into it:

Creating a new "Diary" group and adding bob into it
Initialising group

Now all that we need to do is change the group ownership of Diary.txt so that it’s group owned by our new Diary group:

Changed ownership of Diary.txt to root:Diary
Final Permissions

Et Viola! We have a diary that root can read and write to, members of the Diary group (of which our specified user — bob — is a member) can read the diary, and world is completely shut out.

A job well done!


Final Thoughts

Well, what was originally designed to be a quick post turned into rather a long post! Hopefully you’ve learnt something from it. If you want to do any further research, remember that Google is a valuable resource, and the man pages in Linux are an absolute godsend. Similarly, if you’ve got any questions, please feel free to drop ’em into the comments section, or use the contact form at the top of the page!

One thought on “Unix File Permissions

  1. This was simply amazing, and invaluable. I came across your writeup in tryhackme in the Learn Linux room and just wanted to say that I was struggling with this bit until I read this article. You broke it down nicely and progressed in a very clear and concise, easy-to-follow way. I appreciate the work you’re doing and look forward to reading more by you!

    Shane

Leave a Reply

Your email address will not be published. Required fields are marked *

Enter Captcha Here : *

Reload Image