The Unix permissions model is one of the most elegant and enduring designs in computing. Introduced in the original Unix system in the 1970s, it remains the foundation of access control in Linux, macOS, FreeBSD, and every Unix-like operating system. Every file and directory in a Unix system has an associated set of permissions that determines who can read, write, or execute it.
The model is built on two concepts: three permission types (read, write, execute) and three user categories (owner, group, others). These combine to create a 9-bit permission matrix that governs all file access.
Every file has three user categories, and every user on the system falls into exactly one of them for any given file:
chown command.chgrp.The system checks permissions in order: if you are the owner, owner permissions apply (even if group permissions are more permissive). If you are not the owner but are in the group, group permissions apply. Otherwise, "others" permissions apply.
Each user category can be granted or denied three distinct permissions, each with specific meaning depending on whether the target is a file or a directory.
For files: Allows reading the file's contents. Without read permission, you cannot view, copy, or process the file's data. For directories: Allows listing the directory's contents (the names of files and subdirectories inside it).
For files: Allows modifying the file's contents. This includes editing, appending, truncating, and overwriting. For directories: Allows creating, deleting, and renaming files within the directory. Note that deleting a file requires write permission on the directory, not on the file itself.
For files: Allows running the file as a program or script. Without execute permission, the file cannot be launched, even if it contains valid executable code. For directories: Allows entering the directory (using cd) and accessing files within it. A directory without execute permission is effectively sealed -- you cannot access anything inside it even if you know the file names.
Owner Group Others
------- ------- -------
Read : r r r
Write : w w w
Execute : x x x
Example: rwxr-xr--
Owner: rwx (read, write, execute)
Group: r-x (read, execute)
Others: r-- (read only)
Octal notation represents permissions as a three-digit (or four-digit with special bits) number, where each digit is a value from 0 to 7. This compact notation is the most common way to specify permissions with the chmod command.
Each permission type is assigned a numeric value: read = 4, write = 2, execute = 1. The permissions for each user category are summed to produce a single digit:
Permission Values:
r (read) = 4
w (write) = 2
x (execute) = 1
Octal Digit = sum of granted permissions
Examples:
rwx = 4 + 2 + 1 = 7
rw- = 4 + 2 + 0 = 6
r-x = 4 + 0 + 1 = 5
r-- = 4 + 0 + 0 = 4
-wx = 0 + 2 + 1 = 3
-w- = 0 + 2 + 0 = 2
--x = 0 + 0 + 1 = 1
--- = 0 + 0 + 0 = 0
The three digits represent owner, group, and others (in that order):
chmod 754 myfile
7 = owner: rwx
5 = group: r-x
4 = others: r--
This relationship between the 3-bit binary representation and octal digits is why octal notation is so natural for permissions: each octal digit encodes exactly three permission bits.
Octal Binary Permissions
0 000 ---
1 001 --x
2 010 -w-
3 011 -wx
4 100 r--
5 101 r-x
6 110 rw-
7 111 rwx
Symbolic notation is an alternative way to specify permissions using letters and operators. It is more verbose but more readable, and it supports relative changes (add or remove specific permissions without affecting others).
chmod [who][operator][permissions] file
Who:
u = user (owner)
g = group
o = others
a = all (equivalent to ugo)
Operator:
+ = add permission
- = remove permission
= = set exact permission
Permissions:
r = read
w = write
x = execute
s = setuid/setgid
t = sticky bit
# Add execute permission for owner
chmod u+x script.sh
# Remove write permission for group and others
chmod go-w config.yml
# Set exact permissions for all (read-only for everyone)
chmod a=r document.txt
# Add execute for owner, read for group
chmod u+x,g+r script.sh
# Set owner to rwx, group to rx, others to nothing
chmod u=rwx,g=rx,o= program
# Add setuid bit
chmod u+s /usr/bin/program
Symbolic notation is especially useful when you want to modify specific permissions without knowing or changing the current state. For example, chmod +x script.sh adds execute permission for all users while preserving all existing permissions.
Beyond the standard read, write, and execute permissions, Unix supports three special permission bits that modify how files and directories behave. These are represented by an optional fourth octal digit prepended to the standard three.
When set on an executable file, the setuid bit causes the program to run with the effective user ID of the file's owner, rather than the user who launched it. This allows regular users to perform operations that normally require elevated privileges.
# The passwd command has setuid set (runs as root)
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 ... /usr/bin/passwd
# Note the 's' in place of 'x' for the owner
# Octal: 4755
# Set setuid
chmod u+s program
chmod 4755 program
Setuid is a powerful but security-sensitive feature. A setuid root program with a vulnerability could allow privilege escalation. Minimize the use of setuid programs and audit them carefully.
On an executable file, setgid causes the program to run with the effective group ID of the file's group. On a directory, setgid causes new files and subdirectories created within it to inherit the directory's group rather than the creating user's primary group. This is extremely useful for shared project directories.
# Setgid on a directory (shared project folder)
$ ls -ld /shared/project
drwxrwsr-x 2 root developers 4096 ... /shared/project
# Note the 's' in place of 'x' for the group
# New files created here will belong to the 'developers' group
chmod g+s /shared/project
chmod 2775 /shared/project
The sticky bit on a directory prevents users from deleting or renaming files they do not own, even if they have write permission on the directory. This is essential for shared directories like /tmp.
# The /tmp directory has the sticky bit set
$ ls -ld /tmp
drwxrwxrwt 24 root root 4096 ... /tmp
# Note the 't' in place of 'x' for others
# Octal: 1777
# Any user can create files in /tmp
# But only the owner (or root) can delete their own files
chmod +t /shared/temp
chmod 1777 /shared/temp
Special Bit Values:
4 = setuid
2 = setgid
1 = sticky bit
Examples:
4755 = setuid, owner rwx, group r-x, others r-x
2775 = setgid, owner rwx, group rwx, others r-x
1777 = sticky, owner rwx, group rwx, others rwx
6755 = setuid + setgid, owner rwx, group r-x, others r-x
Certain permission combinations are used so frequently that experienced administrators recognize them instantly:
Permission Symbolic Use Case
----------------------------------------------------
0644 rw-r--r-- Regular files (documents, configs)
0755 rwxr-xr-x Executables, scripts, directories
0600 rw------- Private files (SSH keys, secrets)
0700 rwx------ Private directories, home dirs
0666 rw-rw-rw- World-writable files (rare, risky)
0777 rwxrwxrwx World-writable+executable (avoid!)
0444 r--r--r-- Read-only files
0555 r-xr-xr-x Read-only executables
0750 rwxr-x--- Group-accessible directories
0640 rw-r----- Group-readable files
2775 rwxrwsr-x Shared group directories (setgid)
1777 rwxrwxrwt Shared temp directories (sticky)
# HTML, CSS, JS files (readable by web server)
chmod 644 index.html style.css app.js
# Directories (traversable by web server)
chmod 755 /var/www/html /var/www/html/css
# Upload directories (writable by web server)
chmod 775 /var/www/html/uploads
# Configuration files with secrets
chmod 640 /etc/nginx/conf.d/ssl.conf
# SSL private keys
chmod 600 /etc/ssl/private/server.key
# SSH directory
chmod 700 ~/.ssh
# Private keys (SSH is strict about this!)
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_ed25519
# Public keys
chmod 644 ~/.ssh/id_rsa.pub
# authorized_keys file
chmod 600 ~/.ssh/authorized_keys
# SSH config
chmod 600 ~/.ssh/config
The chmod (change mode) command is the primary tool for modifying file permissions. It supports both octal and symbolic notation.
# Octal notation
chmod 755 file.sh
# Symbolic notation
chmod u=rwx,g=rx,o=rx file.sh
# Multiple files
chmod 644 *.html *.css *.js
# Recursive (all files and directories in a tree)
chmod -R 755 /var/www/html
# -R: Recursive (apply to all files/directories below)
chmod -R 755 directory/
# -v: Verbose (show each file changed)
chmod -v 644 *.conf
# -c: Like verbose, but only report changes
chmod -c 644 *.conf
# --reference: Copy permissions from another file
chmod --reference=template.conf new.conf
A common challenge is setting different permissions for files and directories recursively. Directories need execute permission (to be traversable) but regular files usually do not. Use find to handle this:
# Set directories to 755 and files to 644
find /var/www -type d -exec chmod 755 {} +
find /var/www -type f -exec chmod 644 {} +
# Make all shell scripts executable
find . -name "*.sh" -exec chmod +x {} +
Directory permissions behave differently from file permissions, and understanding these differences is crucial for proper access control.
Read without execute: You can list file names but cannot access file metadata (size, permissions) or the files themselves. ls will show names but report errors for everything else.
Execute without read: You can access files if you know their exact name (blind access) but cannot list the directory contents. This is used for providing access to specific files without revealing what else exists in the directory.
Write without sticky bit: Anyone with write permission can delete any file in the directory, even files they do not own. This is why the sticky bit is essential for shared directories.
# Directory permission effects:
# r-- : Can list names only (not metadata)
# --x : Can access files by name (blind access)
# r-x : Can list and access files (normal read access)
# rwx : Full access (create, delete, rename files)
# rwt : Full access but can only delete own files (sticky)
The umask (user file-creation mask) determines the default permissions for newly created files and directories. It specifies which permission bits to remove from the maximum default permissions.
The maximum default permissions are 666 for files (no execute) and 777 for directories. The umask is subtracted from these to determine actual permissions:
Default permissions = maximum - umask
Common umask values:
umask 022:
Files: 666 - 022 = 644 (rw-r--r--)
Directories: 777 - 022 = 755 (rwxr-xr-x)
umask 077:
Files: 666 - 077 = 600 (rw-------)
Directories: 777 - 077 = 700 (rwx------)
umask 002:
Files: 666 - 002 = 664 (rw-rw-r--)
Directories: 777 - 002 = 775 (rwxrwxr-x)
The default umask on most systems is 022, which creates files readable by everyone but writable only by the owner. For more restrictive environments, 077 ensures new files are private to the owner.
# Check current umask
umask
# Set umask for current session
umask 027
# Set umask permanently (add to ~/.bashrc or ~/.zshrc)
echo "umask 027" >> ~/.bashrc
File permissions are a fundamental security control. Poor permission settings are a leading cause of security incidents in Linux/Unix systems.
find / -perm /6000. Each one is a potential privilege escalation vector.Our Chmod Calculator makes it easy to understand and set Unix file permissions. Enter an octal value and see the corresponding symbolic representation, or toggle individual permission checkboxes to build the octal value visually.
The tool supports all standard permissions plus special bits (setuid, setgid, sticky bit), shows the equivalent chmod command, displays the ls -l output format, and provides common permission presets for quick reference. Whether you are configuring a web server, setting up SSH keys, or troubleshooting access issues, this calculator eliminates guesswork.
chmod 755 sets permissions so the owner has read, write, and execute (7 = rwx), while the group and others have read and execute only (5 = r-x). This is the standard permission for executables and directories.
chmod 644 (rw-r--r--) is for regular files that do not need to be executed. chmod 755 (rwxr-xr-x) is for executables, scripts, and directories that need the execute bit.
The sticky bit (octal 1000, symbolic +t) on a directory prevents users from deleting files they do not own, even with directory write permission. The classic example is /tmp with permissions 1777.
Setuid (octal 4000, symbolic u+s) causes a program to run with the file owner's permissions rather than the executing user's. The passwd command uses setuid to modify system files as root.
Use ls -l for symbolic notation (e.g., -rwxr-xr-x) or stat -c '%a' for octal notation (e.g., 755). The ls -l output's first character indicates file type: - for files, d for directories, l for symlinks.
chmod 777 gives everyone full access, effectively removing all access control. Any user on the system can read, modify, delete, or execute the file. Use appropriate group permissions or ACLs instead.