← Back

2026

Linux File Permissions: chmod, chown and ACLs

Every file on Linux belongs to an owner and a group. Nine permission bits decide who can read it, write to it or execute it. ACLs extend that model when three classes are not enough. Here is how all of it works.

Every file on a Linux system belongs to someone. The kernel tracks that ownership and uses it to decide who is allowed to read the file, who can write to it and who can run it. This is not a policy layered on top of the operating system. It is built into the filesystem itself, evaluated on every single access.

Most of the time the defaults work. You create a file, it belongs to you and nobody else can write to it. The moment you start running services under dedicated accounts, sharing directories across teams or hardening a system, the defaults are not enough. You need to actually understand what the permission bits mean, how to change them deliberately and what ACLs let you express that the traditional model cannot.

This article covers the standard Unix permission model, the tools that manipulate it, the special bits that most people encounter by accident rather than design and the ACL layer that sits on top when three permission classes stop being enough.

The permission model

Every file has an owner (a user) and an owning group. Permissions are defined separately for three classes: the owner, the group and everyone else (called other). Within each class there are three permission bits: read, write and execute.

When a process tries to access a file, the kernel checks which class applies to that process. If the process is running as the file owner, the owner bits apply. If the process belongs to the file's group (but is not the owner), the group bits apply. Everyone else falls under other. Only one class ever applies at a time, starting from the most specific.

r — read

On a file, the holder can open it and read its contents. On a directory, the holder can list the names of entries inside it.

w — write

On a file, the holder can modify its contents or truncate it. On a directory, the holder can create, delete or rename entries inside it. Write on a directory does not by itself let you write to the files inside.

x — execute

On a file, the holder can run it as a program. On a directory, the holder can enter it and access the files inside. A directory without execute is one you can list but not actually use.

Reading permission strings

Run ls -l and the first column is a ten-character string. The first character is the file type. The next nine characters are three groups of three: owner permissions, group permissions, other permissions.

ls -l /usr/bin/passwd

-rwsr-xr-x 1 root root 68208 Mar 14 10:21 /usr/bin/passwd

-

File type. A hyphen means regular file. d means directory. l means symbolic link.

rws

Owner (root) can read, write and execute. The s instead of x means the setuid bit is set.

r-x

Group (root) can read and execute. No write.

r-x

Others can read and execute. No write.

A capital S in the execute position means the special bit is set but execute is not. A lowercase s means both are set. The same convention applies to the sticky bit, which shows as t or T in the other execute position.

chmod

chmod changes permission bits. There are two ways to write the permissions you want: symbolic mode, which describes changes using letters, and octal mode, which expresses the full permission set as a three-digit number.

Symbolic mode is useful when you want to add or remove a specific bit without touching the others. The format is [who][operator][permissions] where who is u (user/owner), g (group), o (other) or a (all three), the operator is + to add, - to remove or = to set exactly.

Symbolic mode examples
chmod u+x script.sh

Add execute permission for the owner of the file.

chmod g-w config.yml

Remove write permission from the group.

chmod o=r README.txt

Set others to read only, removing any existing write or execute.

chmod a+r public.txt

Add read for all three classes at once. a means user, group and other together.

chmod ug+rw shared.txt

Add read and write for both the owner and the group in one step.

Octal mode sets all nine permission bits at once as a number from 0 to 7 for each class. Each digit is the sum of read (4), write (2) and execute (1). A 7 means all three bits set. A 5 means read and execute but no write.

Common octal modes
755

Owner has full access. Group and others can read and execute but not write. Standard for executables and directories you want others to enter.

644

Owner can read and write. Group and others can only read. Standard for regular files like configs and documents.

600

Owner reads and writes. No access for anyone else. Used for private keys and sensitive config files.

700

Owner has full access. Nobody else can do anything. Common for private directories.

777

Everyone can read, write and execute. Rarely correct outside of temporary directories with a sticky bit in place.

Pass -R to apply a change recursively to everything inside a directory. Be deliberate with this. Applying 755 recursively to a directory tree will set execute on regular files too, which is rarely what you want. For recursive changes that treat files and directories differently, a find pipeline is more precise.

chown and chgrp

Permissions control what each class can do. Ownership determines which class a given process falls into. chown changes the owner, the group or both at once.

chown alice report.txt

Transfer ownership of report.txt to alice. The group is not changed.

chown alice:devs report.txt

Set the owner to alice and the group to devs in one command.

chown :devs report.txt

Change only the group, leaving the owner as it is.

chown -R www-data:www-data /var/www/html

Recursively set owner and group to www-data on the entire web root.

chgrp devs /srv/project

Change the group of a directory. Equivalent to chown :devs when you only need the group changed.

Only root can transfer ownership to another user. A regular user can change the group of a file they own, but only to a group they are a member of.

Special permission bits

