Linux File Permissions
last modified October 23, 2026
Linux file permissions control who can read, modify, and execute files and
directories. They are a basic security mechanism of every Unix-like system.
This tutorial explains how permissions are represented and shows how to view
and change them with ls, chmod, chown,
chgrp, and umask.
Every file has an owner and a group. Permissions are defined separately for three classes of users: the owner, the group, and others. Each class can have three types of permissions: read, write, and execute. The root user bypasses these checks.
Basic permission types
The following table outlines the three fundamental permission types in Linux: read, write, and execute. Each permission has a specific symbol and an associated octal value, which are essential for configuring file and directory access.
| Permission | Symbol | Octal Value | Description | File Example | Directory Example |
|---|---|---|---|---|---|
| Read | r | 4 | Allows viewing file contents | Reading a text file | Listing directory contents (ls/dir) |
| Write | w | 2 | Allows modifying contents | Editing a file | Creating/deleting files in directory |
| Execute | x | 1 | Allows execution | Running scripts/programs | Accessing directory (cd) |
These basic permissions form the foundation of Linux access control. For files, 'read' allows viewing contents, 'write' enables editing, and 'execute' permits running the file as a program or script.
For directories, the meanings shift slightly: 'read' lets you list contents,
'write' allows modifications like adding or removing files, and 'execute' is
required to enter the directory with commands like cd.
The octal values (4, 2, 1) are used in numeric notation to combine permissions, as we'll see later.
User classes
This table introduces the three user classes that Linux permissions apply to: owner, group, and others. Each class is assigned specific permissions to control access levels.
| Class | Symbol | Description | Typical Use Case |
|---|---|---|---|
| Owner/User | u | The file's creator or assigned owner | Personal files with full control |
| Group | g | Users in the file's assigned group | Team-shared files |
| Others | o | All other system users | Public access files |
In Linux, permissions are assigned separately to these three classes. The 'owner' is typically the user who created the file and often has the most privileges.
The 'group' consists of users assigned to a specific group (viewable with
ls -l), useful for collaborative work.
'Others' encompasses everyone else on the system, often given minimal access for security. These distinctions allow fine-grained control, such as giving a team (group) read access while restricting outsiders (others).
Permission notation
The table below demonstrates how permissions are represented in both symbolic and octal notation, with examples showing common configurations and their breakdowns.
| Type | Example | Octal | Breakdown |
|---|---|---|---|
| Symbolic | -rwxr-xr-x | 755 |
Owner: rwx (7 = 4+2+1) Group: r-x (5 = 4+1) Others: r-x (5 = 4+1) |
| Symbolic | -rw-r--r-- | 644 |
Owner: rw- (6 = 4+2) Group: r-- (4) Others: r-- (4) |
| Symbolic | -rwxrwxrwx | 777 |
Owner: rwx (7 = 4+2+1) Group: rwx (7 = 4+2+1) Others: rwx (7 = 4+2+1) |
Permission notation can be symbolic (e.g., rwxr-xr-x) or numeric
(e.g., 755). The symbolic form uses 'r', 'w', and 'x' for read,
write, and execute, with '-' indicating no permission.
The octal form condenses this into three digits, one for each user class
(owner, group, others), calculated by adding the values of enabled permissions.
For instance, 755 grants the owner full access (7), while group and
others get read and execute (5).
The 777 example shows full access for all, which is rare due to
security risks, while 644 is common for files needing owner
editing and public reading.
Octal permission values
This table provides a detailed look at how octal values are calculated from permission combinations, showing every possible value from 0 to 7 with their symbolic, binary, and descriptive equivalents.
| Octal Value | Symbolic Notation | Binary Representation | Calculation | Description |
|---|---|---|---|---|
| 0 | --- | 000 | 0 | No permissions |
| 1 | --x | 001 | 1 | Execute only |
| 2 | -w- | 010 | 2 | Write only |
| 3 | -wx | 011 | 2 + 1 = 3 | Write and Execute |
| 4 | r-- | 100 | 4 | Read only |
| 5 | r-x | 101 | 4 + 1 = 5 | Read and Execute |
| 6 | rw- | 110 | 4 + 2 = 6 | Read and Write |
| 7 | rwx | 111 | 4 + 2 + 1 = 7 | Read, Write, and Execute (full permissions) |
The octal system simplifies permission settings by assigning values to each permission: read (4), write (2), and execute (1). These are added together to form a single digit per user class.
The binary representation (e.g., 101 for 5) mirrors this, with each bit
corresponding to a permission (1 for enabled, 0 for disabled). For example,
5 (read and execute) is rare for files but common for directories,
while 6 (read and write) suits editable documents.
This table is a reference for constructing any permission string, like
combining rw- (6) for an owner with r-- (4) for others
in 644.
Special permissions
Besides the nine basic bits, there are three special permission bits. They
are set with a fourth, leading octal digit, for example
chmod 2775.
- SetUID (4): An executable runs with the privileges of
its owner rather than of the user who started it. Shown as
sin the owner's execute position. - SetGID (2): An executable runs with the privileges of
its group. On a directory, new files inherit the directory's group. Shown as
sin the group's execute position. - Sticky bit (1): On a directory, only the owner of a
file (or root) can delete or rename it. Shown as
tin the others' execute position.
Viewing file permissions
The ls -l command shows the permissions in the first column of
its long listing.
ls -l report.txt backup.sh ls -ld docs stat -c '%A %a %U:%G %n' report.txt docs
In -rw-r--r--, the first character is the file type:
- for a regular file, d for a directory, and
l for a symbolic link. The next nine characters are the
permissions of the owner (rw-), the group (r--),
and others (r--). The two names that follow are the owner and
the group. The -d option shows the directory itself instead of
its contents. The stat command can also print the permissions
in octal form.
$ ls -l report.txt backup.sh -rw-r--r-- 1 jano jano 35 Oct 23 09:00 backup.sh -rw-r--r-- 1 jano jano 18 Oct 23 09:00 report.txt $ ls -ld docs drwxr-xr-x 2 jano jano 4096 Oct 23 09:00 docs $ stat -c '%A %a %U:%G %n' report.txt docs -rw-r--r-- 644 jano:jano report.txt drwxr-xr-x 755 jano:jano docs
Changing permissions in numeric mode
The chmod command changes permissions. In numeric mode, it sets
all permission bits at once.
chmod 755 backup.sh
A newly created script cannot be run because it lacks the execute
permission. The mode 755 sets rwx (7) for the
owner and r-x (5) for the group and others. Numeric mode is
absolute: the previous permissions are replaced. Only the owner of a file or
root can change its permissions.
$ ./backup.sh bash: ./backup.sh: Permission denied $ chmod 755 backup.sh $ ls -l backup.sh -rwxr-xr-x 1 jano jano 35 Oct 23 09:00 backup.sh $ ./backup.sh backup complete
Changing permissions in symbolic mode
Symbolic mode modifies selected permissions and leaves the others
unchanged. It combines the classes u, g,
o, and a (all) with an operator and permissions.
chmod g+w team_doc.txt chmod u=rw,g=r,o= notes.txt chmod a-w notes.txt
The + operator adds permissions, - removes them,
and = sets them exactly; o= removes all permissions
of others. Several clauses are separated by commas. After
a-w, nobody can write to the file, so the redirection fails.
$ chmod g+w team_doc.txt $ ls -l team_doc.txt -rw-rw-r-- 1 jano jano 6 Oct 23 09:00 team_doc.txt $ chmod u=rw,g=r,o= notes.txt $ ls -l notes.txt -rw-r----- 1 jano jano 5 Oct 23 09:00 notes.txt $ chmod a-w notes.txt $ ls -l notes.txt -r--r----- 1 jano jano 5 Oct 23 09:00 notes.txt $ echo "more" >> notes.txt bash: notes.txt: Permission denied
Directory permissions
For directories, the read permission allows listing the names of entries, while the execute permission allows accessing the entries.
chmod u-x private chmod u+x,u-r private
Without the execute permission, we can list the file names in
private, but we cannot read the file inside. Without the read
permission but with execute, the listing fails, yet a file whose name we know
can still be opened. The write permission on a directory, together with
execute, allows creating, renaming, and deleting files in it, regardless of
the permissions of those files.
$ mkdir private; echo "secret" > private/key.txt $ chmod u-x private $ ls -ld private drw-r-xr-x 2 jano jano 4096 Oct 23 10:42 private $ cat private/key.txt cat: private/key.txt: Permission denied $ ls private key.txt $ chmod u+x,u-r private $ ls private ls: cannot open directory 'private': Permission denied $ cat private/key.txt secret
Changing ownership
The chown command changes the owner and group of a file;
chgrp changes only the group.
sudo chown alice:devs project.c chgrp devs report.txt
The groups command shows that the current user is a member of
the devs group. The syntax owner:group changes both
at once, and :group changes only the group. Changing the owner
requires root privileges, so a regular user cannot give a file away. The
owner of a file can change its group to any group they belong to.
$ groups jano devs $ ls -l project.c -rw-r--r-- 1 jano jano 10 Oct 23 09:00 project.c $ sudo chown alice:devs project.c $ ls -l project.c -rw-r--r-- 1 alice devs 10 Oct 23 09:00 project.c $ chown alice report.txt chown: changing ownership of 'report.txt': Operation not permitted $ chgrp devs report.txt $ ls -l project.c report.txt -rw-r--r-- 1 alice devs 10 Oct 23 09:00 project.c -rw-r--r-- 1 jano devs 18 Oct 23 09:00 report.txt
Using special permissions
We look at existing special permissions and set the SetGID bit on a shared directory.
ls -l /usr/bin/passwd ls -ld /tmp sudo mkdir /srv/team sudo chgrp devs /srv/team sudo chmod 2775 /srv/team
The passwd program has the SetUID bit, so it runs as root and
can update the password database. The /tmp directory is
world-writable but has the sticky bit, so users cannot delete each other's
files. On /srv/team, the SetGID bit makes new files belong to
the devs group even when created by root. A capital
S or T means that the special bit is set without the
underlying execute permission, which is usually a mistake.
$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 68248 Apr 7 2025 /usr/bin/passwd $ ls -ld /tmp drwxrwxrwt 1 root root 4096 Oct 23 10:42 /tmp $ sudo mkdir /srv/team $ sudo chgrp devs /srv/team $ sudo chmod 2775 /srv/team $ ls -ld /srv/team drwxrwsr-x 2 root devs 4096 Oct 23 10:42 /srv/team $ sudo touch /srv/team/plan.txt $ ls -l /srv/team total 0 -rw-r--r-- 1 root devs 0 Oct 23 10:42 plan.txt $ chmod u+s report.txt $ ls -l report.txt -rwSr--r-- 1 jano devs 18 Oct 23 09:00 report.txt
Default permissions with umask
The umask determines the permissions of newly created files and
directories. Its bits are removed from the default modes, which are
666 for files and 777 for directories.
umask umask -S umask 027
The common umask 022 removes the write permission for the group
and others, giving 644 for files and 755 for
directories. With 027, new files get 640 and
directories 750, so others have no access. The
-S option shows the permissions that remain in symbolic form.
The setting applies to the current shell; to make it permanent, put it in
~/.bashrc or ~/.profile.
$ umask 0022 $ umask -S u=rwx,g=rx,o=rx $ umask 027 $ touch new.txt; mkdir newdir $ ls -ld new.txt newdir drwxr-x--- 2 jano jano 4096 Oct 23 10:42 newdir -rw-r----- 1 jano jano 0 Oct 23 10:42 new.txt
Changing permissions recursively
The -R option applies chmod to a directory and all
its contents.
chmod -R u=rwX,go=rX site
find site -type f -exec chmod 600 {} +
A recursive numeric mode such as chmod -R 755 would make all
regular files executable. The capital X adds the execute
permission only to directories and to files that are already executable for
someone. For finer control, find selects the files by type and
runs chmod on them.
$ mkdir -p site/css site/js; touch site/index.html site/css/main.css site/js/app.js
$ chmod -R u=rwX,go=rX site
$ find site -exec stat -c "%A %n" {} +
drwxr-xr-x site
drwxr-xr-x site/css
-rw-r--r-- site/css/main.css
drwxr-xr-x site/js
-rw-r--r-- site/js/app.js
-rw-r--r-- site/index.html
$ find site -type f -exec chmod 600 {} +
$ find site -type f -exec stat -c "%A %n" {} +
-rw------- site/css/main.css
-rw------- site/js/app.js
-rw------- site/index.html
Finding files by permissions
The -perm test of find searches for files with
given permissions.
find . -perm -o+w find . -type f -perm 600 find /usr/bin -perm -4000
With a leading -, the listed bits must all be set, while other
bits are ignored; the first command finds world-writable files. Without a
prefix, the permissions must match exactly. The last command lists the
SetUID programs in /usr/bin, which is a common security audit
check. When searching the whole system, add 2>/dev/null to
hide errors for directories we cannot read.
$ chmod o+w notes.txt $ find . -perm -o+w ./notes.txt $ find . -type f -perm 600 ./site/css/main.css ./site/js/app.js ./site/index.html $ find /usr/bin -perm -4000 /usr/bin/chfn /usr/bin/su /usr/bin/newgrp /usr/bin/chsh /usr/bin/umount /usr/bin/passwd /usr/bin/gpasswd /usr/bin/mount /usr/bin/sudo
Best practices for file permissions
- Use least privilege: Grant only the permissions that users and services need.
- Avoid 777: World-writable files and directories are a security risk; fix ownership or groups instead.
- Use groups: Share files through groups and SetGID directories rather than opening them to others.
- Be careful with -R: Use
Xorfindto treat files and directories differently. - Audit regularly: Look for unexpected world-writable and SetUID files.
Source
GNU file permissions documentation
In this article, we have explained Linux file permissions and used
ls, chmod, chown, chgrp,
umask, and find to view, change, and audit them.
Author
List all Linux tutorials.