Understanding permissions on linux files and directories

Table of contents

File permissions are one of the most fundamental security mechanisms of any computer system. Understanding how they are managed and interacted with is an essential skill for any linux operator and a robust permission setup can drastically improve a system's security and stability. Linux brings it#s own flavour of file and directory permissions, with a simple yet powerful mechanism to control access.

File permissions

Access to files in linux is managed using a set of three basic permissions:

  • r: Allows reading file contents
  • w: Allows writing to (and deleting) the file
  • x: Allows executing the file as a program

Separate permissions can be defined for three entities: the user owning the file (u), the group owning the file (g), and others (o). You can view the permissions of any file or directory using ls -l:

The output will list all directory contents, one per line. Each line starts with a d (directory) or - (file). The next 9 characters are the permissions for the user, group and others, respectively.

Directory permissions

Permissions on directories follow a similar approach by reusing the rwx permissions, but their meaning is slightly altered:

  • r: Allows listing directory contents with ls, but cannot access them or cd into the directory
  • w: Allows writing file contents (create, rename, delete), but does not work without x
  • x: Allows changing into directory (cd) and accessing files inside, but cannot list directory contents (ls)

To illustrate this further, let's assume we have a test directory test/ with a single file sample.txt inside. The sample.txt file has full rwx permissions for the current user, so all access controls originate from the test/ directory:

mkdir test/
echo "contents of sample.txt" > test/sample.txt
chmod a+rwx test/sample.txt
chmod a-rwx test

Setting only read (r) permissions on the directory allows reading the names of contents:

chmod u=r test
ls -l test

But the output contains an error when trying to read metadata from the file inside:

ls: cannot access 'test/sample.txt': Permission denied
total 0
-????????? ? ? ? ?           ? sample.txt

Trying to cd into the directory or read the contents of sample.txt throws errors:

cat test/sample.txt

Output:

cat: test/sample.txt: Permission denied

Changing the permissions to execute (x) only, the inverse happens:

chmod u=x test
ls -l test

Listing the directory contents is not allowed anymore:

ls: cannot open directory 'test/': Permission denied

But if you know the name of the file inside, you can access it directly:

cat test/sample.txt

This correctly prints the file contents:

contents of sample.txt

A last thing to note is that the write (w) permission implicitly requires the execute (x) permission as well, as you technically need to enter the directory in order to create files in it.

Special permissions

In addition to the traditional rwx permissions, there are some special permissions that change the behaviour of interactions:


  • SUID: Makes a file execute with the permissions of the file owner no matter who runs it. Often used to run programs that need superuser privileges without giving superuser access to users directly.

  • SGID: Makes a file execute with the permissions of the file group no matter who runs it. On directories, makes files created inside inherit the directory group.

  • Sticky bit: For directories, lets only the owner of files or directories delete or rename them. This mode is frequently used for shared directories like /tmp.

Special permissions are bound to their respective entity: SUID to the user (u), SGID to the group (g) and the sticky bit to others (o). When using ls -l, they will show up in the position of the x permission in their respective entity as s for SUID/SGID or t for the sticky bit:

Since you cannot see if the x permission is set in the space occupied by special permissions, you need to use different commands like getfacl to check exact permissions for these files.

Changing ownership

Modifying ownership of files and directories is done with the chown (change owner) command:

chown tom:users file.txt

This example changes the user for file.txt to tom and it's group to users. You can modify both user and group ownership at once, or one at a time.

To change only the user, omit the group portion:

chown tom file.txt

Changing only the group requires the leading colon : in front of the group name to work:

chown :users file.txt

Note that changing to user of a file requires superuser privileges, but you may change it's group to any group your current user has access to. Superusers can change ownership information without restrictions.

Changing permissions

To modify the permissions of a file or directory, the chmod command is used. It works by specifying the entities you want to change (u = user, g = group, o = others), the way you want to change them (- to remove permissions, + to add permissions, = to set exact permissions) and the permissions themselves (r = read, w = write, x = execute).

For example, to add read permissions for others to a file test.txt:

chmod o+r test.txt

Or to set the permissions for user and group to read and execute:

chmod ug=rx test.txt

Changing the permissions for everyone at once can be done through either ugo, it's alias a or by omitting the entity altogether:

chmod ugo+r test.txt
chmod a+r test.txt
chmod +r test.txt

The above commands all have the same effect.


Special permissions are set the same way, with s for SUID or SGID, and t for sticky bit:

chmod +t test/

Since special permissions are bound to a specific entity, setting them on different ones does nothing (e.g. u+t has no effect since sticky bit belongs to o). Because of this, entities are typically omitted for special permissions (using just +t). Be careful when omitting entities, since using +s without u or g will apply both SUID and SGID at the same time.


The owner of a file can take away their own access to a file, but not their ability to modify it's permissions. Even if they have removed all rwx permissions for themselves, they can still use chmod to give themselves these permissions back. The permissions otherwise function normally for them (e.g. trying to read a file without r permissions still results in Permission Denied errors, even if the user owns it).

Octal filemode notation

You may have heard of octal filemodes before, or seen chmod used with numbers like 755. The numbering system is an alternative way to specify exact permissions for a file or directory in linux. It's name octal refers to the base-8 numbering system, as there are 8 possible combinations of rwx permissions (none, r, w, x, rw, rx, wx, rwx).

The octal system works by assigning each permission a number:

  • 4: read (r)
  • 2: write (w)
  • 1: execute (x)
  • 0: no permissions

To represent a filemode, the corresponding numbers are added. As an example, to refer to rw permissions, one would add the 4 from read and 2 from write permissions and arrive at 6.

An octal filemode can be applied directly using chmod as a 3 digit number, each digit representing the permissions for user, group and others, respectively. To grant only the owner rw access to a file, you can use the the octal filemode 600:

chmod 600 test.txt

The permissions on the test.txt file are now equal to rw------- : rw (6) for user, none for group (0) and none for others (0).


Special permissions can also be expressed in octal form, as an optional prefix digit using the same addition:

  • 4: SUID
  • 2: SGID
  • 1: Sticky bit
  • 0 (or only 3 digits): no special permissions

In octal mode, these permissions don't interfere with their entity, and are added as an extra digit in front of the filemode instead:

chmod 5777 test.txt

This grants full rwx permissions for everyone (777), as well as setting the SUID and Sticky bit (5 = 4 for SUID + 1 for Sticky bit). When the digit for the special permissions is missing from a filemode, it is assumed to be 0 (e.g. 755 does not set any special permissions).


More articles

Setting up Grafana to monitor Kubernetes metrics and logs

Combining Grafana, Prometheus and Loki for a robust monitoring stack

Managing users on linux

A guide on users, groups and authentication

Forwarding docker container logs to Grafana Loki

Advanced log processing for local container environments

A gentle introduction to systemd

A broad overview of systemd components and features

Advanced Docker Compose features

Getting more out of container stacks