Beyond the nine standard bits there are three more that modify how permissions behave. They are set with a fourth octal digit or with symbolic notation. Two of them are often misunderstood. One is quietly essential.

setuid (SUID)

When set on an executable file, the program runs with the permissions of the file owner rather than the user who launched it. This is how passwd lets ordinary users modify /etc/shadow. It shows up as an s in the owner execute position in ls output.

setgid (SGID)

On an executable, it runs with the group identity of the file group instead of the calling user's group. On a directory it has a different effect: new files created inside inherit the directory's group rather than the creator's primary group. Useful for shared project directories.

sticky bit

On a directory, only the file's owner, the directory owner or root can delete or rename a file inside it, even if other users have write permission on the directory. /tmp uses this. Without it, any user who can write to the directory could delete anyone else's files.

Setting special bits
chmod u+s /usr/local/bin/mytool

Set the setuid bit on an executable so it runs as its owner.

chmod g+s /srv/team

Set the setgid bit on a directory so new files inherit the directory group.

chmod +t /tmp

Set the sticky bit on a directory so users can only remove their own files.

chmod 4755 /usr/local/bin/mytool

Octal form: the leading 4 sets setuid. 755 is the standard permission pattern.

chmod 2775 /srv/team

Octal form: the leading 2 sets setgid. Common for shared directories.

chmod 1777 /tmp

Octal form: the leading 1 sets the sticky bit. 777 makes it world-writable.

Access control lists

The standard Unix model gives you three classes. Sometimes that is not enough. You need one specific user to have read access to a file without making them part of the owning group. You need two different groups with different levels of access to the same directory. The traditional permission bits cannot express either of those requirements. ACLs can.

An ACL is a list of additional permission entries attached to a file. Each entry names a specific user or group and grants it a set of permissions independently of the standard bits. The standard bits remain in place. ACL entries sit alongside them as extensions.

Filesystem support

ACLs require filesystem support. ext4, XFS and Btrfs all support them by default on modern distributions. If getfacl or setfacl are not available, install the acl package. On some older setups you may need to mount the filesystem with the acl mount option, though most current kernels enable this automatically.

getfacl report.txt

Print the full ACL for report.txt, showing both standard permission bits and any extended entries.

setfacl -m u:alice:rw report.txt

Grant alice read and write access to report.txt without changing the file's owner or standard permissions.

setfacl -m g:devs:r-- /var/log/app.log

Give the devs group read-only access to the log file, on top of whatever the standard group bits say.

setfacl -x u:alice report.txt

Remove the ACL entry for alice specifically. The file's standard permissions remain untouched.

setfacl -b report.txt

Remove all extended ACL entries from the file, leaving only the standard permission bits.

setfacl -d -m g:devs:rw /srv/project

Set a default ACL on the directory. New files created inside will automatically inherit this entry.

getfacl output with an ACL entry

# file: report.txt

# owner: lars

# group: staff

user::rw-

user:alice:rw-

group::r--

mask::rw-

other::---

The mask entry is worth understanding. It caps the effective permissions of all named entries and the owning group. Even if alice has rw in her entry, if the mask is r--, her effective access is read only. setfacl -m mask::rw adjusts it. Tools like chmod update the mask when you change group permissions on a file that has an ACL, which can be surprising the first time it happens.

A plus sign at the end of the permission string in ls -l output indicates that the file has an extended ACL. If you see it and cannot explain why, getfacl will show you what is there.

umask

When a new file is created, the kernel applies a default set of permissions before the creating program can change them. The umask controls which bits are stripped from those defaults.

The typical umask is 022. Files start with a maximum of 666 (read and write for everyone). The umask removes the bits it specifies, so 022 removes write for group and other, leaving 644. Directories start at 777, so a umask of 022 produces 755.

umask

Print the current umask value.

umask 027

Set the umask to 027. New files will be 640, new directories will be 750. Group has no write, others have nothing.

umask 077

Strict umask. New files are 600, directories are 700. Nothing is visible to group or others by default.

Changes to umask in a shell session affect only that session. To make it persistent, set it in the user's shell profile or in /etc/profilefor a system-wide default.

Where it fits

File permissions are the first layer of access control on any Linux system. Before a process can read a config file, write a log, execute a binary or enter a directory, the kernel checks these bits. Everything else, SELinux, AppArmor, network ACLs, sits on top. If the basic ownership is wrong, none of the higher layers help.

In practice, most permission problems come from a handful of recurring mistakes: a service directory owned by root that a non-root service cannot write to, a private key file that is world-readable, a shared directory where users can delete each other's work because the sticky bit is missing. Understanding the model means you can diagnose these immediately rather than guessing at chmod 777 until something works.

ACLs extend this to situations where the three-class model is too blunt. They show up in shared workspaces, NFS mounts with multiple teams, CI systems that need read access to config files owned by a different service account. The core model and ACLs together cover the full range of what production Linux systems actually need to express.