~/articles/linux-file-permissions

Linux File Permissions Explained: A Complete Guide

Understand how Linux file permissions work — from the basics of read, write, and execute to advanced topics like setuid, setgid, sticky bits, and ACLs.

10 min read

Every file and directory on a Linux system has a set of permissions that control who can read, write, or execute it. Understanding file permissions is one of the most fundamental skills for anyone working with Linux — whether you are a developer deploying code, a sysadmin managing servers, or a DevOps engineer writing automation scripts.

Misconfigured permissions are one of the most common causes of security vulnerabilities and "permission denied" errors. This guide walks you through everything you need to know — from the basics to advanced concepts like special bits and ACLs.

The Permission Model: Users, Groups, and Others

Linux uses a three-tier permission model. Every file is owned by a user (the file's creator, by default) and a group. Permissions are then defined for three classes of users:

u — User (owner): the account that owns the file

g — Group: users who belong to the file's group

o — Others: everyone else on the system

When you run ls -l, the first column shows the permission string. For example, -rwxr-xr-- means the owner can read, write, and execute; the group can read and execute; others can only read.

Read, Write, and Execute — What Each Permission Does

BitSymbolOctalOn FilesOn Directories
Readr4View file contentsList directory contents
Writew2Modify file contentsCreate/delete files in dir
Executex1Run as a programEnter (cd into) directory

A common mistake is thinking that "read" permission on a directory lets you read its files. It only lets you list the filenames. To actually read the files inside, you need read permission on those individual files and execute permission on the directory to traverse into it.

Numeric (Octal) vs. Symbolic Notation

Permissions can be expressed in two ways. Octal notation uses three digits (e.g., 755), where each digit is the sum of 4 (read) + 2 (write) + 1 (execute). Symbolic notation uses letters (e.g., rwxr-xr-x).

# Octal — set all permissions at once

$ chmod 755 deploy.sh

# Symbolic — add/remove specific bits

$ chmod u+x deploy.sh   # add execute for owner

$ chmod go-w config.yml # remove write for group & others

Use octal when you want to set the full permission from scratch. Use symbolic when you want to tweak one specific bit without affecting the rest. In scripts and automation, octal is more common because it's explicit and unambiguous.

Changing Ownership with chown and chgrp

Permissions define what can be done; ownership defines who the permissions apply to. Thechown command changes the owner and group of a file:

$ chown www-data:www-data /var/www/html/index.html

$ chown -R deploy:deploy /opt/myapp/ # recursive

$ chgrp docker /var/run/docker.sock

On production servers, ownership mistakes are a top source of deployment failures. If your web server runs aswww-data but your deploy process creates files owned byroot, you will get "permission denied" errors even though the permission bits look correct.

Special Bits: Setuid, Setgid, and Sticky Bit

Beyond the standard rwx bits, Linux has three special permission bits that serve critical security and collaboration purposes:

Setuid (4xxx)

When set on an executable, it runs with the privileges of the file's owner, not the user who launched it. This is how passwd can modify/etc/shadow even when run by a normal user. Use sparingly — setuid root binaries are a major attack surface.

Setgid (2xxx)

On files, it works like setuid but for the group. On directories, it's more useful: new files created inside automatically inherit the directory's group, instead of the creator's primary group. This is essential for shared project directories where multiple users need to collaborate.

Sticky Bit (1xxx)

On directories, only the file owner (or root) can delete or rename files inside — even if others have write permission on the directory. The classic example is /tmp, which is world-writable but uses the sticky bit so users cannot delete each other's files.

$ chmod 4755 /usr/local/bin/myapp  # setuid

$ chmod 2775 /srv/shared-project/ # setgid on dir

$ chmod 1777 /tmp/              # sticky bit

The umask: Default Permissions for New Files

When a process creates a new file, the kernel applies a umask to determine the default permissions. The umask is a bitmask that removes permissions. For example, a umask of022 means new files get644 (rw-r--r--) and new directories get755 (rwxr-xr-x).

$ umask         # view current umask

0022

$ umask 027    # more restrictive: no access for others

On shared servers, setting a restrictive umask (like 077) prevents newly created files from being readable by other users. Set it in /etc/profile or~/.bashrc to make it persistent.

Access Control Lists (ACLs): Beyond the Basics

The standard permission model only supports one owner and one group per file. When you need finer-grained control — for example, giving a specific user read access without changing the file's group — you need POSIX ACLs.

# Grant user "alice" read access to a file

$ setfacl -m u:alice:r /var/log/app.log

# View ACL entries

$ getfacl /var/log/app.log

# Set default ACL on a directory (inherited by new files)

$ setfacl -d -m g:devops:rw /srv/project/

ACLs are particularly useful in environments with multiple teams sharing directories, CI/CD pipelines where service accounts need specific access, or when migrating from Windows where NTFS-style granular permissions were in use. Note that the filesystem must be mounted with ACL support (most modern distros enable this by default).

Common Permission Patterns and When to Use Them

OctalSymbolicUse Case
644rw-r--r--Config files, HTML, CSS, static assets
755rwxr-xr-xExecutable scripts, application directories
600rw-------SSH private keys, secrets, .env files
700rwx------~/.ssh directory, private script dirs
775rwxrwxr-xShared project directories (with setgid)
400r--------Read-only secrets (AWS credentials, TLS keys)

Troubleshooting Permission Issues

When you encounter "Permission denied" errors, follow this checklist:

1. Check the file permissions: ls -la /path/to/file

2. Check ownership: Does the user/group match who is trying to access it?

3. Check parent directories: You need execute permission on every directory in the path. A file at /opt/app/data/file.txt requires +x on /opt, /opt/app, and /opt/app/data.

4. Check for ACLs: getfacl /path/to/file

5. Check SELinux/AppArmor: Mandatory access controls can deny access even when traditional permissions allow it. Run getenforce and check /var/log/audit/audit.log.

The most common gotcha on production servers is forgetting about parent directory permissions. Even if a file ischmod 777, it is inaccessible if a parent directory does not have execute permission for the requesting user.

Related Tools