Changing File and Directory Permissions with chmod

By Alexandru Andrei, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

Linux-based operating systems are multi-user environments. Since it’s expected that multiple users will have access to the same system, basic security mechanisms are implemented. In this tutorial, we will analyze how the level of access to files and directories is decided, based on a set of permissions that we can adjust with the chmod utility. Depending on the rules that are applied, we are able to allow or deny reading, writing and executing specific files. Similarly, it lets us decide which users should be able to browse particular directories and add/remove content to/from them. There are also a few special modes we can set, such as setuid, setgid, sticky and restricted deletion flag, which will be detailed in the following sections.

Even if your particular use case doesn’t involve multiple users having access to the operating system, i.e., only you will be able to log in and browse files on your Elastic Compute Service (ECS) instance, processes such as the Apache web server still run under a dedicated username and file/directory permissions play an important role. Being a service that is accessed remotely (i.e., by other people on the Internet), incorrect permissions may give the public free access to files which are meant to be private, or, they may allow an attacker to exploit a vulnerability and then modify content of your website’s code. Correct permissions, in most cases, will prevent or at least significantly reduce the likelihood of such scenarios.


Launch your instance, connect to it with an SSH client and log in as root.

To understand file/directory permissions, we will first have to go over the basic concepts.

Users and Groups

In some scenarios, you will want to give multiple users the same level of access to the same resource. Let’s say you want a team to be able to edit files of a web application stored on your ECS instance. Since a directory can be owned by only one user, you would have to let the entire team log in as that user, which means they would have to use the same credentials, share the same password, etc. This is not ideal and it’s where groups can help. You can have multiple users (user1, user2, user3) belong to the same group (webeditor). Now, everyone can log in independently, with their own credentials. You can then make the “webeditor” group the owner of the directory and files that make up your web application. Finally, you can add permissions to allow anyone in the “webeditor” group to read and write content.

File and Directory Owners

Create a new user:

adduser --disabled-login --gecos '' user1

Add the user to two supplementary groups, “games” and “users”:

usermod -aG games,users user1

Switch to this user’s environment:

su - user1

Create a file:

touch file1

To see the current owner of the file:

ls -l

The output of the command will look like this:

user1@debian:~$ ls -ltotal 0-rw-r--r-- 1 user1 user1 0 Sep  5 22:56 file1

We can see that the file is owned by user “user1” (first field) and group “user1” (second field). Let’s change the group owner:

chown :games file1

Now ls -l will show:

user1@debian:~$ ls -ltotal 0-rw-r--r-- 1 user1 games 0 Sep  5 22:56 file1

Since “user1” is also part of the “users” group, we can also:

chown :users file1

But if we try to change the group owner to “staff”:

chown :staff file1

Since “user1” is not part of that group, we will get this message:

user1@debian:~$ chown :staff file1chown: changing group of 'file1': Operation not permitted

The syntax of the chown command is: chown user:group /path/to/directory/or/file. As you can see from the examples above, the username can be omitted if we only need to change the group owner, by passing :group as a parameter.

To recursively change owners (perform the same action on all files and subdirectories contained in a directory) you can use the -R parameter in a command such as chown -R user:group /path/to/directory.

Understanding File and Directory Permissions

ls -l /var/

The output may look like this:

root@debian:~# ls -l /var/total 36drwxr-xr-x  2 root root  4096 Sep  4 16:28 backupsdrwxr-xr-x  9 root root  4096 Oct 25  2017 cachedrwxr-xr-x 31 root root  4096 Oct 25  2017 libdrwxrwsr-x  2 root staff 4096 Jul 13  2017 locallrwxrwxrwx  1 root root  9 Oct 25  2017 lock -> /run/lockdrwxr-xr-x  6 root root  4096 Sep  4 16:28 logdrwxrwsr-x  2 root mail  4096 Oct 25  2017 maildrwxr-xr-x  2 root root  4096 Oct 25  2017 optlrwxrwxrwx  1 root root  4 Oct 25  2017 run -> /rundrwxr-xr-x  4 root root  4096 Oct 25  2017 spooldrwxrwxrwt  2 root root  4096 Sep  4 16:28 tmp

