File system permissions in Linux are a little bit different than permissions in Microsoft Windows. File system permissions in the UNIX world use the POSIX standard, which basically says that every file and directory is owned by both a user and group. Every user has a primary group membership. When any any file is created by that user the file is automatically given ownership to the user who created it and the primary group of the user who created it. This is how we enable sharing of files between different users.
Every file has an inode (information node) that stores information about the file, including when the file was last modified, file size, data block location, permissions, and ownership (remember, directories are also files in the Linux system). The portion of the inode that stores permission information is called the mode.
Types of Permissions
In Linux there are three types of permissions. We sometimes refer to them as the triple triple. We said that every file is owned by both the user and the group, but there’s also a world ownership, which is basically the everyone group, and it gets a set of permissions as well. So, the mode has three sections:
- User (owner) permissions
- Group (group owner) permissions
- Other (everyone on the Linux system) permissions
Each permission section can contain three types of permissions:
- Read (r) – enables us to open and read the file, and to list directory contents if the execute permission is also present
- Write (w) – enables us to open, read, and edit the file. When it comes to folders, we can add, delete, and rename files if the execute permission is also present
- Execute (x) – enables us to execute the file (if it’s a program file) or the shell script. When it comes to directories, we can enter the directory and work with its contents
Unlike in the Windows world, where the file extension tells us whether or not a file is executable or not, file extensions have no meaning to the Linux operating system. Extension is just a part of the file name. The executable bit actually makes the file executable. In the case of directories, the execute bit means we have the ability to enter that directory. We could set our directory permission to not have read or write but have execute and allow us to enter that directory, but not see anything in that directory. This allows us to traverse through a set of directories to get to some nested directories, without having to give read or write permissions to have the ability to see or modify the files in between.
When we identify permissions, we can either use the letter abbreviation (r, w, x), or the octal number that corresponds to the permission. Let’s look at the example.
Keep in mind that the root user has all permissions to files and directories regardless of what the mode indicates.
So, we have three sections and three permissions. On a directory this can look something like this:
drwxr-xr-x
That is a permission string, and as you can see it is broken down in three sets (drwx | r-x | r-x). The first set corresponds to the user owner, the second set corresponds to the group owner, and the third set corresponds to the world owner. Each set is then broken down into a read, write, and execute permission. When we see the dash (-), that states that that permission is not granted. If we see a letter, that permission is granted.
On plain files he would see something like this:
-rwxr-xr-x
The first dash (-) in the permission string, in the first column so to say, actually tells what type of file we are dealing with. Remember, in Linux we have several types of files available. We have both directories and normal files, and we also have files like pipes, block files, character files, and so forth. In those cases we would see their corresponding file type in the first column of the permission string. In the case of directories we see a “d” letter, in the case of normal files we just see the dash (-).
Three sets of permissions, the read, write and execute, can actually be boiled down into binary and represented in octal format. To do that we would just consider each one the triples as its own binary number. If the permission was set we would give it a 1, and if the permission was not set we would give it a 0. So, a binary representation of our last example permissions would look like this:
111101101
We can also take each of those triples and then convert it into an octal number by doing standard binary to decimal conversion. So, the 111 would be 7 (4 + 2 + 1), 101 would be 5 (4 + 0 + 1), and again 101 would be 5 (4 + 0 + 1). So the octal representation of this set of permissions could also be represented as
755
This very important because typically when you set permissions on files, we do have the ability to use the rwx notation, but often it’s a lot quicker to use just the octal representation, like 755 in our case.
SUID
Remember, when a user creates a file (or directory), the user and the user’s primary group receive ownership for the file (or directory). File ownership determines which users are allowed to change the file’s ownership and permissions. Only a file owner and the root user can change file ownership or permissions.
Moving forward, we have to mention that there is a fourth group that we don’t typically see on the standard triple triple permission string. One extra bit is the one that can be notated when we use octal format by adding a fourth bit in the beginning of the string, like this:
0755
This fourth bit is referred to as the SUID (noted as 4), SGID (noted as 2) and sticky bit (noted as 1). SUID stands for Set User ID. If we set SUID (by entering 4), it would look like this:
4755
This would actually change the permission string to this (note the s in the first triplet):
-rwsr-xr-x
That basically means that anybody who executes this file would execute the file as if they were the owner of the file. So if the file is owned by root, and we had the SUID bit set, anybody who executes that, whether they are a common user or a root user, would execute it as if they are a root user. This can have security consequences so it is recommended to use SUID very sparingly, if at all.
SGID
SGID is the same concept as SUID, it would basically change the group owner. If we were to set the SGID bit, we could enter something like this:
2755
This would change the permission string to (note the s in the second triplet):
-rwxr-sr-x
This would do the same this as SUID, just to the group. In other words, whoever executes that file would execute the file with the permissions of the group or would be executing as as if they were a member of the group who owned that file.
It is possible to have both of these set by entering the number 6, like this:
6755
This way we would have both the SUID and the SGID bit set, like this (note the s in the first and second triplet):
-rwsr-sr-x
Now the sticky bit. This bit is probably the most useful of all of these, and is probably the permission that we would use most if we’re going to use this extra permission bit. The sticky bit has changed its meaning over time, but it has settled down to mean basically this: if we set the sticky bit on a file, and do that by setting a 1, like this:
1755
That would change our permission string to this (note the t in the last triplet):
-rwxr-xr-t
Let’s say we want to put a file into a directory and have a number of different people be able to access that file, and we want to give them the ability to write the file, but we don’t want to allow anybody to delete it. To do that, we can set the sticky bit on that file the, which will allow anybody to change the file (if the correct permissions are given), but only the owner of the file could delete the file. This gives some level of protection against, for example, deleting a file by accident. So, with sticky bit we can give write and change permission to the file, while only the owner can delete the file.
Example below sets all three:
7421
The UMask
By default, files receive rw-rw-rw- (666) permissions, and directories receive rwxrwxrwx (777) permissions when they are created. In most cases, the default assignment gives excessive permission to files and directories.
We can customize the default permission assignments by setting a umask. The umask identifies which permissions are removed from the default permissions when files and directories are created.
For example, if a umask value is 022.
0022
This would be 000000010010 (binary).
Let’s say that a default set of permissions for a file is 666. This is 110110110 (binary). So, for example, let’s just look at the last triplet, which is 6 for the default permission, and 2 for the umask:
110 010
Imagine that the 1 in the umask blocks the bits from the default permission to be set. So the resulting permission would be (binary):
100
100 binary is 4 in octal. So, for the default permission of 666, and the umask of 022, the resulting permission would be (octal):
644
On the directories, default set of permissions would be 777. With the umask of 0022, the resulting permission would be:
755
Umasks are useful because it allows us to change the default permissions to be set.