Community Blog Changing File and Directory Permissions with chmod

Changing File and Directory Permissions with chmod

In this tutorial, we will learn how to change file and directory permissions on an Elastic Compute Service (ECS) Linux server 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.


If you want to learn by doing and follow all of the steps in this tutorial, launch a new ECS instance and use Debian as the operating system. Other Linux distributions such as CentOS, OpenSUSE or RedHat might have slight variations in default users/groups added to the system, different locations for configuration files, etc., which means you might have to adapt some of the commands. Otherwise, if you intend to only read and learn the theory, distribution choice isn't important since chmod itself is pretty much identical on all Linux-based operating systems.

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

You can think of users on a Linux system as a sort of user accounts. Every user must belong to a primary group and, optionally, can belong to one or more additional groups. There's a differentiation between regular users and system users. The first type will usually have a home directory, a default login shell and will be able to log in to the system, either locally or from remote locations (through SSH). System users are usually intended to run daemons and have no home directory, login shell or password associated so that local or remote logins are impossible. The purpose of this approach is to limit access as much as possible for certain processes (usually services that accept inbound connections from the Internet, since they are considered more vulnerable).

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

Every file and directory is owned by a user and by a group. Only the user owner can change permissions (user id of the person logged in must match the user id stored as the file/directory owner). The only exception to this rule is the root user which is allowed to adjust the permission of any object, regardless of the owner. You automatically own the files that you create and only the root user can change the user owner of a file. The group owner however can be changed by any user, under these conditions: the user owns the file and is part of the group that will become the new group owner. Example: "user1" is part of primary group "user1" (by default, every user manually added to the system will be part of a group that has the same name). "user1" is also part of additional group "webadmin". With the chown command, "user1" can change the group owner of a file to either "user1" or "webadmin" but not to another group such as "ntp". Since this may sound confusing at first, let's go through a practical example.

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 -l

total 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 -l

total 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 file1

chown: 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

Let's see the permissions and owners of every object stored in the /var directory:

ls -l /var/

The output may look like this:

root@debian:~# ls -l /var/

total 36

drwxr-xr-x  2 root root  4096 Sep  4 16:28 backups

drwxr-xr-x  9 root root  4096 Oct 25  2017 cache

drwxr-xr-x 31 root root  4096 Oct 25  2017 lib

drwxrwsr-x  2 root staff 4096 Jul 13  2017 local

lrwxrwxrwx  1 root root  9 Oct 25  2017 lock -> /run/lock

drwxr-xr-x  6 root root  4096 Sep  4 16:28 log

drwxrwsr-x  2 root mail  4096 Oct 25  2017 mail

drwxr-xr-x  2 root root  4096 Oct 25  2017 opt

lrwxrwxrwx  1 root root  4 Oct 25  2017 run -> /run

drwxr-xr-x  4 root root  4096 Oct 25  2017 spool

drwxrwxrwt  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

Make sure you're still logged in as a regular user, for example "user1" we created in the previous section. The root user can bypass permissions, making it harder to notice the effects of restrictions. Let's create a few directories and files, to learn how to use chmod on them:

mkdir directory

mkdir directory/subdirectory

touch 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 -l

total 4

drwxr-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 -l

total 4

drwxr-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 -l

total 4

drwxr-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 -l

total 4

drwxr-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 -l

total 4

drwxr-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).

rwx rwx rwx rwx rwx rwx rwx rwx
Binary Value 000 001 010 011 100 101 110 111
Octal Value 0 1 2 3 4 5 6 7
Resulting Permission --- --x -w- -wx r-- r-x rw- rwx

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 -l

total 4

drwxr-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 -l

total 4

drwxr-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 file3

drwxr-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 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 file3

drw-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/file

touch: 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 file3

drwxr----- 2 user1 user1 4096 Sep  6 00:28 subdirectory
0 0 0
Share on

Alibaba Clouder

2,628 posts | 706 followers

You may also like