File permissions in Linux
Linux is a file-based system, it considers directories, drives, devices, etc as files. The actions you are allowed to perform on a Linux system depends on the permissions you have to these files.
The primary permissions
The three primary permissions are read, write, and execute. They have different meanings when applied to files and directories.
Files
Read Permission: Allows you to read the contents of a file. You can cat the contents of a text file to the terminal or open a file using an application.
Write Permission: Allows you to modify the contents of a file.
Execute Permission: Allows you to execute the file. This permission is relevant only for executable files, which may be binary files or script files like BASH script, Perl script, etc. For a script file execute permission is useless unless it has read permission as well since some interpreter needs to read the file.
Directories
With directories, the permissions are not as straightforward.
Read Permission: Allows you to see the contents of a directory. You can list the contents of a directory in the terminal or open the directory in a file manager. Denying read permission does not make the contents of the directory read proof. The directory is a special file that contains a list of files and subdirectories inside it. Without read permission, you cannot read the contents of this special file. But if you already know a file exists in the directory and has read permission to the file, you can read the file.
Write Permission: Allows you to create and delete files and subdirectories in the directory, provided that you also have execute permission. If a write-protected directory is empty it can be deleted as long as you have write permission to its parent directory.
Execute Permission: Without execute permission the only thing you can do with a directory is to list the names of its contents. To use the path to a directory for any other operation you need execute permission. For example, you cannot CD into the directory or view the contents of a file in the directory or remove a file from a directory since you need to use the path to the directory for these operations.
Users, groups, and others
The permission you have on a file depends on your role in relation to the file. These roles could be the following.
User: A user is effectively the owner of the file. When you create a file, by default, you will be the user of the file. This can be changed later.
Group: If a user belongs to the same group which the file belongs to, the user will have group permissions. Note: conditions apply, see below about cumulative permissions.
Other: Somebody who is neither a user or have group permission.
Permissions are not cumulative
Permissions in Linux are not cumulative and it goes in the order user, group, and then other. If you are a user you get only the permissions of the user; group permissions and other’s permissions do not apply to you. If you are not a user but a group member, you get only group permissions, you will not get other’s permissions along with it. This is usually not an issue since permissions tend to decline as we go from user to group to others, but might cause confusion in rare cases.
Viewing file permissions
Use the ls -l
command to view file permissions.
1av@ubuntu:~$ ls -l script.sh
2-rwxr-xr-- 1 av av 10 May 18 14:39 script.sh
– | Type of file. |
rwxr-xr--
|
Read, write and execute permissions for owner, group, and others |
1 | Number of links |
av | User |
av | Group |
10 | Size |
May 18 14:39 | Date and time |
script.sh | Filename |
File Types
The type of file can be any of the following:-
Symbol | Description |
---|---|
– | Normal file |
d | Directory |
l | Link |
p | Named Pipe |
c | Character Device |
b | Block Device |
tip: To view permissions of a directory use the command ls -ld <directory name>
The permission string
The nine characters coming after the filetype is what represents the file permissions. The first three letters represent permissions for the user, the next three letters represent permissions for the group and the last three letters represent permissions for others (everyone else). The permissions are written in the order read, write, execute. A dash represents a lack of that particular permission.
Changing Permissions with chmod
You can use the chmod command to change file permissions. The chmod command has two forms the numeric form and the symbolic form.
Numeric method
In the numeric method, we normally use three octal (base 8) numbers to specify permissions. A fourth leading-digit can be used to specify some special permissions but this is optional. The special permissions are discussed later in the article.
Priority | Octal | Binary |
---|---|---|
No Permission | 0 | 000 |
Execute | 1 | 001 |
Write | 2 | 010 |
Read | 4 | 100 |
The permissions are powers of 2 in the reverse order they are listed by the ls -l command. To learn how to use these numbers, let us start with the simplest possible example. Let us say we want to give only read permission to the user, group, and others. Here is the command:-
1av@ubuntu:~$ ls -l help.txt
2-rw-rw-r-- 1 av av 0 Jun 12 16:38 help.txt
3av@ubuntu:~$ chmod 444 help.txt
4av@ubuntu:~$ ls -l help.txt
5-r--r--r-- 1 av av 0 Jun 12 16:38 help.txt
At the start, the file help.txt has rw-rw-r--
permission, then we run the chmod command. We end up with the permission r--r--r--
. The first 4 in chmod gives read permission to the user, the second 4 gives read permission to the group and the last 4 gives read permission to others. This is an easy to remember order since permissions are listed in the order user, group, and then others.
One thing to note about the numeric method of chmod is that existing permissions do not matter, the command starts with a clean slate. Since we asked for only read permission we get only that, the previous permissions that used to be there are gone.
Now we need to learn how to give additional permissions. Let us say we want read and write permission for users and group and read permission for others. How are we going to do that with only three digits to specify the permissions? We just add the numbers: read + write = 4 + 2 = 6. So our permission number will be 664.
1av@ubuntu:~$ chmod 664 help.txt
2av@ubuntu:~$ ls -l help.txt
3-rw-rw-r-- 1 av av 0 Jun 12 16:38 help.txt
If we have a script file and need the following permission:
user: read, write and execute = 4+ 2+ 1 = 7
group: read and execute = 4 + 1 = 5
other: read = 4
1av@ubuntu:~$ chmod 754 script.sh
2av@ubuntu:~$ ls -l script.sh
3-rwxr-xr-- 1 av av 10 Jun 12 18:34 script.sh
Symbolic method
With the symbolic method, we can tweak existing permissions. Let us see what the various symbols represent.
Symbol | Role |
---|---|
a | All |
u | User |
g | Group |
o | Other |
The permissions are represented by r, w and x as you would expect, we have already seen that in the output of ls -l. The symbolic method has mainly three forms:
- Add permissions to the existing set.
- Remove permissions from the existing set.
- Assign brand new permissions instead of old ones. This form is similar to the numeric method, but the symbolic method supports more fine-grained control.
To give execute permission to all users:
1av@ubuntu:~$ ls -l script.sh
2-rw-r--r-- 1 av av 10 Jun 12 18:34 script.sh
3av@ubuntu:~$ chmod a+x script.sh
4av@ubuntu:~$ ls -l script.sh
5-rwxr-xr-x 1 av av 10 Jun 12 18:34 script.sh
Notice the important difference between the numeric method and the symbolic method, here execute permission was given to all but the other existing permissions remained unchanged.
To give write permission to group and others:
1av@ubuntu:~$ ls -l script.sh
2-rwxr-xr-x 1 av av 10 Jun 12 18:34 script.sh
3av@ubuntu:~$ chmod go+w script.sh
4av@ubuntu:~$ ls -l script.sh
5-rwxrwxrwx 1 av av 10 Jun 12 18:34 script.sh
To remove write and execute permission from others:
1av@ubuntu:~$ ls -l script.sh
2-rwxrwxrwx 1 av av 10 Jun 12 18:34 script.sh
3av@ubuntu:~$ chmod o-wx script.sh
4av@ubuntu:~$ ls -l script.sh
5-rwxrwxr-- 1 av av 10 Jun 12 18:34 script.sh
You can also combine more than one addition or subtraction in a single command:
1av@ubuntu:~$ ls -l script.sh
2-rwxrwxr-- 1 av av 10 Jun 12 18:34 script.sh
3av@ubuntu:~$ chmod g-w,o+x script.sh
4av@ubuntu:~$ ls -l script.sh
5-rwxr-xr-x 1 av av 10 Jun 12 18:34 script.sh
If you want functionality similar to the numeric method, use the equals option. With equals you only get the permissions you ask for, the earlier permissions are erased.
1av@ubuntu:~$ ls -l test/1.py
2-rwxrwxr-- 1 av av 0 Jun 13 11:36 test/1.py
3av@ubuntu:~$ chmod u=rwx,g=rx,o=rx test/1.py
4av@ubuntu:~$ ls -l test/1.py
5-rwxr-xr-x 1 av av 0 Jun 13 11:36 test/1.py
As with adding and removing permissions, setting absolute permissions using equals can be done for selective roles. Here the permission of others is completely replaced with a new set of permissions but the permissions of users and group remain untouched.
1av@ubuntu:~$ ls -l test/1.py
2-rwxr-xrwx 1 av av 0 Jun 13 11:36 test/1.py
3av@ubuntu:~$ chmod o=rx test/1.py
4av@ubuntu:~$ ls -l test/1.py
5-rwxr-xr-x 1 av av 0 Jun 13 11:36 test/1.py
Changing Permissions of multiple files
The chmod -R option can be used to change permissions on multiple files.
To give read permission to all files and directories in the test directory to others:
1chmod -R o+r test/
You can also use the find command to find the files you want and then run chmod on them. To give execute permission to the user to all py files in the test directory:
1find test/ -iname "*.py" -exec chmod u+x {} \+
Numeric method vs Symbolic method
If you know the full set of permissions that a file must have then the numeric method is a very concise way to specify that. For small tweaks to existing permission, the symbolic method is easier. To tweak existing permissions on a large number of files, the symbolic method is required. For example, to give others read permission to all files in a directory without touching other existing permissions, you need the symbolic method.
Special permissions
We have already seen read, write, and execute permissions. Now let us look at setuid, setgid, and the sticky bit. These permissions are not commonly used but are useful in some situations.
tip: Special permissions work as intended only if execute permission is also set.
Setuid
Setuid is a risky addition to execute permission for users. To understand this permission let us look at a use case. You can use the passwd command to change your password. This command does not require root privileges, but the passwords are stored in /etc/shadow file which does require root privileges, as you would expect.
1av@ubuntu:~$ ls -l /etc/shadow
2-rw-r----- 1 root shadow 1163 Mar 21 18:02 /etc/shadow
So how did a user process manage to change a file belonging to the root? Setuid is the answer; see the permissions for the passwd executable file.
1av@ubuntu:~$ ls -l /usr/bin/passwd
2-rwsr-xr-x 1 root root 59640 Mar 23 2019 /usr/bin/passwd
The file belongs to the root, but it has an s where user execute permission would normally be. This allows the file to be executed by any user with privileges of the owner, root in this case. Needless to say, this option should be used with extreme caution.
Why setuid?
So why is it okay for passwd to use setuid? It is because the passwd program has a narrow, clearly defined scope. It does not allow ordinary users to perform unsafe operations. If you use setuid on something like mv or rm there would be absolute chaos. What benefit do we get from using setuid for passwd? The user needs access to a root file where the password is stored. The only alternative is to force the user to acquire root privileges temporarily. This is unnecessary and counter-productive for an otherwise safe command like passwd.
How to give setuid permission
Use the following command to allow setuid permission.
1av@ubuntu:~/test$ chmod u+s hello.py
2av@ubuntu:~/test$ ls -l hello.py
3-rwsrw-r-- 1 av av 0 Jun 13 11:36 hello.py
Setgid
Setgid is similar to setuid, the only difference is that in setgid the program runs with group permissions instead of user permissions. To give setgid permission to a file, use the following command:
1av@ubuntu:~/test$ chmod g+s hello.py
2av@ubuntu:~/test$ ls -l hello.py
3-rwxrwsr-- 1 av av 0 Jun 13 11:36 hello.py
Notice that the output of ls -l command has an s where group-execute permission would normally be.
Sticky Bit
The sticky bit is a special permission that is applicable to directories. It is useful for shared directories where everyone must have write access. The problem with such a directory is that anyone who can write to the directory can also delete files from it. So a user can delete files belonging to other users even if they have no permission to the file itself. The sticky bit can solve this problem. If sticky bit is set on the directory, users can delete only those files which they own. To set the sticky bit use the following command:
1av@ubuntu:~$ chmod +t test/
2av@ubuntu:~$ ls -ld test
3drwxrwxrwt 4 av av 4096 Jun 13 12:39 test
Notice that, in the output of ls -l there is a t where group-execute permission would normally be.
tip: If a special permission is set without corresponding execute permission, the s and t symbols would be capitalized in the ls -l output.
Numeric method for special permissions
As mentioned earlier, the numeric method of chmod has an optional leading digit to represent special permissions. The numbers representing special permissions are as follows.
Number | Permission |
---|---|
1 | Sticky Bit |
2 | Setgid |
4 | Setuid |
To set the sticky bit on a directory, use the following command
1av@ubuntu:~$ chmod 1777 test/
2av@ubuntu:~$ ls -ld test/
3drwxrwxrwt 4 av av 4096 Jun 13 12:39 test/
As earlier, you can combine permissions by adding the numbers.