Let’s break down the following line: drwxrwsr-x 2 root mail 4096 Oct 25 2017 mail. In the first field, drwxrwsr-x, the first letter, d signifies that the object is a directory. If the first character would be - it would denote a file and l would indicate a symbolic link. After that, we have the permissions: rwxrwsr-x. The first three letters denote user (owner) permissions, the next three group permissions and the last three, permissions for all of the other users on the system. The order is always rwx, rwx, rwx for user, group, other, and where you will find a - instead of a letter it means that particular permission is non-existent/denied. x may sometimes be replaced by s, S, t or T which indicates special types of flags have been set.

Let’s see what the letters mean. For files:

  1. r -- readable
  2. w -- writable
  3. x -- executable (for programs/scripts)
  4. - -- permission denied (r-x would denote that you can read and execute file but not write to it, rw- that you can read and write but not execute)
  5. s -- File is executable and will set user (setuid) or group ID (setgid) on execution. The process will execute with the file's user owner ID and/or group owner ID, regardless of the user that launched the program, e.g., if the user nobody runs a file with properties such as -rwsr-xr-x 1 root root 40536 May 17 2017 /bin/su, su will run as the root user.
  6. S -- File has set user/group ID on execution enabled but is not executable (although possible to set permissions in such a way, it serves no purpose).
  7. t or T -- Sticky bit; can be set on files but does nothing on Linux (on other operating systems it may have some effects).

For directories, permissions are interpreted in a slightly different way:

  1. r -- Contents can be listed with a command such as ls name_of_directory. Always used in conjunction with x to be useful. A readable but not executable directory can be listed with a command such as ls name_of_directory but the contents themselves cannot be read or written to and programs cannot be run, even if the readable, writable, executable bit is set on those files.
  2. w -- You can add files and subdirectories, delete or rename contents within.
  3. x -- You can "execute" directory contents, meaning you can read (readable) files, write to those files (if the files themselves have the write permission enabled) and run programs (if executable bit is set on them).

