LFCA 24 ๐ง Understanding File Permissions
Every file and directory on a Linux system carries a set of permission bits. These bits decide who can read the file, who can write to it, and who can execute it. They are the mechanism that enforces the separation between users, and they are checked on every file operation the kernel performs. When you run ls -l and see something like -rw-r--r--, you are looking at three groups of three bits each โ one group for the owner, one for the group, and one for everyone else. Understanding what those bits mean, how they combine, and what happens when they are wrong is the foundation of Linux security and the prerequisite for every chmod, chown, and access-control decision that follows. This chapter covers the permission model from the ground up: the three permission types, the three identity classes, how they combine for files and for directories, how the numeric and symbolic notations work, and the special bits that go beyond the basic nine.
Key point: Linux permissions are three bits for each of three identity classes โ read, write, and execute for the owner, the group, and others. For files, read means “view contents,” write means “modify contents,” and execute means “run as a program.” For directories, the meanings are different: read means “list entries,” write means “create or delete entries,” and execute means “traverse into or through the directory.” The numeric notation maps read=4, write=2, execute=1, and each class’s bits are summed into a single octal digit โ so 755 is rwxr-xr-x. Beyond these nine bits are three special bits โ setuid, setgid, and sticky โ that change how execution and deletion behave.
The three permission types
Every permission bit has one of three meanings, and the meaning depends on whether the object is a file or a directory. This is the single most important distinction in the permission model, and confusing the two is the most common source of misunderstanding.
Read (r). On a file, read grants the ability to view the file’s contents โ cat, less, grep, opening it in an editor. On a directory, read grants the ability to list the entries in the directory โ ls returns the names of the files inside. Without read on a directory, ls fails even if you know the names of the files, because listing requires reading the directory’s own data structure, which contains the mapping from names to inodes.
Write (w). On a file, write grants the ability to modify the file’s contents โ editing, appending, truncating. On a directory, write grants the ability to create, delete, and rename entries within that directory. Note the asymmetry: deleting a file is a write operation on the directory, not on the file. A file with mode 444 (read-only for everyone) can be deleted by anyone who has write permission on its parent directory, because deletion is an operation on the directory entry, not the file contents. This surprises people, and it is the source of the “how did my read-only file get deleted?” question.
Execute (x). On a file, execute grants the ability to run the file as a program โ the kernel will load it and start a process. For interpreted scripts, execute permission plus a shebang line (#!/bin/bash) allows the kernel to invoke the interpreter. On a directory, execute grants the ability to traverse the directory โ to access files inside it by name, to cd into it, to use it as a component of a path. Without execute on a directory, you cannot access any file within it, even if you know the exact path and have full permissions on the file itself. A directory with read but not execute allows listing the names but not accessing the contents, which is an unusual but valid configuration.
Why the directory meanings matter more than they seem. Most permission problems in practice involve directories, not files. A web server that cannot traverse a directory cannot serve files from it. A user who cannot write to a directory cannot create files in it, regardless of the files’ own permissions. A script that cannot be executed cannot be run, even if it is readable. The directory’s permission bits are the gate, and the file’s bits are the lock on the door behind it.
Why the execute bit on a directory is required for path resolution. When you access
/home/alice/notes.txt, the kernel traverses/, thenhome, thenalice, checking execute permission on each directory along the way. If execute is missing on any component, the traversal fails with “Permission denied” โ even if the target file is world-readable. This is why directory execute is sometimes called “search” permission; it is the ability to search for names within the directory.
The three identity classes
Every file has an owner and a group. The permission bits are divided into three sets, one for each identity class that the kernel checks.
Owner (u for user). The first set of three bits applies to the file’s owner โ the user whose UID matches the file’s owner UID. The owner is set at file creation (to the creating user) and can be changed with chown. The owner usually has the most permissions, but not necessarily โ a file can be owned by a user with fewer permissions than the group or others, though this is unusual.
Group (g). The second set applies to the file’s group โ the group whose GID matches the file’s group GID, and to which the current process belongs. Remember from LFCA 21 that a process can belong to multiple groups, and the kernel checks all of them. If the file’s group matches any of the process’s groups โ primary or supplementary โ the group permissions apply.
Others (o). The third set applies to everyone else โ any process whose UID is not the owner and whose groups do not include the file’s group. This is the catch-all class, and its permissions are often the most restrictive.
Why the kernel checks in order. The kernel evaluates the classes in order: owner first, then group, then others. The first match wins, and the remaining classes are not consulted. This means that if a user is the owner and the owner has no permissions, the user gets no permissions โ even if the “others” class grants read. The kernel does not fall through. This is a common source of confusion: “but the file is world-readable, why can’t I read it?” โ because you are the owner, and the owner bits deny it, and the kernel stops there.
Why the group match is by GID list, not by primary group alone. A process carries a set of GIDs โ its primary group and any supplementary groups. If the file’s group matches any of them, the group class applies. This is why adding a user to a supplementary group grants access to files owned by that group, without changing the user’s primary group.
Why “others” is not a fallback. It is tempting to think of “others” as “everyone who did not match the owner or group.” That is correct, but the important consequence is that narrowing “others” does not affect the owner or the group. A file with mode 700 is fully accessible to the owner and completely inaccessible to everyone else. A file with mode 770 adds group access. A file with mode 777 grants everyone everything. The classes are independent, and each is checked only if the previous ones did not match.
Reading ls -l output
The ls -l command prints the permission string, the owner, the group, and other metadata. Reading it correctly is the first practical skill.
$ ls -l notes.txt
-rw-r--r-- 1 alice developers 1024 Mar 15 10:22 notes.txt
The first character is the file type. - is a regular file, d is a directory, l is a symbolic link, c is a character device, b is a block device, s is a socket, and p is a named pipe. The next nine characters are the permission bits, in three groups of three: owner, group, others. In this example, the owner has rw-, the group has r--, and others have r--. The owner is alice, the group is developers, the size is 1024 bytes, the date is March 15, and the name is notes.txt.
The numeric equivalent. Each group of three bits maps to an octal digit. Read is 4, write is 2, execute is 1. Sum the bits in each group. rw- is 4+2+0 = 6. r-- is 4+0+0 = 4. So rw-r--r-- is 644. The full mode is 644, often written as 0644 with a leading zero. Similarly, rwxr-xr-x is 4+2+1, 4+0+1, 4+0+1 โ 755. And rwx------ is 700.
Why the leading zero matters in some contexts. Commands like chmod accept both 644 and 0644. The leading zero is sometimes required when a special bit is set โ 4755 for setuid, 2775 for setgid, 1777 for sticky. The four-digit form is the explicit way to express all twelve bits (three special plus nine regular), and it is the safer habit.
Why the file type character matters for interpretation. The same permission string means different things for a file and a directory. drwxr-xr-x is a directory where the owner can read, write, and traverse, and group and others can read and traverse. -rwxr-xr-x is a file that the owner can read, write, and execute, and group and others can read and execute. The bits are the same; the object type changes the meaning.
Why
ls -lshows the owner and group by name. The file stores UIDs and GIDs, not names.ls -llooks up the names in/etc/passwdand/etc/group. If a UID has no matching entry โ a stale UID โlsshows the number instead.ls -lnforces numeric output regardless, which is useful when names are ambiguous or when scripting.
Numeric and symbolic notation
chmod accepts two notations: numeric (octal) and symbolic. Both set the same bits, and the choice is a matter of context and clarity.
Numeric notation uses three or four octal digits. Each digit encodes one class’s permissions. 755 is rwxr-xr-x. 644 is rw-r--r--. 600 is rw-------. The notation is compact and unambiguous, and it is the standard for setting a known mode from scratch.
chmod 755 script.sh
chmod 644 document.txt
chmod 600 private.key
Symbolic notation uses letters and operators. The letters are u (owner), g (group), o (others), and a (all three). The operators are + (add), - (remove), and = (set exactly). The permissions are r, w, x, and the special bits s, t.
chmod u+x script.sh # add execute for owner
chmod go-w file.txt # remove write for group and others
chmod a+r document.txt # add read for everyone
chmod u=rw,g=r,o= file.txt # set exact permissions
Why symbolic is better for incremental changes. When you want to add execute permission without touching the other bits, chmod +x or chmod u+x expresses the intent directly. The numeric equivalent would require knowing the current mode, computing the new one, and setting it โ and if the current mode was not what you thought, you would silently change unrelated bits. Symbolic notation changes only what you specify.
Why numeric is better for exact modes. When you want a file to have exactly 600 regardless of its current state, chmod 600 is the direct expression. Symbolic notation would require chmod u=rw,go= to achieve the same result, which is more verbose. Both are correct; the choice depends on whether the operation is incremental or absolute.
The X special case. chmod +X (capital X) adds execute permission only if the file is a directory or already has execute permission for some class. This is useful for recursive operations on trees that contain both files and directories: chmod -R a+rX adds read for everyone and execute only where appropriate, without making every file executable.
Permission meanings for directories
The directory permission model is different enough from the file model that it deserves its own treatment. The three bits mean something else, and the combinations produce behaviors that are not obvious from the file case.
| Mode | Directory behavior |
|---|---|
r-- | Can list names, cannot access contents |
r-x | Can list names and access contents by name |
-wx | Can access contents if name is known, cannot list |
--x | Can access contents if name is known, cannot list |
rwx | Full access |
rw- | Can create and delete entries, cannot list or traverse |
The combinations that matter in practice are r-x (the normal readable directory), --x (the “execute-only” directory that lets someone access a file by known name without being able to list the contents), and rwx (full access). The mode rw- on a directory is unusual and mostly useless: you can create and delete entries by name, but you cannot list them or traverse into subdirectories, so you have to know the names in advance.
Why --x on a directory is useful. A web server’s document root might be --x for others, so that a client can request /index.html and get it, but cannot list the directory and discover what other files exist. The web server knows the filename from the request; the client cannot enumerate. This is a common hardening technique, and it depends on the directory execute bit meaning “traverse” rather than “list.”
Why deleting a file depends on the directory, not the file. When you rm file.txt, the kernel removes the directory entry that maps file.txt to its inode. That is a write operation on the parent directory. The file’s own permissions are irrelevant to the deletion. A file with mode 444 can be deleted if the directory has write permission. This is why rm on a read-only file does not prompt for confirmation by default in most shells โ the kernel does not consider the file’s mode.
Why the sticky bit changes deletion. The sticky bit (t) on a directory restricts deletion: only the file’s owner, the directory’s owner, or root can delete a file within the directory, regardless of write permission on the directory. This is what makes /tmp safe โ mode 1777 grants everyone write, but the sticky bit prevents one user from deleting another user’s files. Without the sticky bit, /tmp with mode 777 would let anyone delete anyone else’s temporary files.
Why the execute bit is checked on every path component. To open
/home/alice/documents/report.txt, the kernel traverses/,home,alice, anddocuments, checking execute on each. Ifalicehas mode700, then group and others cannot traverse into it, so they cannot reachdocumentsorreport.txtregardless of those objects’ permissions. The most restrictive directory in the path determines the effective access.
Special permission bits
Beyond the nine basic bits, three special bits change the behavior of execution and deletion. They occupy the position before the nine, and they are expressed as a fourth octal digit or as s and t in symbolic notation.
Setuid (s on the owner’s execute position). When set on an executable file, the process that runs it gains the file owner’s UID as its effective UID, rather than the invoking user’s. This is how passwd works: a normal user runs it, but the process temporarily runs as root, which is what allows it to write to /etc/shadow. Setuid is displayed as s where the owner’s execute bit would be, or S if the execute bit is not set (which is a misconfiguration โ the setuid bit has no effect without execute).
Setgid (s on the group’s execute position). On an executable file, setgid works like setuid but for the group: the process runs with the file’s group as its effective GID. On a directory, setgid has a different and very useful effect: files created inside the directory inherit the directory’s group rather than the creator’s primary group. This is how shared project directories work โ several users create files, and every file belongs to the same group, so the group’s permissions apply uniformly. Setgid is displayed as s in the group’s execute position, or S if execute is missing.
Sticky bit (t on the others’ execute position). On a directory, the sticky bit restricts deletion as described above: only the file owner, the directory owner, or root can delete or rename entries within the directory. On modern Linux systems, the sticky bit on a file has no effect (it was historically used to keep a program in swap, but that behavior is obsolete). The sticky bit is displayed as t in the others’ execute position, or T if execute is missing. The classic example is /tmp, which has mode 1777: rwxrwxrwt.
Why the special bits are displayed with s/S and t/T. The uppercase form signals that the special bit is set but the corresponding execute bit is not, which means the special bit is not functioning as intended. rwSr--r-- has setuid set but execute off, so the setuid behavior does not apply. This is almost always a mistake, and the uppercase letter is the signal to fix it.
Why the numeric forms are 4xxx, 2xxx, and 1xxx. Setuid is 4000, setgid is 2000, sticky is 1000. A directory with setgid and full permissions is 2775. A directory with sticky and full permissions is 1777. The four-digit form combines them: 6755 would be setuid plus setgid plus 755.
Complete Example Session
# ============================================
# PART 1: READING PERMISSIONS
# ============================================
touch file.txt
ls -l file.txt
# -rw-r--r-- 1 alice alice 0 Mar 15 10:00 file.txt
# โโโฌโโโฌโโโฌโ
# โ โ โ โโโ others: r--
# โ โ โโโโโโ group: r--
# โ โโโโโโโโโ owner: rw-
# โโโโโโโโโโโ type: regular file
# ============================================
# PART 2: NUMERIC NOTATION
# ============================================
chmod 755 file.txt
ls -l file.txt
# -rwxr-xr-x 1 alice alice 0 Mar 15 10:00 file.txt
chmod 644 file.txt
ls -l file.txt
# -rw-r--r-- 1 alice alice 0 Mar 15 10:00 file.txt
chmod 600 file.txt
ls -l file.txt
# -rw------- 1 alice alice 0 Mar 15 10:00 file.txt
# ============================================
# PART 3: SYMBOLIC NOTATION
# ============================================
chmod u+x file.txt
ls -l file.txt
# -rwx------ 1 alice alice 0 Mar 15 10:00 file.txt
chmod go+r file.txt
ls -l file.txt
# -rwxr--r-- 1 alice alice 0 Mar 15 10:00 file.txt
chmod a-x file.txt
ls -l file.txt
# -rw-r--r-- 1 alice alice 0 Mar 15 10:00 file.txt
# ============================================
# PART 4: DIRECTORY PERMISSIONS
# ============================================
mkdir testdir
ls -ld testdir
# drwxr-xr-x 2 alice alice 4096 Mar 15 10:00 testdir
# โโโฌโโโฌโโโฌโ
# โ โ โ โโโ others: r-x (list + traverse)
# โ โ โโโโโโ group: r-x
# โ โโโโโโโโโ owner: rwx
# โโโโโโโโโโโ type: directory
# ============================================
# PART 5: EXECUTE-ONLY DIRECTORY
# ============================================
mkdir secretdir
touch secretdir/known.txt
chmod 711 secretdir
ls secretdir
# ls: cannot open directory 'secretdir': Permission denied
# (no read = cannot list)
cat secretdir/known.txt
# (works โ execute allows traversal, and the name is known)
# ============================================
# PART 6: DELETION DEPENDS ON DIRECTORY
# ============================================
touch readonly.txt
chmod 444 readonly.txt
ls -l readonly.txt
# -r--r--r-- 1 alice alice 0 Mar 15 10:00 readonly.txt
rm readonly.txt
# (works โ the directory has write permission)
# ============================================
# PART 7: STICKY BIT ON /tmp
# ============================================
ls -ld /tmp
# drwxrwxrwt 15 root root 4096 Mar 15 10:00 /tmp
# โ
# โโโ t = sticky bit
# ============================================
# PART 8: SETGID DIRECTORY
# ============================================
mkdir /tmp/shared
chmod 2775 /tmp/shared
ls -ld /tmp/shared
# drwxrwsr-x 2 alice developers 4096 Mar 15 10:00 /tmp/shared
# โ
# โโโ s = setgid, files inherit "developers" group
# ============================================
# PART 9: SETUID FILE
# ============================================
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 Mar 15 10:00 /usr/bin/passwd
# โ
# โโโ s = setuid, runs as root even when invoked by a user
# ============================================
# PART 10: THE ORDER OF CHECKS
# ============================================
# As the owner, owner bits apply โ even if others would grant more
chmod 077 file.txt
ls -l file.txt
# ----rwxrwx 1 alice alice 0 Mar 15 10:00 file.txt
cat file.txt
# cat: file.txt: Permission denied
# (owner class matched, owner has no read, kernel stops)
Each part isolates one aspect of the permission model. Parts 1 through 3 show the notation. Parts 4 through 6 show the directory semantics. Parts 7 through 9 show the special bits. Part 10 shows the order-of-checks rule.
Quick Reference
Permission Values
| Symbol | Value | Meaning (file) | Meaning (directory) |
|---|---|---|---|
r | 4 | Read contents | List entries |
w | 2 | Modify contents | Create/delete entries |
x | 1 | Execute | Traverse |
- | 0 | No permission | No permission |
Common Modes
| Mode | Symbolic | Typical Use |
|---|---|---|
644 | rw-r--r-- | Regular files |
600 | rw------- | Private files, keys |
755 | rwxr-xr-x | Executables, directories |
700 | rwx------ | Private directories |
777 | rwxrwxrwx | Fully open (rarely correct) |
1777 | rwxrwxrwt | /tmp (sticky) |
2775 | rwxrwsr-x | Shared group directory |
4755 | rwsr-xr-x | Setuid executable |
Identity Classes
| Class | Symbol | Matches |
|---|---|---|
| Owner | u | Process UID = file UID |
| Group | g | Process GID in file’s group |
| Others | o | Neither owner nor group |
Special Bits
| Bit | Octal | On File | On Directory |
|---|---|---|---|
| Setuid | 4000 | Run as file owner | (no effect) |
| Setgid | 2000 | Run as file group | New files inherit group |
| Sticky | 1000 | (obsolete) | Only owner can delete |
chmod Notation
| Form | Example | Effect |
|---|---|---|
| Numeric | chmod 644 file | Set exact mode |
| Symbolic add | chmod u+x file | Add execute for owner |
| Symbolic remove | chmod go-w file | Remove write for group/others |
| Symbolic set | chmod u=rw file | Set owner to exactly rw |
| Recursive | chmod -R 755 dir | Apply to tree |
| Capital X | chmod -R a+rX dir | Execute only where appropriate |
File Type Characters
| Char | Type |
|---|---|
- | Regular file |
d | Directory |
l | Symbolic link |
c | Character device |
b | Block device |
s | Socket |
p | Named pipe |
Best Practices
โ Do This:
# Use the least privilege that works
chmod 600 ~/.ssh/id_rsa # โ
# Use 755 for directories and executables
chmod 755 /usr/local/bin/script.sh # โ
# Use 644 for regular readable files
chmod 644 /var/www/html/index.html # โ
# Use setgid for shared group directories
chmod 2775 /srv/project # โ
# Use the sticky bit on world-writable directories
chmod 1777 /tmp # โ
# Use symbolic notation for incremental changes
chmod +x script.sh # โ
# Use -R with capital X for trees
chmod -R a+rX /var/www # โ
โ Don’t Do This:
# Don't use 777 because "it works"
chmod 777 /var/www # opens everything to everyone # โ ๏ธ
# Don't set setuid on scripts
chmod u+s script.sh # ignored on most systems, unsafe # โ ๏ธ
# Don't chmod -R 777 to fix permission problems
chmod -R 777 / # catastrophic # โ ๏ธ
# Don't forget the execute bit on directories
chmod 644 somedir # cannot traverse # โ ๏ธ
# Don't assume read-only files cannot be deleted
rm readonly.txt # deletion depends on the directory # โ ๏ธ
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Owner bits deny, others allow | Kernel stops at owner | Check owner class first |
| Read-only file deleted | Deletion is a directory write | Check directory permissions |
Cannot access file in r-- directory | No traverse | Add execute: r-x |
Setuid S not s | Execute bit missing | Add execute |
| Setgid on directory not working | Wrong group or missing bit | Verify with ls -ld |
| 777 “fixes” a permission problem | Over-permissive | Grant the minimum |
| Recursive chmod changes wrong files | Applied to files and dirs alike | Use X not x |
| Numeric mode misunderstood | Decimal vs octal | 644 is octal, not decimal |
Real-World Examples
1. SSH private key
chmod 600 ~/.ssh/id_rsa
2. Web directory
chmod 755 /var/www/html
chmod 644 /var/www/html/*.html
3. Script executable
chmod 755 /usr/local/bin/backup.sh
4. Shared project directory
chmod 2775 /srv/project
5. Temporary directory
chmod 1777 /tmp
6. Setuid binary
chmod 4755 /usr/local/bin/custom-tool
7. Private directory
chmod 700 ~/private
8. Incremental execute
chmod +x deploy.sh
9. Recursive with capital X
chmod -R a+rX /srv/www
10. Exact reset
chmod 644 config.ini
Visual: Permission String Anatomy
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ - r w x r - x r - - โ
โ โ โ โ โ โ โ โ โ โ โ โ
โ โ โโฌโ โโฌโ โโฌโ โ
โ โ โ โ โ โ
โ โ โ โ โโโ others: r-- = 4 โ
โ โ โ โโโโโโโ group: r-x = 5 โ
โ โ โโโโโโโโโโโ owner: rwx = 7 โ
โ โโโโโโโโโโโโโโ type: - = regular file โ
โ โ
โ Numeric: 754 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: File vs Directory Meanings
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FILE โ DIRECTORY โ
โ โ โ
โ r = read contents โ r = list entries โ
โ (cat, less) โ (ls) โ
โ โ โ
โ w = modify contents โ w = create/delete entries โ
โ (edit, append) โ (touch, rm, mv) โ
โ โ โ
โ x = execute โ x = traverse โ
โ (./script) โ (cd, access by name) โ
โ โ โ
โ The same bits mean โ The directory's w controls โ
โ different things. โ deletion, not the file's. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Order of Checks
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Process tries to open a file โ
โ โ โ
โ โผ โ
โ Is process UID == file owner UID? โ
โ โ โ
โ โโโ Yes โโโบ Use OWNER bits. Stop. โ
โ โ โ
โ โโโ No โ
โ โ โ
โ โผ โ
โ Is file's GID in process's group list? โ
โ โ โ
โ โโโ Yes โโโบ Use GROUP bits. Stop. โ
โ โ โ
โ โโโ No โ
โ โ โ
โ โผ โ
โ Use OTHERS bits. โ
โ โ
โ First match wins. No fallthrough. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Traversal Requires Execute
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ /home/alice/documents/report.txt โ
โ โ
โ To read report.txt, the kernel checks: โ
โ / โ x โ
โ home โ x โ
โ alice โ x โ
โ documents โ x โ
โ report.txt โ r โ
โ โ
โ If /home/alice has mode 700, only alice can traverse. โ
โ Group and others fail at "alice" โ regardless of the โ
โ permissions on documents or report.txt. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Sticky Bit on /tmp
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ /tmp with mode 1777 โ
โ โ
โ drwxrwxrwt โ
โ โ โ โโโ t = sticky โ
โ โ โโโโโโ w = everyone can create โ
โ โโโโโโโโโ rwx = owner full โ
โ โ
โ alice creates /tmp/alice.tmp โ
โ bob creates /tmp/bob.tmp โ
โ โ
โ alice tries: rm /tmp/bob.tmp โ
โ โ Operation not permitted โ
โ (sticky bit: only the owner, dir owner, or root) โ
โ โ
โ Without the sticky bit, alice could delete bob's file. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Setgid Directory
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ /srv/project with mode 2775, group "developers" โ
โ โ
โ drwxrwsr-x alice developers โ
โ โ โ
โ โโโ s = setgid โ
โ โ
โ alice (primary group "alice") creates a file: โ
โ -rw-r--r-- alice developers newfile.txt โ
โ โ โ
โ โโโ group is "developers", NOT "alice"โ
โ โ
โ Every file in the directory belongs to "developers", โ
โ so group permissions apply uniformly. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Concept | Value |
|---|---|
| Read | 4 |
| Write | 2 |
| Execute | 1 |
| Owner class | u |
| Group class | g |
| Others class | o |
| Setuid | 4000 |
| Setgid | 2000 |
| Sticky | 1000 |
| Check order | Owner, group, others |
| Directory delete | Controlled by parent’s write |
| Directory traverse | Controlled by execute |
Key takeaways:
- Linux permissions are three bits for each of three identity classes โ owner, group, and others โ checked in that order, first match wins
- The bits mean different things for files and directories โ read is view vs list, write is modify vs create/delete, execute is run vs traverse
- Deleting a file is a write operation on the parent directory, not on the file itself, so a read-only file can be deleted if the directory allows it
- Traversing a path requires execute permission on every directory component โ a missing execute on any component blocks access to everything below it
- Numeric notation sums each class’s bits โ read=4, write=2, execute=1 โ producing modes like
644,755, and600 - Symbolic notation is better for incremental changes and numeric notation is better for exact modes
- The setuid bit makes a program run as its owner โ this is how
passwdwrites to/etc/shadowwithout running as root - The setgid bit on a directory makes new files inherit the directory’s group โ the standard pattern for shared project directories
- The sticky bit on a directory restricts deletion to the file owner, directory owner, or root โ the mechanism that keeps
/tmpsafe - The most common permission mistake is granting more than necessary โ
777is almost never the right answer, and the fix for a permission problem is to find the missing bit, not to open everything
Remember: File permissions are the kernel’s answer to “who can do what.” The model is small โ nine bits, three classes, three types โ but the interaction with directories, path traversal, and the special bits produces a system that is expressive enough for everything from private keys to shared team directories. Learn to read ls -l at a glance, know the difference between file and directory meanings, and treat the special bits as tools for specific problems rather than defaults.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!