chown changes owner and group; chgrp changes group only
setuid, setgid, and sticky bits are special modes that alter execution behavior
Most permission-related incidents stem from missing execute on directories or incorrect group ownership
✦ Definition~90s read
What is Linux File Permissions?
Linux file permissions are the operating system's access control system, determining who can read, write, or execute files and directories. Every file and directory has an owner user and group, plus three permission triads: one for the owner (user), one for the group, and one for others (everyone else).
★
Think of every file on your Linux system as a room in a building.
Each triad consists of read (r=4), write (w=2), and execute (x=1) bits, commonly expressed as octal numbers (e.g., 755) or symbolic strings (e.g., rwxr-xr-x). This model is fundamental to multi-user systems and server security — misconfiguring it is why your Nginx workers silently fail to serve static assets or your cron jobs can't write logs.
You manipulate permissions with chmod (change mode), ownership with chown (change owner) and chgrp (change group). The classic pitfall: running chown -R www-data:www-data /var/www might fix one problem but break Nginx workers if the user running the master process (often root) can't access the worker's socket or log files because the sticky bit or group permissions were stripped.
Special modes like setuid (4000), setgid (2000), and the sticky bit (1000) add nuance — setuid on an executable runs it as the file owner (think passwd), setgid on a directory forces new files to inherit the group, and the sticky bit on /tmp prevents users from deleting each other's files.
In practice, you'll debug permission errors with ls -la, stat, and strace to see exactly which syscall fails with EACCES. Common patterns: web servers need directories to be 755 and files 644, with the server user (e.g., www-data) owning the content or being in the group.
For team access, use group ownership with setgid on shared directories (e.g., chmod g+s /project/data) so new files automatically belong to the team's group. Avoid 777 like the plague — it's a security hole that screams 'I don't understand permissions.' When Nginx workers can't read your SSL certificate or write to a Unix socket, it's almost always because the worker user (not the master process) lacks the correct permission bit on some parent directory or file.
Plain-English First
Think of every file on your Linux system as a room in a building. File permissions are the lock-and-key rules that decide who can enter (read), rearrange the furniture (write), or actually use the room as an office (execute). There are three groups of people who might want in: the owner of the room, a team the owner belongs to, and everyone else in the building. Linux lets you set different rules for each group — so your boss can edit the room, your colleagues can only look around, and random strangers can't even peek through the window.
Every production outage story that starts with 'well, someone accidentally deleted...' or 'the web server suddenly couldn't read its own config...' has file permissions somewhere near the root cause. Linux file permissions aren't just a theoretical concept buried in a sysadmin handbook — they're the first line of defence between a running application and chaos. Misconfigure them and you've either locked your own service out of its data, or handed a malicious actor a skeleton key to your entire system.
The permission system exists because Linux was designed from day one as a multi-user operating system. Unlike early personal computers where one person owned everything, Unix-descended systems needed a way to let dozens of users share the same machine without stepping on each other's work — or worse, each other's secrets. The read/write/execute model, combined with user/group/other ownership, solves that problem elegantly with just nine bits of information per file.
By the end of this article you'll be able to read any permission string at a glance, write chmod commands in both symbolic and octal notation without guessing, set up group-based access patterns for real team deployments, understand the dangerous-but-useful setuid/setgid/sticky bits, and diagnose permission-related errors before they become production incidents.
What Are Linux File Permissions?
Linux file permissions are a set of rules that determine who can read, write, or execute a file or directory. Every file and directory is owned by a user and a group. Permissions are defined for three categories: the file owner, the owning group, and everyone else (others). The permissions themselves are three bits: read (r), write (w), and execute (x). For directories, read lets you list contents, write lets you create/delete files inside, and execute lets you enter the directory.
The classic permission string looks like this: -rwxr-xr--. The first character is the file type (- for regular file, d for directory, l for symlink). The next nine characters are three triples: owner, group, others. The example above means the owner can read, write, and execute; group members can read and execute; everyone else can only read.
Chances are you've seen Permission denied when trying to access a file you know exists. That's the permission system doing its job — blocking access that wasn't explicitly granted. Understand these nine bits and you'll stop guessing why your app can't read its config.
check-permissions.shBASH
1
2
3
4
5
6
#!/bin/bash
ls -la /var/log/auth.log
# Output example:
# -rw-r----- 1 root adm 12345Mar0610:00 /var/log/auth.log
# Owner: root (rw-), Group: adm (r--), Others: --- (-)
# So only root can write; root and adm group members can read; nobody else can access
Output
-rw-r----- 1 root adm 12345 Mar 06 10:00 /var/log/auth.log
Mental Model
Permission Bits as a Tri-Lock System
Think of each triple as a lock: owner holds the first key, group holds the second, everyone else gets the third.
Owner triple: the file's owner can set different restrictions for themselves.
Group triple: files belong to one group; all group members share the second key.
Other triple: any user not owner or group member — the public lock.
A missing execute bit on a directory is like locking the building door: even with read, you can't step inside.
📊 Production Insight
A common production trap: giving 777 permissions to a directory 'just to make it work.'
That means every user on the system can write to that directory — including compromised accounts.
Rule: never use 777 in production. Use octal modes like 755 for directories that need broad access, 750 if group control is enough.
🎯 Key Takeaway
Permissions are nine bits, not magic.
The default umask typically gives 755 for directories and 644 for files — that's secure for most single-user setups.
The rule: if a file's permissions don't match the process user's needs, you get a silent crash.
When to Use Which Permission Level
IfSingle user needs full control (e.g., personal scripts)
→
Use700 for files (rwx------), 755 for directories (rwxr-xr-x)
IfMultiple users in a team need write access to shared files
→
UseUse a common group, set ownership to that group, and use 775 (rwxrwxr-x)
IfWeb server needs to read static assets but not write
→
UseOwner: deployment user, Group: www-data, Permissions: 644 for files, 755 for directories
IfA binary should execute as a different user (e.g., passwd)
→
UseSet the setuid bit: chmod 4755 (u+s)
thecodeforge.io
Linux File Permissions
Changing Permissions with chmod (Symbolic and Octal)
chmod is your tool to modify permissions. Two modes: symbolic and octal. Symbolic uses letters: u (owner), g (group), o (others), a (all), combined with + (add), - (remove), = (set exactly). Example: chmod u+x script.sh adds execute for the owner. Octal mode uses a three-digit number (0-7) where each digit represents the sum of r=4, w=2, x=1. So 754 means owner=rwx (7), group=rx (5), others=r (4).
Which should you use? Symbolic is clearer for one-off changes like 'add execute for owner.' Octal is more reliable for scripts because it's unambiguous — you set the exact permissions regardless of the current state. Use octal in deployment pipelines.
A common mistake:chmod 777 to 'fix' a permission problem. Don't. It's lazy and dangerous. Always figure out the minimum permissions needed. For directories, note that execute is required to enter — so web apps often need 755 on public directories.
chmod-examples.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
# Symbolic: add execute for owner
chmod u+x deploy.sh
# Symbolic: remove write for group and others
chmod go-w config.yml
# Symbolic: set exactly rwx for owner, rx for group, nothing for others
chmod u=rwx,g=rx,o= config.yml
# Octal: set to 755 (rwxr-xr-x)
chmod 755 app.sh
# Octal: set to 644 (rw-r--r--)
chmod 644 index.html
# Recursive: change all files inside directory (be careful!)
chmod -R 755 /var/www/html
⚠ Note: Recursive chmod Can Wreck Your System
Using chmod -R on a large directory tree without checking what's inside can break setuid binaries, change permissions on sensitive system files, or make scripts inaccessible. Always test on a copy or use find with -type d and -type f to set directory vs file permissions separately.
📊 Production Insight
Using symbolic mode in a script can accidentally add or remove bits you didn't intend.
Octal mode is deterministic: chmod 644 always produces the exact same permissions regardless of the current state.
Rule: use octal in automation, symbolic in interactive shells.
🎯 Key Takeaway
chmod octal is idempotent.
Symbolic is great for quick one-off changes.
Never use 777 — find the minimal permissions your service needs.
Changing Ownership with chown and chgrp
chown changes the owner and/or group of a file. chgrp changes only the group. The syntax: chown newowner:newgroup file — if you omit the group, the file's group stays unchanged; if you omit the owner, you must include a colon: :newgroup. Common scenario: after deploying code with a build tool (like Jenkins running as jenkins user), the files end up owned by jenkins:jenkins. But your web server runs as www-data. The server can't read the files. The fix: chown -R www-data:www-data /var/www/app or better, chown -R www-data:appgroup /var/www/app and use group permissions.
Important: only root can change file owners. However, the owner of a file can change its group to any group they belong to (with chgrp). So if an app runs as a non-root user but needs to share files with a team, the user can chgrp the files to a common group.
A tricky edge case: symbolic links. By default, chown and chgrp follow symlinks — they change the target, not the link itself. To change the link's ownership, use chown -h. This catches many admins off guard.
chown-examples.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
# Change owner only
chown alice report.txt
# Change owner and group
chown alice:developers report.txt
# Change group only (alternatives)
chown :developers report.txt
chgrp developers report.txt
# Recursively change owner and group (common deployment)
chown -R www-data:www-data /var/www/app
# Change symlink ownership directly (not target)
chown -h bob link_to_report.txt
# Find files owned by a specific user and fix them
find /var/www -user jenkins -exec chown www-data: {} +
🔥Tip: Check User and Group Before Changing
Before fixing permissions, identify the users and groups involved: id, getent passwd, getent group. Know your service's runtime user (check systemd service file or process table with ps aux) – that's who needs access.
📊 Production Insight
A CI/CD script that runs chown -R as root can accidentally change ownership of system files if the path is wrong.
Always isolate deployment directories and use explicit paths.
Rule: if you need to change ownership, understand the minimal scope and use find to target only the application files.
🎯 Key Takeaway
Only root can chown a file.
File owners can chgrp to groups they belong to.
Watch symlinks — they follow the target by default.
thecodeforge.io
Linux File Permissions
Special Modes: setuid, setgid, and the Sticky Bit
Beyond the basic nine bits, Linux provides three special permission modes that change how executables and directories behave:
setuid (octal 4000 or u+s): When set on an executable, the process runs with the file owner's privileges, not the user who launched it. Classic example: /usr/bin/passwd — it's owned by root and has setuid, so normal users can change their own password (which writes to /etc/shadow that only root can write to).
setgid (octal 2000 or g+s): On executables, the process runs with the group of the file. On directories, new files created inside inherit the directory's group, not the creating user's primary group — incredibly useful for shared team directories.
Sticky bit (octal 1000 or o+t): On directories, only the owner of a file can delete or rename that file. Most commonly used on /tmp — everyone can write to /tmp, but only the file owner can remove what they created.
Setuid is powerful and dangerous. A bug in a setuid binary can give an attacker root privileges. That's why Linux ignores setuid on scripts (shebangs) for security reasons — but it still works on compiled binaries. Use setuid sparingly and audit it regularly.
Setgid on directories is a safe and effective pattern for collaborative workspaces. Example: chmod g+s /shared/project; chown :projectteam /shared/project.
special-modes.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# View special bits in permission string
ls -l /usr/bin/passwd
# -rwsr-xr-x — the s in owner's execute slot indicates setuid
# Set setuid on a compiled binary (must be root or owner)
chmod u+s mybinary
# Alternative octal: chmod 4755 mybinary
# Set setgid on a directory for team collaboration
chmod g+s /shared/teamdata
chown :developers /shared/teamdata
# Nownew files get group 'developers' automatically
# Set sticky bit on a shared directory
chmod +t /shared/upload
# Only file owners can delete their files
# Check all setuid binaries on the system (security audit)
find / -type f -perm -40002>/dev/null
Output
-rwsr-xr-x 1 root root 68208 Mar 15 2024 /usr/bin/passwd
⚠ Security: Setuid on Shell Scripts Is Ignored
Linux kernel ignores the setuid bit on scripts with a shebang because of race conditions. If you need a privileged helper, write it in C or a compiled language and set setuid on the binary. Do NOT rely on setuid on Python or Bash scripts — it simply won't work.
📊 Production Insight
Setgid on directories is one of the most underused production patterns.
It solves the 'different users create files with wrong group' problem without complex ACLs.
Setuid binaries are prime targets for privilege escalation — monitor them with tools like aide or tripwire.
Sticky bit on /tmp prevents a common attack: a user overwriting another's temporary file.
🎯 Key Takeaway
Setuid elevates privileges — use only when necessary.
Setgid on directories enforces group inheritance.
Sticky bit prevents unauthorised file deletion in shared spaces.
Real-World Patterns for Team Access
In production, it's rare to find a machine with only one user. You have deployment users, application users, monitoring agents, and human admins. The trick is to set up permissions so that every process gets exactly what it needs and nothing more.
Pattern 1: The Deploy User + Web Server User - Code is delivered by a deploy user (e.g., jenkins or deploy). The web server runs as www-data. - Best approach: make both users part of a common group like appgroup. Set files to 750 and directories to 755, owned by deploy:appgroup. The deploy user writes, the web server reads.
Pattern 2: Shared Project Directory - Team members need to edit files in /home/projects/foo. Each member has their own login. - Create a group fooproj, add all members. Set ownership nobody:fooproj (or any user, doesn't matter as long as group exists). Use setgid on the directory: chmod g+s /home/projects/foo; chmod 2775 /home/projects/foo. Now every file created inside automatically gets group fooproj and group-write permission.
Pattern 3: Locking Down Sensitive Config - Configuration files for a service (e.g., database credentials) should be readable only by the service user and root. Set chmod 600 or 640 if group needs read. Use chown root:servicegroup. - For log files, use 640 with owner being the service user and group being a monitoring group. Add the monitoring tool's user to that group.
These patterns avoid the 'chmod 777 everything' anti-pattern and keep your system secure.
production-pattern.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# Pattern: Deploy + WebServer
mkdir -p /var/www/app
chown deploy:www-data /var/www/app
chmod 2775 /var/www/app # setgid ensures new files inherit group
# Files: deploy writes, www-data reads
find /var/www/app -type f -exec chmod 640 {} \;
find /var/www/app -type d -exec chmod 2755 {} \;
# Pattern: Shared project with setgid
mkdir -p /shared/project
chown :projectgroup /shared/project
chmod 2775 /shared/project
# New files created by any team member will be group-writable
# Pattern: Config lockdown
# Presume service runs as 'myservice', monitoring as 'monitor'
cp config.prod.yml /etc/myapp/
chown root:myservice /etc/myapp/config.prod.yml
chmod 640 /etc/myapp/config.prod.yml
usermod -aG myservice monitor # add monitor user to group
💡Use ACLs for Complex Scenarios
For cases where multiple groups need different permissions, Linux Access Control Lists (ACLs) give you fine-grained control beyond user/group/other. Use setfacl -m g:deploy:rwx,g:www-data:rx /path. But be aware: ACLs add complexity and are not visible in 'ls -l' — you need getfacl to see them.
📊 Production Insight
Team access patterns often fail because someone forgets the setgid on a shared directory.
Without setgid, each user's files end up in the user's primary group, breaking shared write access.
Rule: if a directory is shared, use setgid (chmod g+s) and 2775 to maintain group consistency.
🎯 Key Takeaway
Design permissions around user and group relationships, not broad access.
Setgid on shared directories is your friend.
Minimal permissions = fewer security incidents.
Debugging Permission Errors in Practice
When you hit a permission error, don't guess. Follow a systematic approach:
Identify the process user: ps aux | grep service-name – that user is who needs access.
Check the file's permissions and ownership: ls -la /path, stat -c '%a %U %G' /path.
Check the path: A directory in the path may lack execute permission. Use namei -l /full/path.
Check groups: id $service_user — is the service user in the group that owns the file?
Check for ACLs: getfacl /path — ACLs override basic permissions.
Check for mount options: mount | grep /path — the filesystem may be mounted with noexec or nosuid.
Most permission bugs are simple: missing execute on a directory, wrong group membership, or an accidental chmod 000 from a script. But sometimes the problem is subtle — like a SELinux or AppArmor policy that denies even though file permissions look correct. Always check dmesg or ausearch for AVC denials if you're on an SELinux-enabled system.
debug-permissions.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# Step1: Find which user is running the process
SERVICE=$(systemctl show -p MainPID nginx.service | cut -d= -f2)
USER=$(ps -o user= -p $SERVICE)
echo "Process runs as: $USER"
# Step2: Check file and path
FILE="/var/www/app/index.php"
ls -la "$FILE"
namei -l "$FILE"
# Step3: Check user's groups
echo "User groups:"
id "$USER"
# Step4: CheckifACLs are involved
getfacl "$FILE"
# Step5: Check mount options for noexec
echo "Mount options for parent directory:"
stat -f -c '%T %O'"$FILE"
🔥Remember: Strace Shows Real-Time Access Checks
If you need to see exactly what permissions are being checked, run strace -e trace=access,openat -p $PID. It shows every file access attempt and the return code. This is the nuclear option — always try namei first.
📊 Production Insight
The most misleading permission error is a 403 from a web server that actually comes from a missing index file or a configuration reload. Always check the web server error log, not just the HTTP status.
SELinux blocks can look identical to file permission errors. If you see 'Permission denied' but file permissions seem correct, check /var/log/audit/audit.log or run ausearch -m avc.
Rule: use namei -l to check the entire path before anything else — 80% of permission bugs are a directory in the path lacking execute.
🎯 Key Takeaway
Don't guess — trace the actual path with namei.
Check SELinux if file permissions look right.
The process user is who matters, not the user running your debug commands.
Reading Permissions Like a Forensic Report: ls, stat, and namei
Before you fix a permissions bug, you have to read the evidence cold. The classic ls -l spits out the permission string left to right: 10 characters. The first char is the file type; the next nine are three triples for user, group, and other. -rwxr-xr-- means owner can do everything, group can read and execute, everyone else just reads. But ls only shows you the surface. When a file is buried three directories deep and one parent lacks execute permission, ls won't tell you that. Use namei -l /path/to/file to walk each component's permissions. It prints the owner, group, and mode for every directory in the path. That's how you catch a 'Permission denied' caused by a parent's sticky bit or a missing 'x' flag. For deeper forensics, stat dumps the raw bits, timestamps, and inode number. If the file's access time hasn't changed since deploy, you know the app never touched it. Stop guessing. Use these tools to build a timeline of exactly where access failed.
namei reveals /var/www/app is missing 'x' for group, causing 'Permission denied' even though the file itself is readable.
⚠ Production Trap:
A file with 644 permissions is useless if any parent directory lacks execute (x) for that user. Always trace the full path with namei.
🎯 Key Takeaway
When debugging permission errors, start with the file, then walk every ancestor directory. The problem is almost never the file itself.
Default Permissions: Why Your New Files Inherit the Wrong Bits
New files don't spring from the void with useful permissions. They inherit whatever the parent directory's default ACL or the process's umask gives them. And the umask is the silent saboteur. Umask is a three-digit octal mask that subtracts permissions from the default 666 for files or 777 for directories. A umask of 022 gives you 644 for files and 755 for directories. That sounds fine until your cron job runs with umask 077 and dumps a file that only the root user can read. The fix is explicit, not inherited. Set umask inside your scripts or service files. For directories where you need consistent group access, use a default ACL: setfacl -d -m g:webteam:rwx /shared/project. That default ACL overrides umask for new children and ensures every file or directory created inside /shared/project gives the webteam group read-write-execute. Do not rely on 'it works on my machine'. Set the umask in your Dockerfile, in your systemd unit, and in your entrypoint script. Control defaults or watch your deployment pipeline break at 2 AM.
deploy_harden.shBASH
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# io.thecodeforge - harden defaults for shared dirs
umask 0027 # Owner rwx, group rx, others nothing
mkdir -p /shared/project
chown :webteam /shared/project
chmod 2775 /shared/project # setgid: new files inherit group
setfacl -d -m g:webteam:rwx /shared/project
touch /shared/project/data.csv
ls -la /shared/project/data.csv
# Output: -rw-rw----+ 1 deploy webteam ...
Output
New file gets group read-write (660) and the '+' indicates an ACL is active. Group members can now read and write without chmod after every deploy.
⚠ Production Trap:
A webserver writing uploads with umask 077 will create files that only the www-data user can read. Your team's support scripts will fail silently.
🎯 Key Takeaway
Your production services should set umask explicitly. For shared directories, use a default ACL to guarantee new files inherit the correct group permissions.
● Production incidentPOST-MORTEMseverity: high
The Web Server That Couldn't Read Its Own Config
Symptom
Nginx returned 500 Internal Server Error for all requests. The application logs showed 'Permission denied' when trying to read /etc/nginx/sites-enabled/app.conf.
Assumption
“We use a shared deployment user — it must be able to read all config files.” The deployment script ran chown deploy:deploy on the entire /etc/nginx directory.
Root cause
The nginx master process runs as root, but the worker processes run as the 'www-data' user. After chown, /etc/nginx was owned by deploy:deploy with 750 permissions, meaning www-data had no read access. The worker couldn't open the config file.
Fix
Re-run chown -R root:root /etc/nginx and set permissions to 755. Then add the deploy user to the www-data group, and ensure config files have group-read (chmod 640 or 644).
Key lesson
Always check which system user actually reads files your service depends on.
Never chown entire directories without understanding the process ownership.
Document the required ownership and permissions for every component in your deployment playbook.
Production debug guideTrack down who owns what and which permissions block access4 entries
Symptom · 01
Application logs show 'Permission denied' when reading a file
→
Fix
Run ls -la on the file to check owner, group, and permissions. Use stat to see exact numeric permissions: stat -c '%a %n' filename
Symptom · 02
Web server returns 403 Forbidden on a directory
→
Fix
Check directory permissions — read (r) allows listing files, execute (x) allows entering the directory. Run namei -l /path/to/dir to trace permissions along the full path
Symptom · 03
A service fails silently after a permission change by a deployment script
→
Fix
Compare before and after permissions using a Git-based permission tracking tool like etckeeper, or use acl getfacl on the directory
Symptom · 04
sudo commands work interactively but fail in systemd or cron
→
Fix
Ensure the service user has direct access. Run su -s /bin/bash -c 'cat /path/to/file' serviceuser to simulate the service environment
★ Permission Debugging Quick ReferenceCommon permission errors and the exact commands to diagnose and fix them.
Cannot read file: Permission denied−
Immediate action
Check current user id and group membership
Commands
id; ls -la /path/to/file; stat -c '%a %n' /path/to/file
getfacl /path/to/file (if ACLs are enabled)
Fix now
chmod u+r /path/to/file (if you are the owner) or chown $(whoami) /path/to/file
ls -ld /path/with/multiple/dirs/to/file /path/with/multiple/dirs/to /path/with/multiple/dirs
Fix now
chmod +x /path/to/parent for each directory lacking execute
setuid binary runs as root, not as owner+
Immediate action
Check that the setuid bit is actually set
Commands
ls -l /usr/bin/somebinary | grep '^...s'
stat -c '%a' /usr/bin/somebinary (look for 4 in first digit, e.g., 4755)
Fix now
chmod u+s /usr/bin/somebinary (only if you own the file and have root)
Permission Modes at a Glance
Octal
Symbolic
Permission String
Typical Use Case
755
rwxr-xr-x
-rwxr-xr-x (dir: drwxr-xr-x)
Executables, public directories
644
rw-r--r--
-rw-r--r--
Static files, configs (read-only for group/other)
600
rw-------
-rw-------
Sensitive files (SSH keys, passwords)
700
rwx------
-rwx------
Private scripts, user home directories
2775
rwxrwxr-x (setgid)
drwxrwsr-x
Shared team directories (setgid)
4755
rwxr-xr-x (setuid)
-rwsr-xr-x
Privileged binaries (passwd, ping)
1777
rwxrwxrwt
drwxrwxrwt
World-writable sticky (like /tmp)
⚙ Quick Reference
8 commands from this guide
File
Command / Code
Purpose
check-permissions.sh
ls -la /var/log/auth.log
What Are Linux File Permissions?
chmod-examples.sh
chmod u+x deploy.sh
Changing Permissions with chmod (Symbolic and Octal)
chown-examples.sh
chown alice report.txt
Changing Ownership with chown and chgrp
special-modes.sh
ls -l /usr/bin/passwd
Special Modes
production-pattern.sh
mkdir -p /var/www/app
Real-World Patterns for Team Access
debug-permissions.sh
SERVICE=$(systemctl show -p MainPID nginx.service | cut -d= -f2)
Debugging Permission Errors in Practice
forensics.sh
$ ls -l /var/www/app/config/database.yml
Reading Permissions Like a Forensic Report
deploy_harden.sh
umask 0027 # Owner rwx, group rx, others nothing
Default Permissions
Key takeaways
1
Linux permissions consist of three triples (owner/group/other) for read, write, execute.
2
Use octal chmod in automation for idempotent results; symbolic for interactive work.
3
Only root can chown a file; non-root users can chgrp to groups they belong to.
4
setuid elevates privileges (use sparingly); setgid on directories enforces group inheritance; sticky bit protects files in shared writable directories.
5
Always debug permission errors by tracing the full path with namei and checking SELinux/AppArmor if file permissions appear correct.
6
Never use 777 in production—opt for 755/644 and group-based access patterns.
INTERVIEW PREP · PRACTICE MODE
Interview Questions on This Topic
Q01SENIOR
What does the permission string '-rwsr-xr--' mean? Who can execute the f...
Q02SENIOR
Explain the difference between chmod 755 and chmod 755 + setgid (chmod 2...
Q03SENIOR
A web server returns 403 Forbidden for a specific file. The file shows 6...
Q04SENIOR
What is the sticky bit and where is it commonly used?
Q05SENIOR
How would you set up a shared directory where a team of developers can a...
Q01 of 05SENIOR
What does the permission string '-rwsr-xr--' mean? Who can execute the file and with what privileges?
ANSWER
The first character '-' indicates a regular file. Owner (rwx + setuid 's') has read, write, execute, and the setuid bit set – meaning the file runs with the owner's privileges. Group (r-x) has read and execute. Others (r--) have only read. The setuid bit means the file will execute as the owner (likely root), not as the calling user. Typical example: /usr/bin/passwd.
Q02 of 05SENIOR
Explain the difference between chmod 755 and chmod 755 + setgid (chmod 2755) on a directory. When would you use the latter?
ANSWER
chmod 755 sets rwxr-xr-x – owner full, group and other read+execute. Adding setgid (2755) changes the group executed permission to include 's' instead of 'x' (rwxr-sr-x). On a directory, setgid means new files created inside inherit the directory's group, not the creator's primary group. Use 2755 on shared team directories so all team members can access each other's files regardless of their primary group.
Q03 of 05SENIOR
A web server returns 403 Forbidden for a specific file. The file shows 644 permissions and the web server user is in the correct group. What else could be wrong?
ANSWER
Three common possibilities: (1) One of the parent directories lacks execute permission – use namei -l to check the full path. (2) SELinux or AppArmor is blocking access – check audit logs with ausearch. (3) The file might be on a filesystem mounted with 'noexec' or 'nosuid' options – check mount options. Also verify the web server didn't have a configuration reload fail silently, blocking access to that specific location.
Q04 of 05SENIOR
What is the sticky bit and where is it commonly used?
ANSWER
The sticky bit (octal 1000, symbol 't') prevents users from deleting or renaming files they don't own, even if they have write permission on the directory. It's most commonly found on /tmp (drwxrwxrwt). Without the sticky bit, any user with write access to /tmp could delete files created by others – a major security risk. The sticky bit ensures only file owners (or root) can delete their files.
Q05 of 05SENIOR
How would you set up a shared directory where a team of developers can all edit files, and new files automatically get group-writable?
ANSWER
Create a group (e.g., 'devteam'), add all developers to it. Create the shared directory. Set ownership to root:devteam. Set permissions to 2775 (setgid + rwx for owner and group, rx for others). The setgid bit ensures new files inherit the 'devteam' group. To ensure new files are group-writable, set the default ACL: setfacl -d -m g:devteam:rwx /shared. Alternatively, each user's umask should be 002, but setgid + ACL is more reliable.
01
What does the permission string '-rwsr-xr--' mean? Who can execute the file and with what privileges?
SENIOR
02
Explain the difference between chmod 755 and chmod 755 + setgid (chmod 2755) on a directory. When would you use the latter?
SENIOR
03
A web server returns 403 Forbidden for a specific file. The file shows 644 permissions and the web server user is in the correct group. What else could be wrong?
SENIOR
04
What is the sticky bit and where is it commonly used?
SENIOR
05
How would you set up a shared directory where a team of developers can all edit files, and new files automatically get group-writable?
SENIOR
FAQ · 5 QUESTIONS
Frequently Asked Questions
01
What does chmod 755 mean?
It sets permissions to rwxr-xr-x: owner can read, write, execute; group can read and execute; others can read and execute. Commonly used for executables and directories.
Was this helpful?
02
How do I make a file executable?
Use 'chmod +x filename' (symbolic) or 'chmod 755 filename' (octal). For shell scripts, ensure the first line is #!/bin/bash (or appropriate interpreter).
Was this helpful?
03
What is the difference between chown and chgrp?
chown changes the owner and optionally the group (chown newowner:newgroup file). chgrp changes only the group. chown :newgroup is equivalent to chgrp newgroup.
Was this helpful?
04
Why does my web server return 403 even though the file has 644 permissions?
Most likely a parent directory lacks execute permission. Use 'namei -l /path/to/file' to check each component. Also check if SELinux or AppArmor is blocking access.
Was this helpful?
05
Can I set the setuid bit on a Python script?
No. Linux kernel ignores the setuid bit on scripts with a shebang line (#!). Use a compiled binary or use sudoers to allow specific commands to run as root.