Every file and directory on Unix systems has an owner, a group, and permissions. These three pieces of information determine who may read, modify, or execute files. The concept dates back to the 1970s and protects multi-user systems against accidental changes and unauthorized access.
Permissions are divided into three categories: owner (user), group, and others. Each category can have three permissions: read, write, and execute. These nine bits define the access rights—Unix needs nothing more for functional access control.
Understanding the Permission System
The Three Permission Categories
$ ls -l /home/michael/documents/report.pdf
-rw-r--r-- 1 michael users 45632 Oct 6 14:23 report.pdf
The output begins with ten characters: -rw-r--r--. The first character (-) identifies the file type—a hyphen for regular files, d for directories. The remaining nine characters are divided into three groups of three:
- rw- (characters 2–4): Owner permissions (michael)
- r– (characters 5–7): Group permissions (users)
- r– (characters 8–10): Permissions for all other users
The owner can read and write the file (rw-), the group can only read it (r--), and other users can also only read it (r--). Nobody except the owner can modify or delete the file.
Read, Write, Execute in Detail
Read (r) allows a file to be read. cat report.pdf works with the read permission; without it, you get “Permission denied.” For directories, r allows the contents to be listed with ls.
Write (w) allows a file to be modified. Editors can save changes, and data can be appended. Without the write permission, files are read-only—even the owner cannot save changes unless the permissions are changed first. For directories, w allows files to be created, deleted, and renamed.
Execute (x) makes files executable. Shell scripts and binaries require the execute permission to run. Without it, ./script.sh returns a permission error. For directories, x means permission to enter the directory—cd /path requires execute permission on /path.
Owner and Group
$ ls -l script.sh
-rwxr-xr-x 1 michael developers 2048 Oct 6 15:30 script.sh
The file belongs to user michael and group developers. Every user can belong to multiple groups. The id command displays your group memberships:
$ id michael
uid=1000(michael) gid=1000(michael) groups=1000(michael),27(sudo),1001(developers)
Michael is a member of the michael group (primary group), sudo (allowed to execute root commands), and developers. New files automatically receive the creator’s primary group. The newgrp command temporarily changes the primary group.
Groups make team collaboration possible without granting global permissions. All members of developers can read and execute script.sh, but only michael can modify it. Other users (not in the group) can also read and execute the script, but cannot modify it.
Changing Permissions with chmod
Symbolic Notation
The chmod command (change mode) changes permissions. Symbolic notation uses letters: u for user (owner), g for group, o for others, and a for all (all three categories).
$ chmod u+x script.sh
This adds (+) the execute permission (x) for the owner (u). The file becomes executable for the owner. Existing permissions remain unchanged.
$ chmod go-w file.txt
This removes (-) the write permission (w) from the group (g) and others (o). Only the owner can still write to the file. There is no u, so the owner’s permissions remain unchanged.
$ chmod a+r info.txt
This grants read permission (r) to everyone (a). The owner, group, and others can all read the file. Existing permissions remain intact; only the read permission is added.
Multiple changes can be combined:
$ chmod u+x,go-w script.sh
This makes the script executable for the owner and removes write permissions from the group and others. The comma separates the operations.
Octal Notation
Octal notation uses three digits from 0 to 7. Each digit encodes three bits (rwx) as a sum: r=4, w=2, x=1. The first digit applies to the owner, the second to the group, and the third to others.
$ chmod 755 script.sh
This sets the permissions to rwxr-xr-x:
- 7 for the owner: r(4) + w(2) + x(1) = 7 = rwx
- 5 for the group: r(4) + x(1) = 5 = r-x
- 5 for others: r(4) + x(1) = 5 = r-x
The owner has full access, while the group and others can read and execute. This is the typical permission set for executable files that others should be able to use.
$ chmod 644 document.txt
This results in rw-r--r--:
- 6 for the owner: r(4) + w(2) = 6 = rw-
- 4 for the group: r(4) = 4 = r–
- 4 for others: r(4) = 4 = r–
These are the standard permissions for text files—the owner can write, everyone else can only read. Documents, configuration files, and source code commonly use 644.
$ chmod 600 private.key
This sets rw-------:
- 6 for the owner: r(4) + w(2) = 6 = rw-
- 0 for the group: no permissions
- 0 for others: no permissions
Only the owner has access. SSH keys require these permissions—SSH refuses authentication if private key files are too permissive.
Common Permission Patterns
| Octal | Symbolic | Meaning | Typical Use |
|---|---|---|---|
| 755 | rwxr-xr-x | Owner has full access, others can read and execute | Executable programs |
| 644 | rw-r–r– | Owner can write, others can read | Text files, configuration |
| 600 | rw——- | Only the owner can read and write | Private files, SSH keys |
| 700 | rwx—— | Only the owner has full access | Private scripts, personal directories |
| 444 | r–r–r– | Everyone can read, nobody can write | Read-only data |
| 777 | rwxrwxrwx | Full access for everyone | Insecure—never use |
The 777 permission is a security risk. Any user can modify or delete the file. Temporary debugging situations may occasionally justify it—but never on production systems.
Directory Permissions
Execute Permission on Directories
For directories, the execute permission (x) has a special meaning: it allows users to enter the directory with cd. Without x, users cannot change into the directory, even if they have read permission.
$ ls -ld /home/michael/projects/
drwxr-xr-x 12 michael michael 4096 Oct 6 14:45 projects/
The leading d identifies a directory. The permissions rwxr-xr-x mean:
- Owner: read, write, enter (rwx)
- Group: read, enter (r-x)
- Others: read, enter (r-x)
Everyone can execute cd /home/michael/projects/ and list the contents with ls. Only the owner can create, delete, or rename files.
Read Without Execute
$ chmod 744 directory/
This sets rwxr--r-- on a directory. The group and others have only r (read), not x (execute). They cannot run cd directory/, even though they theoretically have permission to list the contents. Without x, the directory cannot be entered—ls fails with “Permission denied.”
This combination is rarely useful. Directories generally need r and x together (r-x); otherwise, the read permission is effectively useless.
Write Permission on Directories
The write permission (w) on directories allows files to be created, deleted, and renamed within the directory. It applies independently of the permissions on the files themselves.
$ ls -ld project/
drwxrwxr-x 5 michael developers 4096 Oct 6 15:12 project/
$ ls -l project/important.txt
-r--r--r-- 1 sandra developers 1024 Oct 3 10:22 important.txt
The project/ directory has rwxrwxr-x—the owner and the group can write. The file important.txt is read-only (r--r--r--) and belongs to sandra.
Michael can still delete important.txt because he has write permission on the parent directory. File permissions protect only the file’s contents, not the file’s existence. The directory permission determines whether a file can be deleted.
Typical Directory Permissions
| Octal | Symbolic | Meaning | Typical Use |
|---|---|---|---|
| 755 | rwxr-xr-x | Owner can write, others can navigate | Standard user directories |
| 775 | rwxrwxr-x | Owner and group can write | Team projects |
| 700 | rwx—— | Only the owner has access | Private directories |
| 1777 | rwxrwxrwt | Everyone can write, only owners can delete | /tmp with the Sticky Bit |
The Sticky Bit (the leading 1 in octal notation) on directories allows everyone to create files, but only the owner of a file (or the owner of the directory) can delete it. /tmp uses this behavior—everyone can create temporary files, but nobody can delete another user’s files.
Changing Ownership with chown
Changing User and Group
The chown command (change owner) changes the owner of a file. Only root can use chown—ordinary users cannot transfer files to other users. This prevents users from bypassing quota systems (disk space limits per user).
$ sudo chown sandra document.txt
The file now belongs to sandra. The group remains unchanged. Sandra can now change the permissions and act as the owner.
$ sudo chown sandra:developers document.txt
This changes the owner to sandra and the group to developers. The colon separates the user and the group. Both are changed with a single command.
$ sudo chown :admins file.txt
Only the group is changed (to admins); the owner remains the same. A colon without a user name changes only the group.
Recursive Changes
The -R (recursive) option changes ownership for entire directory trees:
$ sudo chown -R michael:developers /opt/project/
All files and subdirectories in /opt/project/ now belong to michael with the group developers. This is useful after extracting archives or transferring ownership of project directories.
$ sudo chmod -R 755 /opt/project/bin/
All files in /opt/project/bin/ and its subdirectories receive permission 755. Scripts and programs become executable. Recursive changes save time compared to running chmod on every file individually.
Caution: Recursive chmod can cause serious damage. Running chmod -R 777 / as root would make the entire system writable by everyone—a catastrophic failure for both stability and security. Always verify recursive commands before executing them.
Special Permission Bits
SetUID — Execute as the Owner
The SetUID (Set User ID) bit allows a program to run with the permissions of its owner instead of the user who starts it. This is powerful and potentially dangerous.
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Mai 28 2024 /usr/bin/passwd
The s in rws indicates SetUID. The passwd program is owned by root. Ordinary users can execute it, and it runs with root privileges. This is necessary because passwd must modify the /etc/shadow file, which only root may access.
Without SetUID, ordinary users could never change their passwords because /etc/shadow is strictly protected. With SetUID, passwd temporarily runs as root, updates the file, and exits. The user never receives root privileges—only the program does.
For security reasons, SetUID works only with executable files, not shell scripts. A SetUID script could be manipulated through environment variables and is therefore considered too dangerous.
$ chmod u+s programm
$ chmod 4755 programm
Both commands set the SetUID bit. Symbolic notation uses u+s; octal notation uses a leading 4 (4755 instead of 755). The s then appears in the owner’s execute field in ls -l.
SetGID — Execute as the Group
The SetGID (Set Group ID) bit works similarly to SetUID, but for groups. Programs run with the permissions of the file’s group instead of the executing user’s group.
$ chmod g+s programm
$ chmod 2755 programm
Octal notation uses a leading 2 (2755). The s appears in the group’s execute field in ls -l.
On directories, SetGID has a different meaning: new files automatically inherit the directory’s group instead of the creator’s primary group. This is useful for team directories.
$ ls -ld /opt/team-project/
drwxrwsr-x 8 michael developers 4096 Oct 6 16:20 team-project/
The s in the group field (rws) indicates SetGID. Every file created in this directory automatically belongs to the developers group, regardless of who created it. This simplifies team collaboration because all group members receive the same group permissions on new files.
Sticky Bit — Only the Owner Can Delete
The Sticky Bit on directories prevents users from deleting files that belong to other users, even if they have write permission on the directory. Only the owner of a file (or the owner of the directory, or root) may delete it.
$ ls -ld /tmp/
drwxrwxrwt 15 root root 4096 Oct 6 16:45 /tmp/
The t at the end (rwt instead of rwx) indicates the Sticky Bit. The /tmp directory has permission 1777—everyone can create files, but nobody can delete another user’s files. User A may read a file belonging to user B (if the file permissions allow it), but cannot delete it.
$ chmod +t directory/
$ chmod 1777 directory/
Symbolic notation uses +t; octal notation uses a leading 1 (1777). The Sticky Bit is useful for shared directories such as /tmp, where all users store temporary files.
Combined Special Permission Bits
The special permission bits can be combined:
| Octal | Meaning |
|---|---|
| 4755 | SetUID, normal permissions rwxr-xr-x |
| 2755 | SetGID, normal permissions rwxr-xr-x |
| 1777 | Sticky Bit, full permissions rwxrwxrwx |
| 6755 | SetUID + SetGID |
| 7755 | All three special permission bits |
The first octal digit encodes the special permission bits: 4=SetUID, 2=SetGID, 1=Sticky Bit. Adding them combines the bits: 4+2=6 for SetUID+SetGID, 4+2+1=7 for all three.
Practical Applications
Secure Script Access
A script backup.sh should create backups, but only the administrator should be able to modify it:
$ sudo chown root:admins backup.sh
$ chmod 750 backup.sh
This results in rwxr-x---: root has full access, the admins group can execute the script (start backups), and ordinary users have no access. The script itself is protected against modification.
Team Project Directory
A project directory for a development team:
$ sudo mkdir /opt/project
$ sudo chown michael:developers /opt/project
$ sudo chmod 2775 /opt/project
This sets rwxrwsr-x with SetGID. All team members (group developers) can create, modify, and delete files. New files automatically belong to the developers group. Other users can view the contents (r-x), but cannot modify them.
Private Home Directories
User home directories should be private:
$ chmod 750 /home/michael
This sets rwxr-x---: Michael has full control, members of his group can enter and read the directory (useful for shared files), and other users have no access. By default, home directories are often 755, allowing everyone to read them. 750 is more secure.
Web Server Directories
A web server needs read access to HTML files, but not write access:
$ sudo chown www-data:www-data /var/www/html
$ sudo chmod 755 /var/www/html
$ find /var/www/html -type f -exec chmod 644 {} \;
$ find /var/www/html -type d -exec chmod 755 {} \;
Directories receive 755 (traversable), files receive 644 (readable). The web server process (running as www-data) can read everything but cannot modify anything. Upload directories require 755 or 775 if write access is needed.
Umask and Default Permissions
Understanding umask
The umask (user file creation mask) defines which permissions are automatically removed from newly created files and directories. It is applied by subtracting permissions from the maximum defaults.
$ umask
0022
The default umask is usually 022. New files theoretically start with 666 (rw-rw-rw-), and new directories with 777 (rwxrwxrwx). The umask is subtracted:
- Files:
666 - 022 = 644(rw-r--r--) - Directories:
777 - 022 = 755(rwxr-xr-x)
A umask of 077 removes all permissions for the group and others:
- Files:
666 - 077 = 600(rw-------) - Directories:
777 - 077 = 700(rwx------)
All newly created files are then private. This is more secure, but less practical for team collaboration.
$ umask 002
This temporarily sets the umask to 002. New files receive 664 (rw-rw-r--), and directories receive 775 (rwxrwxr-x). The group can write—useful for team directories. The change applies only to the current shell session. Permanent changes belong in ~/.bashrc or /etc/profile.
Checking Default Permissions
$ touch testfile
$ mkdir testdirectory
$ ls -ld testfile testdirectory
-rw-r--r-- 1 michael michael 0 Oct 6 17:15 testfile
drwxr-xr-x 2 michael michael 4096 Oct 6 17:15 testdirectory/
New files receive 644, and new directories receive 755, matching the default umask of 022. This provides a balance between accessibility and protection—the owner can write, while others can only read.
Debugging Permissions
Checking Access
The ls -l command displays permissions, but sometimes this is not enough to understand a “Permission denied” error. The namei command displays the complete path along with the permissions of every component:
$ namei -l /home/michael/projects/website/index.html
f: /home/michael/projects/website/index.html
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxr-x--- michael michael michael
drwxr-xr-x michael michael projects
drwxr-xr-x michael michael website
-rw-r--r-- michael michael index.html
Accessing index.html requires execute permission on every directory in the path. The /home/michael directory has drwxr-x---—only the owner and the group may enter it. Other users fail at cd /home/michael and therefore never reach index.html, even if the file itself is readable.
Checking Effective Permissions
The getfacl command displays extended ACLs (Access Control Lists), if they are present:
$ getfacl file.txt
# file: file.txt
# owner: michael
# group: developers
user::rw-
group::r--
other::r--
ACLs allow more fine-grained permissions than the standard rwx model—individual users or additional groups can receive specific permissions. Most systems rarely use ACLs because rwx permissions are sufficient for almost all situations.
Security Considerations
Never Use 777
The permission 777 (rwxrwxrwx) is almost always the wrong choice. Anyone can read, modify, or delete the file. A malicious user could inject malware, steal data, or compromise the system.
Debugging situations sometimes tempt administrators to run chmod 777 because “it finally works.” This is dangerous. The correct solution is to determine the proper permissions—not to assign the most permissive ones. A web upload directory may require 775, but never 777.
Use SetUID Carefully
SetUID programs run with elevated privileges. Bugs or security vulnerabilities in SetUID root programs are critical because they can allow privilege escalation. Every additional SetUID program increases the system’s attack surface.
Only trusted, well-maintained programs should use SetUID. Never set SetUID on your own scripts—they are too prone to errors. Use sudo with specific rules instead.
Regular Audits
$ find / -perm -4000 -ls 2>/dev/null
This finds every SetUID file on the system. An unknown SetUID file is suspicious—it may indicate a compromised system or incorrectly configured software.
$ find /var/www -type f -perm -002 -ls
This finds all files under /var/www that are world-writable (-002). Web server files should never be world-writable—they represent a security risk.
Summary
Unix permissions using rwx for User, Group, and Others are simple but effective. Octal notation (644, 755, 600) is compact and quick to read. SetUID, SetGID, and the Sticky Bit extend the permission model for special requirements.
Regular files typically use 644 (owner writes, others read). Executable programs use 755 (owner writes, everyone executes). Private data uses 600 (owner only). Directories typically use 755 or 700. These four permission patterns cover roughly 90% of all situations.
The next article covers links between files—hard links and symbolic links—and explains the inode concept that underlies permissions and file names.
Software and Versions Used
This discussion refers to:
- POSIX permissions: Standard since Unix Version 7 (1979)
- Operating systems: All Linux distributions and BSD systems
- Context: Universal across all Unix-like systems
- As of: October 2025
Next steps: