If you are new to the Linux world, you might find yourself scratching your head when it comes to file permissions. Linux file systems use a file permission system implemented by the much older Unix systems.
By looking at the permissions of a file or a directory, the first column represents the permissions, which show a bunch of letters or dashes:
ck@linux ~ $ ls -la /tmp/myfile
-rw-rw-r-- 1 ck ck 0 Sep 11 10:36 /tmp/myfile
The permission column supports 10 characters. The first character is used to indicate the type of file (such as a directory or link), the nine other characters are split into a group of three (User – Group – Others) and represent the actual file permission. Each character group has a set of permissions (Read – Write – Execute).
User – Group – Others
The Unix permissions are based on three different types of access:
- User: Represents the owner of the file or directory. What permissions should the owner have?
- Group: Represents the group the file belongs to. In most cases the user is a member of this group. What permissions should the group have?
- Others: Represents all other users. What permissions should all other users have on this file or directory?
Read – Write – Execute
Each type of access (User, Group, Others) have their own permissions. There are three types of permissions on files:
- Read: Allows the file to be read by the selected access type
- Write: Allows the file to be (over-) written by the selected access type
- Execute: Allows the file to be executed by the selected access type.
Note: On directories the execution permission is needed to change into the directory.
Binary permission numbers: 4, 2, 1
Surely you have seen and heard about the permission "numbers", such as 644, 666, 777 etc. when changing file and directory permissions. Also web-developers come across these permissions when using FTP or SFTP to upload files and change permissions. These numbers represent the summarized binary number for file permissions.
The binary numbers are set the following way:
- Read: 4
- Write: 2
- Execute: 1
Let's take a simple file as an example:
geek@linux ~ $ ls -la /tmp/myfile
-rw-rw-r-- 1 geek geek 0 Sep 11 10:36 /tmp/myfile
Let's start with the user/owner. The user geek has read and write permissions. So we add 4 (read) and 2 (write) = 6. This number represents the first permission for the user/owner.
For the next access type (group) we also see read and write permissions. Again 4 + 2 = 6.
And finally the last access type (others) we see only a read permission, meaning just a 4.
With the permissions number for each access types we come up with : 664 .
Changing permissions
File permissions can be changed using the chmod command. The command supports two syntaxes:
1. Using the permissions on an access type (e.g. user)
Example: Adding write permission to others:
geek@linux ~ $ chmod o+w /tmp/myfile
geek@linux ~ $ ls -la /tmp/myfile
-rw-rw-rw- 1 geek geek 0 Sep 11 10:36 /tmp/myfile
Example: Removing write permission for group:
geek@linux ~ $ chmod g-w /tmp/myfile
geek@linux ~ $ ls -la /tmp/myfile
-rw-r--rw- 1 ckadm ckadm 0 Sep 11 10:36 /tmp/myfile
2. Using the binary number for the permission across all access types.
Example: Setting read-write permissions to all access types:
geek@linux ~ $ chmod 666 /tmp/myfile
geek@linux ~ $ ls -la /tmp/myfile
-rw-rw-rw- 1 ckadm ckadm 0 Sep 11 10:36 /tmp/myfile
Example: Setting read-write permission to user, read to group, none to others:
geek@linux ~ $ chmod 640 /tmp/myfile
geek@linux ~ $ ls -la /tmp/myfile
-rw-r----- 1 ckadm ckadm 0 Sep 11 10:36 /tmp/myfile
File types
As mentioned above, the first of the ten permission characters is used to indicate a Unix file type.
The most common "different" file type is a directory. Looking at the permissions of a directory quickly shows that the first character is a "d", representing a directory:
geek@linux ~ $ mkdir /tmp/mydirectory
geek@linux ~ $ ls -la /tmp | grep mydirectory
drwxrwxr-x 2 geek geek 4096 Sep 11 10:36 mydirectory
Other special file types (non-conclusive list):
- – (dash): Regular file (seen on every normal file)
- d: Directory
- b: Block device
- l: Symbolic link
- s: Socket
Special permissions (setuid, setgid, sticky bit)
Besides indicating a file type, such as directory, the first character can also show whether or not special permissions have been applied to a file or directory. These special permissions are the following.
setuid bit (4)
Additional setuid permission allows a user to run a program with the same permissions as the owner of the file.
To set setuid as additional permission:
geek@linux ~ $ chmod 4755 /tmp/myprogram
geek@linux ~ $ ls -la /tmp/myprogram
-rwsr-xr-x 1 geek geek 26 Sep 11 12:54 /tmp/myprogram
The execution bit for the user has changed from x to s.
A typical example and real-world use case for the setuid is the passwd command:
geek@linux:~$ ls -la /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Nov 29 2022 /usr/bin/passwd
Without the setuid bit applied, a regular user would not be able to execute passwd and change its own password.
setgid bit (2)
Additional setgid permission allows a user to run a program with the same permissions as the group of the file.
If set on a directory, the behaviour of setgid changes. Instead of executing a program, setgid allows a user to create new files in that directory which then belong to the same group as the directory.
geek@linux ~ $ mkdir /tmp/geek
geek@linux ~ $ chmod 2777 /tmp/geek
geek@linux ~ $ ls -la /tmp/|grep geek
drwxrwsrwx 2 geek geek 4096 Sep 11 13:15 geek
tester@linux:~$ touch /tmp/geek/hello.txt
tester@linux:~$ ls -la /tmp/geek/hello.txt
-rw-rw-r-- 1 tester geek 0 Sep 11 13:17 /tmp/geek/hello.txt
sticky bit (1)
The sticky bit is rarely used but is important for world-writeable directories, such as the /tmp directory. As the /tmp directory is writeable by any user, a file could be created by one user and then deleted by another user. With the sticky bit set, the file system allows modification and deletion of a file only by the file owner, the directory owner or root user.
The sticky bit permission can be seen at the very end of the ten permission characters (with a t instead of x):
geek@linux ~ $ touch /tmp/this-file-is-owned-by-geek.txt
geek@linux ~ $ chmod 666 /tmp/this-file-is-owned-by-geek.txt
tester@linux:~$ rm /tmp/this-file-is-owned-by-geek.txt
rm: cannot remove '/tmp/this-file-is-owned-by-geek.txt': Operation not permitted
Common mistakes
The most common mistake is when (non-aware) users want to just grant read write permissions to everyone, e.g. for a web application handling uploads. In many cases a general chmod 777 is then applied. But as we've described above, the additional execution bit is only needed for directories, not for regular files. The correct way to do this would be chmod 666 for regular files and chmod 777 for directories. However this is considered a security risk and you should stick to setting permissions for user and group only.