To more easily remember the effects of these permissions you can think that they focus more on the structure of a directory rather than the objects it contains: with r you can read the structure, see the table of contents, with w you can change the structure and with x you can execute/take action (read, write, run) on any part of that structure.

  1. s -- Set group ID: the directory is executable and every file/subdirectory created in it will automatically inherit the group owner. From our example above /var/mail has the following permissions: drwxrwsr-x 2 root mail 4096 Oct 25 2017 mail. This means that any file/directory that any user creates there will automatically be owned by the "mail" group (even if the user doesn't belong to this group). Although s can also be set for user permissions, instead of group, it has no effect on Linux. The files will still be owned by the user that created them, not by the user owning the directory.
  2. S -- The directory has the set group ID/set user ID flag enabled but is not executable.
  3. t -- Restricted deletion flag enabled and directory is executable by other users. This is useful on directories shared between multiple users. Normally, whoever can write content in a directory, can also delete it, even if they don't own that content. The restricted deletion flag prevents that and allows users to delete only content that they own.
  4. T -- Restricted deletion flag enabled but directory is not executable by other users.

How to Use the chmod Command

mkdir directorymkdir directory/subdirectorytouch directory/file{1..3}

Let’s break down one of the syntax forms chmod has: chmod [ugoa][-+=][rwxXst] /path/to/file/or/directory. u stands for user, to change user permissions. g is for group and o is for others. a means all, altering permissions in the same way for all three categories, user, group and others. - removes permissions and + adds, leaving unmentioned flags unchanged, = sets them to exactly the values specified and removes all unmentioned permissions. rwxXst are the permissions we have described in the previous section (X will be explained in an example below). It's easier to understand when we see the effects:

ls -l

We should get an output similar to:

user1@debian:~$ ls -ltotal 4drwxr-xr-x 3 user1 user1 4096 Sep  5 23:36 directory-rw-r--r-- 1 user1 users  0 Sep  5 22:56 file1

“file1” can be read by other users. Let’s say we want to make it private:

chmod o-r file1

Now the read permission should be removed for other users:

ls -l


user1@debian:~$ ls -ltotal 4drwxr-xr-x 3 user1 user1 4096 Sep  5 23:36 directory-rw-r----- 1 user1 users  0 Sep  5 22:56 file1

If we want other users to be able to read, write and execute the file:

chmod o+rwx file1

Let’s list files again:

ls -l


user1@debian:~$ ls -ltotal 4drwxr-xr-x 3 user1 user1 4096 Sep  5 23:36 directory-rw-r--rwx 1 user1 users  0 Sep  5 22:56 file1

Now if we want to get back to the same way it was, readable by other users, we would have to remove the w and x permissions with o-wx or, we can make use of the = sign:

chmod o=r file1

New output of ls -l:

user1@debian:~$ ls -ltotal 4drwxr-xr-x 3 user1 user1 4096 Sep  5 23:36 directory-rw-r--r-- 1 user1 users  0 Sep  5 22:56 file1

Multiple types of permissions can be set simultaneously, by separating them with commas:

chmod u=rwx,g+w,o= file1

ls -l output:

user1@debian:~$ ls -ltotal 4drwxr-xr-x 3 user1 user1 4096 Sep  5 23:36 directory-rwxrw---- 1 user1 users  0 Sep  5 22:56 file1

We also learned how to clear all permissions, by using o=. If you don't specify any values after the = sign, all permissions of that type are removed.

Another way to specify permissions, which can be faster to type, is by using octal values. This is done by considering that the r, w, x flags are either ON (1) or OFF (0) and then converting the resulting binary value (base 2) to an octal value (base 8).


Binary Value


Octal Value


Resulting Permission


So instead of writing a command such as chmod u=rwx,g=rx,o= file1 to get the resulting permission rwxr-x---, we can simply write:

chmod 750 file1

And ls -l will confirm our change:

user1@debian:~$ ls -ltotal 4drwxr-xr-x 3 user1 user1 4096 Sep  5 23:36 directory-rwxr-x--- 1 user1 users  0 Sep  5 22:56 file1

To enable the setuid flag for a file:

chmod u+sx file1

u+s is actually what enables setuid, but we will also have to make the file executable if it isn't already so, otherwise the setuid flag wouldn't have much use. To enable the set group ID flag, we just change u to g: chmod g+sx file1.

The same commands hold true for directories, but in their case we also have the restricted deletion flag we can make use of:

chmod +t directory

New state of files/directories:

user1@debian:~$ ls -ltotal 4drwxr-xr-t 3 user1 user1 4096 Sep  5 23:36 directory-rwsr-s--- 1 user1 users  0 Sep  5 22:56 file1

Just like with chown, we can add the -R parameter to recursively apply changes to everything contained in a directory:

chmod -R o= directory

And we can see that all permissions for other users have been disabled:

user1@debian:~$ ls -l directory/total 4-rw-r----- 1 user1 user1  0 Sep  5 23:36 file1-rw-r----- 1 user1 user1  0 Sep  5 23:36 file2-rw-r----- 1 user1 user1  0 Sep  5 23:36 file3drwxr-x--- 2 user1 user1 4096 Sep  5 23:36 subdirectory

It’s also possible to apply the same changes to all three types of permissions (user, group and other) by using a (meaning all):

chmod -R a-x directory/*

Here, we used directory/* instead of directory/, to apply actions on contents but not on the directory itself. Now that the executable flag is removed from all objects in "directory", we can exemplify another useful parameter of the chmod command.

ls -l directory will show us that all contents are non-executable:

user1@debian:~$ ls -l directorytotal 4-rw-r----- 1 user1 user1  0 Sep  6 00:28 file1-rw-r----- 1 user1 user1  0 Sep  6 00:28 file2-rw-r----- 1 user1 user1  0 Sep  6 00:28 file3drw-r----- 2 user1 user1 4096 Sep  6 00:28 subdirectory

Which is problematic for directories since now creating files in “subdirectory” will fail:

touch directory/subdirectory/file


user1@debian:~$ touch directory/subdirectory/filetouch: cannot touch 'directory/subdirectory/file': Permission denied

It’s easy to just make “subdirectory” executable again but what if we had hundreds of files and subdirectories? We couldn’t just run chmod -R u+x directory since that would also make files executable, not only directories. To recursively add the executable flag only to directories, but not files, we can use capital X, like in the following command:

chmod -R u+X directory/

And ls -l directory/ will confirm that the executable flag has only been added to "subdirectory":

user1@debian:~$ ls -l directory/total 4-rw-r----- 1 user1 user1  0 Sep  6 00:28 file1-rw-r----- 1 user1 user1  0 Sep  6 00:28 file2-rw-r----- 1 user1 user1  0 Sep  6 00:28 file3drwxr----- 2 user1 user1 4096 Sep  6 00:28 subdirectory


Follow me to keep abreast with the latest technology news, industry insights, and developer trends.