Table of contents
- Why Are Permissions So Strict?
- User, Group, and Others
- Decoding the 9 Characters of ls -l
- chmod — Changing Permissions
- chown — Changing Ownership
- sudo — Borrowing Privileges Only When Needed
- umask — Determining Default Permissions for New Files
- SUID, SGID, Sticky Bit — The Three Special Permission Bits
- Permission Debugging — When You’re Stuck in Practice
- Recap of This Part
Why Are Permissions So Strict?
You uploaded a deployment script to a server, but Permission denied blocks execution. You try to edit someone else’s file and get rejected with “that’s not yours.” Why does everything keep getting blocked, and why was the system designed this way? — Every Linux beginner has gone through this frustration at least once.
The answer is simple. Linux was designed from the start with the premise of multiple users sharing a single machine. In the 1970s, dozens of users simultaneously connected to and worked on the minicomputers running UNIX. File permissions are the safeguard preventing someone from breaking another person’s files and preventing regular users from touching system files. This structure has survived nearly unchanged for over 50 years.
This part starts by decoding those cryptic symbols on the left side of ls -l output.
User, Group, and Others
Every file in Linux has three types of “stakeholders.”
flowchart LR
FILE["File or Directory"]
FILE --> OWNER["Owner<br/>(owner / user)"]
FILE --> GROUP["Group<br/>(group)"]
FILE --> OTHER["Everyone else<br/>(others / world)"]
- Owner: The specific user who created the file (or was designated as administrator)
- Group: A collection of users. Groups like
developers,docker,sudoexist. A user can belong to multiple groups simultaneously - Others: Everyone who is neither the owner nor a group member
For each stakeholder, actions on the file are split into read (r), write (w), and execute (x), each allowed or denied. 3 x 3 = 9 bits complete the access permissions.
The command to check which groups you belong to is id.
id
# uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),999(docker)
groups
# alice sudo docker
alice belongs to her own default group (primary group), and is additionally a member of the sudo and docker groups. This structure is why you need to be in the docker group to access the Docker socket.
Decoding the 9 Characters of ls -l
Let’s pull up the beginning of ls -l output again.
-rwxr-xr-- 1 alice developers 1024 Apr 20 10:30 deploy.sh
As mentioned earlier, the first character (-) is the file type. The next 9 characters are permissions, split into three groups of three.
- rwx r-x r--
│ │ │ │
│ │ │ └── others: read only
│ │ └──────── group: read and execute
│ └────────────── owner: read, write, and execute
└─────────────────── regular file
r(read, 4): Can read the file’s contents. For directories, it means “list contents”w(write, 2): Write access allowed. For directories, it means “permission to create or delete files inside it”x(execute, 1): For files, permission to run as an executable. For directories, it means “cdinto it is possible”
Without x on a directory, you can’t even cd into it. Conversely, a directory with only r but no x creates a peculiar state where ls can see the names but you can’t access the files inside. The subtle differences that emerge from combining these permissions can be confusing at first — it’s better to try creating them yourself.
chmod — Changing Permissions
Permission changes are done with chmod (CHange MODe). There are two syntaxes.
Symbolic Mode — Human-Readable
Uses the format user type + operator + permission.
# User types: u(user/owner) g(group) o(others) a(all)
# Operators: + (add) - (remove) = (set exactly this)
# Permissions: r w x
chmod u+x deploy.sh # Add execute permission for the owner
chmod g-w notes.txt # Remove write permission from the group
chmod o=r secret.env # Others get read only
chmod a+r public.md # Add read permission for everyone
chmod u=rwx,g=rx,o=r file # Multiple specifications, comma-separated
Numeric Mode — Much Faster Once You Learn It
This method views each digit as a 3-bit binary number. Add r=4, w=2, x=1.
Permission Binary Decimal
--- --- ---
rwx 111 7
rw- 110 6
r-x 101 5
r-- 100 4
-wx 011 3
-w- 010 2
--x 001 1
--- 000 0
Lining up three digits (owner, group, other) gives you the numeric mode.
chmod 755 deploy.sh
# owner=rwx(7), group=r-x(5), other=r-x(5)
chmod 644 notes.txt
# owner=rw-(6), group=r--(4), other=r--(4)
chmod 600 ~/.ssh/id_rsa
# Only the owner can read and write. SSH private keys must be 600 to work
A few combinations come up frequently in practice.
- 755: Standard for executables and directories
- 644: Standard for regular documents/text files
- 600: Sensitive key files (SSH, GPG)
- 700: Personal directories (
~/.ssh) - 777: Everyone can do everything. Almost never use this in production — the moment you say “permissions weren’t working so I set it to 777,” you’ve created a security hole
For recursive application, use the -R option. However, applying the same permissions to both files and directories causes problems — directories need x, but files get unnecessary x. In such cases, combine with find.
# Directories get 755, files get 644
find /path/to/dir -type d -exec chmod 755 {} \;
find /path/to/dir -type f -exec chmod 644 {} \;
chown — Changing Ownership
The command to change the owner or owning group is chown (CHange OWNer). It usually requires root privileges.
# Change owner only
sudo chown alice file.txt
# Change owner and group at once (separated by colon)
sudo chown alice:developers file.txt
# Change group only — leave the part before the colon empty, or use chgrp
sudo chown :developers file.txt
sudo chgrp developers file.txt
# Recursively
sudo chown -R alice:developers /var/www/site
A common scenario when running web servers is “I upload files with my account, but the www-data user runs them.” In this case, you keep the owner as your account, change the group to www-data, and grant read/execute permission to the group.
sudo — Borrowing Privileges Only When Needed
The supreme administrator in Linux is the root user (UID 0). But staying logged in as root all the time is dangerous. A single typo can destroy the system, and there’s often no way to recover accidentally deleted files.
That’s why sudo (SuperUser DO) exists. You stay as a regular user normally, and borrow root’s power only for the one command that needs admin privileges.
# Trying as a regular user — denied
apt install nginx
# Permission denied
# Prefix with sudo for one-time root access
sudo apt install nginx
# Switch to a root shell entirely (use with caution)
sudo -i
# or
sudo su -
Users who can use sudo are defined in the /etc/sudoers file (or files in /etc/sudoers.d/). Depending on the distribution, users in the sudo or wheel group are configured to use sudo by default.
Never edit the sudoers file directly with vi. A syntax error can lock you out of the system. Always use visudo — it validates the syntax before saving.
sudo visudo
umask — Determining Default Permissions for New Files
When you create an empty file with touch new.txt, what are the default permissions? Usually 644 (rw-r--r--). What determines this default is umask (User MASK).
umask specifies the permissions to subtract. It works by subtracting the umask value from the “potential maximum permissions” of a new file.
- Maximum default for files:
666(execute permission x is excluded for safety) - Maximum default for directories:
777
Let’s say the typical umask is 022.
File: 666 - 022 = 644 (rw-r--r--)
Directory: 777 - 022 = 755 (rwxr-xr-x)
Here’s how to check and set the current umask value.
umask
# 0022
# Set a stricter value — completely block group/others write permission
umask 077
# Check a newly created file
touch test.txt
ls -l test.txt
# -rw------- 1 alice alice 0 Apr 20 10:30 test.txt
With 077, new files get 600 and new directories get 700. If protecting personal data matters on a shared server, a common pattern is to hardcode umask 077 in ~/.bashrc or ~/.zshrc.
An important note: umask does not change permissions on existing files. It only affects the “default permissions of files created going forward.”
SUID, SGID, Sticky Bit — The Three Special Permission Bits
Occasionally you’ll see s or t mixed into ls -l output. These are special permission bits. In numeric mode, they’re represented by the leading digit (4xxx, 2xxx, 1xxx).
SUID (Set User ID) — Execute with the Owner’s Permissions
When SUID is set on an executable, it runs with the file owner’s permissions regardless of who executes it. The x in the owner position becomes s.
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 Feb 5 11:35 /usr/bin/passwd
The passwd command lets regular users change their own password. But the actual password is stored in /etc/shadow, which only root can write to. SUID is the solution. Because passwd has SUID set, even a regular user temporarily gains root privileges when executing it, allowing them to modify /etc/shadow.
SUID is powerful, and accordingly the most dangerous bit from a security perspective. If a SUID binary has a vulnerability, it becomes a pathway for privilege escalation. It’s worth reviewing the list of SUID binaries on your server at least once.
sudo find / -perm -4000 -type f 2>/dev/null
SUID is set with chmod u+s or chmod 4xxx.
SGID (Set Group ID) — Group Inheritance
When SGID is set on a directory, new files created inside it automatically inherit the directory’s group. The x in the group position becomes s.
sudo mkdir /shared
sudo chown alice:developers /shared
sudo chmod 2775 /shared # Leading 2 is SGID
# drwxrwsr-x alice developers /shared
# Now regardless of who creates a file, its group will be developers
cd /shared && touch file.txt
ls -l file.txt
# -rw-r--r-- bob developers ... file.txt
This is useful when creating shared team folders. Regardless of which group each person logged in with, all files created in that folder share the same group.
Sticky Bit — You Can Only Delete Your Own Files
Look at the permissions on /tmp and you’ll see something unusual.
ls -ld /tmp
# drwxrwxrwt root root /tmp
The last character is t instead of x. This is the sticky bit. It’s a mechanism that restricts a world-writable directory so that only the creator of a file can delete it. In places like /tmp where every user writes temporary files, it prevents users from deleting each other’s files.
chmod +t mydir
chmod 1777 mydir
Permission Debugging — When You’re Stuck in Practice
A checklist to run through when someone says “it won’t execute.”
- Does the file itself have
x? Check withls -l script.sh. If not,chmod +x - Does the directory containing the file have
x? Without directoryx, you can’t access files inside it - Do all parent directories have
x? To execute/home/alice/scripts/run.sh,/,/home,/home/alice, and/home/alice/scriptsall needx - Is SELinux or AppArmor blocking it? Especially on RHEL-based systems, if
ls -lshows permissions look fine but access is still denied, suspect the SELinux context (ls -Z) - Is the filesystem mounted with
noexec? If/tmpis mounted withnoexec, script execution is completely blocked (mount | grep /tmp)
Permission problems are usually caught at #1 and #3. Especially #3 — x on parent directories — is the easiest point for beginners to miss.
Recap of This Part
A brief summary.
- Every file has r/w/x permissions for three groups: owner, group, and others
chmoduses two syntaxes: symbolic mode (u+x) and numeric mode (755). Numeric mode uses r=4, w=2, x=1chownchanges the owner,chgrp(orchown :group) changes the groupsudoallows “root for this one time.”/etc/sudoersmust be edited withvisudoumaskdetermines default permissions for new files. The calculation is “maximum - umask”- SUID executes with the owner’s permissions, SGID inherits the group, and sticky bit restricts deletion to the file owner
In the next part, we move beyond the world of files and permissions into processes. From PIDs to signals to background execution — we’ll dig into what “running” really means in Linux.

Loading comments...