How Linux file permissions map to binary — rwx representation, chmod octal-to-binary conversion, and practical permission bit manipulation.
Every Linux file permission is stored as a sequence of binary bits. I've spent years working with Linux systems, and the single most important insight I can share is this: think of rwx not as letters, but as a 3-bit binary number. Each letter is a position: r (read) is the high bit (22 = 4), w (write) is the middle bit (21 = 2), and x (execute) is the low bit (20 = 1).
When you see rwx, that's binary 111 which is decimal 7. When you see rw-, the execute bit is 0, so it's 110 = 6. A dash simply means that bit position is 0. This is why chmod uses octal: each octal digit from 0 to 7 maps perfectly to a 3-bit rwx group. Here is the complete mapping:
I have debugged many permission issues on production Linux servers where a file was readable but not executable — that is the difference between 644 and 755 in action, and it always comes down to that execute bit being set.
| Octal | Binary | rwx | Meaning |
|---|---|---|---|
| 0 | 000 | --- | No permissions |
| 1 | 001 | --x | Execute only |
| 2 | 010 | -w- | Write only |
| 3 | 011 | -wx | Write + execute |
| 4 | 100 | r-- | Read only |
| 5 | 101 | r-x | Read + execute |
| 6 | 110 | rw- | Read + write |
| 7 | 111 | rwx | Read + write + execute |
In my experience, the confusion most people have is that 4 does not mean "read" — it means "the read bit is 1 and the write and execute bits are 0." The value 4 is just the decimal representation of the 3-bit binary sequence 100. When you type chmod 644, Linux interprets each octal digit independently and sets the corresponding 3-bit pattern.
A Linux file permission string like rwxr-xr-- is 9 bits grouped into three triples: owner (bits 8-6), group (bits 5-3), and others (bits 2-0). The full binary representation is:
Let's walk through one of the most common permission sets I use in production. chmod 754 is typical for directories and executable scripts where the owner needs full control, the group needs read and execute, and everyone else gets read-only access.
I use 754 extensively for web application directories. The web server process typically runs under a specific group, so group members can traverse directories (execute) and read files. The owner — usually my deployment user — has full control to create, delete, and modify files within the directory. Others can only read, which prevents unauthenticated users from listing directory contents or executing scripts.
Here is the bit-by-bit breakdown of every individual bit in the 754 mask:
| Bit Pos | Class | Permission | Value | 754 Bit |
|---|---|---|---|---|
| 8 | Owner | Read | 4 | 1 |
| 7 | Owner | Write | 2 | 1 |
| 6 | Owner | Execute | 1 | 1 |
| 5 | Group | Read | 4 | 1 |
| 4 | Group | Write | 2 | 0 |
| 3 | Group | Execute | 1 | 1 |
| 2 | Others | Read | 4 | 1 |
| 1 | Others | Write | 2 | 0 |
| 0 | Others | Execute | 1 | 0 |
chmod 644 is the standard permission set for regular files. I have thousands of files on production servers with 644 — it is the default for most Linux distributions when you create a new file. The owner can read and write, while everyone else can only read.
One thing I've learned the hard way: never put executable scripts in 644. If you create a shell script or a Python script and the file is 644, you will get a Permission denied error when trying to run it. The execute bit (bit 6 in the owner triple) is 0. You need at least 755 for executables. But for configuration files, HTML files, CSS, JavaScript assets, and log files, 644 is perfectly fine and actually preferred from a security standpoint.
In my work, I always reserve 644 for static assets. Here is a quick rule of thumb I follow:
Run stat -c "%a %n" file.txt to see the octal permission value of any file. I use this constantly during deployment audits — it tells me immediately if a sensitive file has accidentally been made world-readable. Compare this to the binary representation on our bitwise calculator to confirm your understanding of each bit.
chmod 777 is the most permissive — and most dangerous — permission set. In binary it is 111111111. Every single bit is set to 1. The owner, group, and others all have read, write, and execute permissions. I want to be very clear: in almost every production scenario, this is a bad idea.
I have seen 777 used as a quick fix when a web application can't write to a directory. And yes, it works — but it also means any user on the system, including compromised accounts, can modify those files. If an attacker gains even minimal access to a server, 777 directories are gold mines.
A far better approach in my experience is to find the correct owner and group for the process that needs write access and set 775 instead. This gives the owner and group full access while locking others to read and execute only. The binary difference is 111111101 vs 111111111 — just the last 2 bits of the others triple go from 11 to 01.
The Linux permission model divides users into three security classes, each represented by exactly 3 bits. Understanding this structure is fundamental to working with file permissions at the binary level.
The first three bits encode the file owner's permissions. Bit 8 is the read bit (numerical value 256 in the full 9-bit mask), bit 7 is write (128), and bit 6 is execute (64). When you see rwx------, that's 111000000 in binary — 700 in octal. Only the owner has any access at all.
Bits 5 (read, value 32), 4 (write, value 16), and 3 (execute, value 8) define what members of the file's group can do. For ---rwx---, that's 000111000 in binary, or 070 in octal — only the group has full access. I use this pattern rarely but it is useful for shared project directories where the group needs control but the owner should not be special.
Bits 2 (read, value 4), 1 (write, value 2), and 0 (execute, value 1) control everyone else. For ------rwx, that's 000000111 = 007 octal. I have never used 007 in production — giving write permission to "others" is almost always a mistake.
Once you understand that permissions are just bits, you can manipulate them programmatically using bitwise operations. I frequently write scripts that need to check or modify file permissions without calling external commands.
To check whether the group execute bit is set, you test bit 3 of the permission mask:
To add the group write permission without affecting other bits, use OR:
To remove the others write bit, use AND with NOT:
In my shell scripts, I use these patterns with $((...)) arithmetic to compute permission masks on the fly. For instance, $((mask | (1 << 4))) adds group write. This is much cleaner than parsing and reconstructing the symbolic u+x form when you are working with numeric permission values programmatically.
Use the bitwise calculator to convert any permission octal to binary instantly. Experiment with different combinations and see exactly which bits change.
rwx represents three binary bits: read (r) is the high bit (value 4, binary 100), write (w) is the middle bit (value 2, binary 010), and execute (x) is the low bit (value 1, binary 001). A dash means that bit is 0. So rwx = 111 (7), rw- = 110 (6), r-x = 101 (5), r-- = 100 (4).
chmod 754 breaks down as: 7 = 111 (rwx for owner), 5 = 101 (r-x for group), 4 = 100 (r-- for others). The full binary representation is 111101101. Each octal digit maps directly to a 3-bit binary group representing the rwx permissions for one security class.
chmod 644 breaks down as: 6 = 110 (rw-) for the owner, 4 = 100 (r--) for the group, 4 = 100 (r--) for others. In binary: 110100100. The owner can read and write, while group members and others can only read. This is the standard permission set for regular files because you want everyone to read but only the owner to modify.
chmod 777 in binary is 111111111. Each octal digit 7 maps to 111 (rwx), so all three triples are fully set: owner=111, group=111, others=111. This gives everyone read, write, and execute permissions. It is generally considered insecure and should only be used in very specific circumstances.
chmod uses octal (base-8) as its input format. Each octal digit from 0 to 7 corresponds to a 3-bit binary sequence. Octal is convenient because 3 bits exactly represent the rwx permission triple for one user class. The chmod command accepts octal values like 644, 755, and 700 because each digit maps cleanly to a 3-bit rwx pattern.
To add execute permission for the owner, use mask | (1 << 6). For the group, use mask | (1 << 3). For others, use mask | (1 << 0). The bit positions correspond to the 9-bit permission layout where bit 6 is owner-execute, bit 3 is group-execute, and bit 0 is others-execute.
755 in binary is 111101101 (rwxr-xr-x) and 754 is 111101100 (rwxr-xr--). The difference is just the last bit — bit 0 (others-execute). In 755, others can execute; in 754 they cannot. For directories, the execute bit on others controls whether they can traverse into the directory and list its contents.