Introduction
File permissions are the cornerstone of Linux security. Every file and directory has permissions that control who can read, write, or execute them. Understanding and properly configuring these permissions is essential for system security and proper access control.
In this comprehensive guide, you'll learn:
- How to read and understand Linux permission notation (rwx)
- Changing permissions with
chmod
using both symbolic and numeric modes - Managing file ownership with
chown
andchgrp
- Understanding special permissions: SUID, SGID, and sticky bit
- Working with SELinux security contexts
- Security best practices and troubleshooting tips
Prerequisites: Basic familiarity with the Linux command line. You'll need sudo privileges for ownership changes and some permission modifications.
Understanding File Permissions Basics
Every file and directory in Linux has three types of permissions for three categories of users:
Permission Types (rwx)
Symbol | Permission | For Files | For Directories |
---|---|---|---|
r | Read | View file contents | List directory contents |
w | Write | Modify file contents | Create/delete files in directory |
x | Execute | Run file as program/script | Enter directory (cd into it) |
- | No permission | Cannot perform action | Cannot perform action |
User Categories
Symbol | Category | Description |
---|---|---|
u | User (Owner) | The file owner |
g | Group | Users in the file's group |
o | Others | Everyone else |
a | All | User + Group + Others (u+g+o) |
Reading Permission Strings
Let's create some test files and examine their permissions:
touch file1.txt
mkdir dir1
ls -l
Output:
total 0
drwxr-xr-x. 2 centos9 centos9 6 Oct 6 18:35 dir1
-rw-r--r--. 1 centos9 centos9 0 Oct 6 18:35 file1.txt
Decoding the Permission String
Let's analyze the permission string for file1.txt
: -rw-r--r--
Position | Characters | Meaning |
---|---|---|
1 | - | File type (- = regular file, d = directory, l = symlink) |
2-4 | rw- | Owner permissions: read + write (no execute) |
5-7 | r-- | Group permissions: read only |
8-10 | r-- | Others permissions: read only |
Complete Line Breakdown:
-rw-r--r--
: Permission string1
: Number of hard linkscentos9
: Owner usernamecentos9
: Group name0
: File size in bytesOct 6 18:35
: Last modification timefile1.txt
: Filename
For the directory dir1
: drwxr-xr-x
d
: It's a directoryrwx
: Owner can read, write (add/delete files), and execute (enter directory)r-x
: Group can read and execute (list and enter), but not writer-x
: Others can read and execute, but not write
The dot (.
) at the end of permissions indicates SELinux security context is applied to the file.
Changing Permissions with chmod (Symbolic Mode)
The chmod
command changes file permissions. Symbolic mode uses letters to represent permissions.
Adding Execute Permission to Owner
chmod u+x file1.txt
ls -l
Output:
-rwxr--r--. 1 centos9 centos9 0 Oct 6 18:35 file1.txt
Command Breakdown:
chmod
: Change mode (permissions) commandu+x
: Add (+) execute (x) permission to user/owner (u)file1.txt
: Target file
What Changed:
- Owner permissions changed from
rw-
torwx
- The file can now be executed as a program/script by the owner
Removing Group Read Permission
chmod g-r file1.txt
ls -l
Output:
-rwx---r--. 1 centos9 centos9 0 Oct 6 18:35 file1.txt
Command Breakdown:
g-r
: Remove (-) read (r) permission from group (g)
Result:
- Group permissions changed from
r--
to---
- Group members can no longer read the file
Setting Exact Permissions with =
chmod u=rwx,g=rx,o= file1.txt
ls -l
Output:
-rwxr-x---. 1 centos9 centos9 0 Oct 6 18:35 file1.txt
Command Breakdown:
u=rwx
: Set owner to read, write, execute (exact, replaces existing)g=rx
: Set group to read and execute (no write)o=
: Set others to nothing (no permissions)- Comma-separated for multiple changes in one command
Result:
- Owner:
rwx
(full access) - Group:
r-x
(read and execute) - Others:
---
(no access)
Symbolic Operators:
+
: Add permission-
: Remove permission=
: Set exact permission (replaces all existing)
Changing Permissions with chmod (Numeric Mode)
Numeric (octal) mode uses numbers to represent permissions. Each permission type has a value:
Permission | Value | Binary |
---|---|---|
Read (r) | 4 | 100 |
Write (w) | 2 | 010 |
Execute (x) | 1 | 001 |
No permission (-) | 0 | 000 |
How to Calculate:
- Add values for desired permissions
rwx
= 4 + 2 + 1 = 7rw-
= 4 + 2 + 0 = 6r-x
= 4 + 0 + 1 = 5r--
= 4 + 0 + 0 = 4
Setting Permissions to 755
chmod 755 file1.txt
ls -l
Output:
-rwxr-xr-x. 1 centos9 centos9 0 Oct 6 18:35 file1.txt
Permission Breakdown:
Position | Number | Calculation | Result | Category |
---|---|---|---|---|
1st digit | 7 | 4 + 2 + 1 | rwx | Owner |
2nd digit | 5 | 4 + 0 + 1 | r-x | Group |
3rd digit | 5 | 4 + 0 + 1 | r-x | Others |
Use Case: 755
is common for executables and directories - owner has full control, others can read and execute.
Setting Permissions to 600
chmod 600 file1.txt
ls -l
Output:
-rw-------. 1 centos9 centos9 0 Oct 6 18:35 file1.txt
Permission Breakdown:
6
(owner): 4 + 2 =rw-
(read + write)0
(group):---
(no permissions)0
(others):---
(no permissions)
Use Case: 600
is ideal for private files like SSH keys, config files with passwords - only owner can access.
Common Numeric Permission Values
Value | Symbolic | Meaning | Common Use |
---|---|---|---|
755 | rwxr-xr-x | Owner: RWX, Group/Others: RX | Executables, directories |
644 | rw-r--r-- | Owner: RW, Group/Others: R | Regular files, documents |
700 | rwx------ | Owner: RWX, Group/Others: nothing | Private executables |
600 | rw------- | Owner: RW, Group/Others: nothing | SSH keys, sensitive config |
777 | rwxrwxrwx | Everyone: RWX | ā ļø Insecure! Avoid in production |
666 | rw-rw-rw- | Everyone: RW | ā ļø Insecure! Avoid in production |
Changing File Ownership with chown
The chown
command changes file ownership. Only root or users with sudo can change ownership.
Changing File Owner
sudo chown root file1.txt
ls -l file1.txt
Output:
-rw-------. 1 root centos9 0 Oct 6 18:35 file1.txt
Command Breakdown:
sudo
: Execute with superuser privileges (required for ownership changes)chown
: Change owner commandroot
: New owner usernamefile1.txt
: Target file
What Changed:
- Owner changed from
centos9
toroot
- Group remains
centos9
- Now only root can read/write this file (permissions are 600)
Changing Owner and Group Simultaneously
You can change both owner and group in one command:
sudo chown user:users file1.txt
Syntax: chown owner:group filename
user
: New ownerusers
: New group (separated by colon)
Recursive Changes: Use chown -R
to change ownership of directories and all their contents recursively. Example: sudo chown -R user:group /path/to/directory
Changing Group Ownership with chgrp
The chgrp
command changes only the group ownership:
sudo chgrp wheel file1.txt
ls -l
Output:
-rw-------. 1 root wheel 0 Oct 6 18:35 file1.txt
Command Breakdown:
chgrp
: Change group commandwheel
: New group name (common admin group on RHEL/CentOS)file1.txt
: Target file
Result:
- Group changed from
centos9
towheel
- Owner remains
root
- Members of the
wheel
group now have group-level access (currently none due to 600 permissions)
Special Permissions: SUID, SGID, and Sticky Bit
Beyond standard rwx permissions, Linux has three special permission bits with powerful security implications.
SUID (Set User ID) - Executes as Owner
SUID allows a user to execute a file with the permissions of the file's owner.
Real-World Example: passwd Command
which passwd
ls -l /usr/bin/passwd
Output:
/usr/bin/passwd
-rwsr-xr-x. 1 root root 32648 Aug 10 2021 /usr/bin/passwd
Notice the 's' in owner execute position: -rwsr-xr-x
Why This Matters:
- The
passwd
command must modify/etc/shadow
(owned by root, 000 permissions) - Regular users can't normally write to
/etc/shadow
- The SUID bit (
s
) allowspasswd
to run with root privileges - When user runs
passwd
, it temporarily executes as root to modify the password file
Setting SUID:
chmod u+s filename # Symbolic
chmod 4755 filename # Numeric (4 prefix enables SUID)
Security Warning: SUID files running as root are potential security risks. An exploited SUID root binary can grant attackers root access. Only use SUID when absolutely necessary and audit regularly.
SGID (Set Group ID) - For Group Collaboration
SGID has different behaviors for files vs. directories:
For Directories (Most Common Use):
mkdir shared_dir
sudo chmod g+s shared_dir
ls -l
Output:
drwxr-sr-x. 2 centos9 centos9 6 Oct 6 18:40 shared_dir
Notice the 's' in group execute position: drwxr-sr-x
What SGID Does for Directories:
- Any file created inside
shared_dir
inherits the directory's group - Without SGID: files get the creator's primary group
- With SGID: files get
centos9
group (the directory's group) - Perfect for team collaboration directories
Setting SGID:
chmod g+s directory # Symbolic
chmod 2755 directory # Numeric (2 prefix enables SGID)
For Files:
- File executes with the group permissions of the file's group
- Less common than directory SGID
- Used for specific multi-user application scenarios
Sticky Bit - Prevent Deletion by Others
The sticky bit is primarily used on directories to restrict deletion.
Common Example: /tmp Directory
sudo chmod +t /tmp
ls -ld /tmp
Output:
drwxrwxrwt. 44 root root 8192 Oct 6 18:40 /tmp
Notice the 't' in others execute position: drwxrwxrwt
What Sticky Bit Does:
- On
/tmp
: Everyone can create files (world-writable) - BUT: Users can only delete their own files
- Without sticky bit: Any user could delete anyone's files in a world-writable directory
- With sticky bit: Only file owner, directory owner, or root can delete files
Setting Sticky Bit:
chmod +t directory # Symbolic
chmod 1777 directory # Numeric (1 prefix enables sticky bit)
Use Case: Shared directories where multiple users create files but shouldn't be able to delete each other's files.
Special Permissions Numeric Reference
Special Bit | Numeric Value | Symbol | Position | Example |
---|---|---|---|---|
SUID | 4 | s | Owner execute | 4755 = rwsr-xr-x |
SGID | 2 | s | Group execute | 2755 = rwxr-sr-x |
Sticky Bit | 1 | t | Others execute | 1777 = rwxrwxrwt |
Capital Letter Meaning: If you see capital S
or T
, it means the special bit is set but execute permission is not. Example: rwSr--r--
means SUID is set but owner can't execute (usually a mistake).
Understanding SELinux Security Contexts
SELinux (Security-Enhanced Linux) provides Mandatory Access Control (MAC), adding another layer beyond traditional permissions.
Viewing SELinux Context
ls -Z file1.txt
Output:
unconfined_u:object_r:user_home_t:s0 file1.txt
SELinux Context Fields:
Field | Value | Description |
---|---|---|
User | unconfined_u | SELinux user (unconfined = less restricted) |
Role | object_r | SELinux role (object_r for files) |
Type | user_home_t | Most important: file type context (user home file) |
Level | s0 | MLS/MCS level (sensitivity level) |
Installing SELinux Management Tools
sudo dnf install policycoreutils-python-utils
Output:
Last metadata expiration check: 2:12:11 ago on Mon 06 Oct 2025 04:31:31 PM PKT.
Package policycoreutils-python-utils-3.6-3.el9.noarch is already installed.
Dependencies resolved.
Nothing to do.
Complete!
This package provides semanage
, restorecon
, and other SELinux management utilities.
Changing SELinux Context
sudo chcon -t httpd_sys_content_t file1.txt
Command Breakdown:
chcon
: Change context command-t
: Specify type fieldhttpd_sys_content_t
: Apache web server content type- This would allow Apache to serve this file (if permissions also allow)
Restoring Default SELinux Context
sudo restorecon -v file1.txt
Output:
Relabeled /home/centos9/Razzaq-Labs-II/random/random/permissions/file1.txt from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:user_home_t:s0
Command Breakdown:
restorecon
: Restore context to default policy-v
: Verbose (show what changed)
What Happened:
- Context type changed from
httpd_sys_content_t
back touser_home_t
- Based on file location (
/home/centos9
), SELinux knows it should beuser_home_t
- This fixes incorrect contexts that might prevent access
When SELinux Blocks Access: If permissions look correct but access is denied, check SELinux. Use restorecon -Rv /path
to fix contexts or ausearch -m avc -ts recent
to view denial logs.
Troubleshooting Permission Issues
Permission Denied Errors
When you see "Permission denied":
-
Check current permissions:
ls -l filename
- Verify you have required permission (r for read, w for write, x for execute)
- Check if you're owner, in group, or other
-
Verify your user identity:
whoami id
- Confirm your username and group memberships
-
Check SELinux context if permissions seem correct:
ls -Z filename getenforce # Check if SELinux is enforcing
- Even with correct permissions, wrong SELinux context blocks access
- Check
/var/log/audit/audit.log
for SELinux denials
Ownership Changes Not Working
If chown
or chgrp
fails:
-
Ensure you have root/sudo:
- Only root can change file ownership
- Use
sudo chown
orsudo chgrp
-
Verify user/group exists:
getent passwd username getent group groupname
- User/group must exist in the system
- Check
/etc/passwd
and/etc/group
Special Bits Not Showing
Understanding special bit display:
Permission | With Execute | Without Execute |
---|---|---|
SUID (owner) | s (lowercase) | S (uppercase) |
SGID (group) | s (lowercase) | S (uppercase) |
Sticky (others) | t (lowercase) | T (uppercase) |
Example:
rwsr-xr-x
: SUID set, owner has execute (correct)rwSr-xr-x
: SUID set, owner has no execute (usually a mistake)
Best Practices for File Permissions
Security Best Practices
-
Follow Principle of Least Privilege
- Grant minimum permissions necessary
- Avoid
777
(world-writable) and666
permissions - Use
750
or640
instead of755
/644
for sensitive files
-
Protect Sensitive Files
- SSH keys:
600
(~/.ssh/id_rsa
) - SSH config:
644
(~/.ssh/config
) - Password files:
600
(configuration files with credentials) - Home directories:
700
or750
- SSH keys:
-
Audit SUID/SGID Files Regularly
find / -perm -4000 -type f 2>/dev/null # Find SUID files find / -perm -2000 -type f 2>/dev/null # Find SGID files
- Review list for unauthorized SUID/SGID binaries
- Potential security risk if exploited
-
Use Groups for Shared Access
- Create dedicated groups for projects/teams
- Use SGID on shared directories
- Avoid making files world-readable/writable
-
Set Proper Umask
- Default umask
022
: files created as644
, directories as755
- Restrictive umask
027
: files as640
, directories as750
- Set in
~/.bashrc
or system-wide/etc/profile
- Default umask
Operational Best Practices
-
Document Permission Decisions
- Record why specific permissions were set
- Document SUID/SGID requirements
- Maintain permission standards for your organization
-
Use Symbolic Mode for Clarity
chmod u+x script.sh
is clearer thanchmod 755
- Easier to understand intent
- Less prone to typos
-
Recursive Changes with Caution
chmod -R 755 /path
affects everything underneath- Can break things if applied incorrectly
- Use
find
for selective changes:find /path -type f -exec chmod 644 {} \; # Files only find /path -type d -exec chmod 755 {} \; # Directories only
-
Test Permission Changes
- Test on non-production first
- Verify application still works after changes
- Have rollback plan ready
-
Regular Permission Audits
- Review file permissions periodically
- Check for world-writable files:
find / -perm -002 -type f
- Monitor changes to critical system files
Common Permission Patterns
Use Case | Permission | Symbolic | Example |
---|---|---|---|
Public web content | 644 | rw-r--r-- | HTML, images |
Executable scripts | 755 | rwxr-xr-x | Shell scripts, binaries |
Private config files | 600 | rw------- | SSH keys, passwords |
Private directories | 700 | rwx------ | ~/.ssh directory |
Shared project dir | 2775 | rwxrwsr-x | Team collaboration |
Temporary shared | 1777 | rwxrwxrwt | /tmp, /var/tmp |
Command Cheat Sheet
Permission Commands
Command | Purpose | Example |
---|---|---|
chmod | Change file permissions | chmod 755 file.sh |
chown | Change file owner | sudo chown user:group file |
chgrp | Change file group | sudo chgrp developers file |
ls -l | List files with permissions | ls -l /path |
ls -ld | Show directory permissions (not contents) | ls -ld /tmp |
umask | View/set default permission mask | umask 022 |
getfacl | Get ACL (extended permissions) | getfacl file |
setfacl | Set ACL (extended permissions) | setfacl -m u:user:rwx file |
chmod Symbolic Mode
Command | Meaning | Result |
---|---|---|
chmod u+x file | Add execute for owner | Owner can execute |
chmod g-w file | Remove write from group | Group can't modify |
chmod o=r file | Set others to read only | Others: read only |
chmod a+x file | Add execute for all | Everyone can execute |
chmod u=rwx,go=rx file | Owner rwx, group/others rx | Same as 755 |
chmod Numeric Values Quick Reference
Octal | Binary | Symbolic | 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 |
SELinux Commands
Command | Purpose | Example |
---|---|---|
ls -Z | View SELinux context | ls -Z file |
chcon | Change SELinux context | sudo chcon -t httpd_sys_content_t file |
restorecon | Restore default context | sudo restorecon -Rv /path |
getenforce | Check SELinux mode | getenforce |
setenforce | Set SELinux mode | sudo setenforce 0 (permissive) |
ausearch | Search SELinux audit logs | ausearch -m avc -ts recent |
semanage | Manage SELinux policy | sudo semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?" |
Finding Files by Permission
Command | Purpose |
---|---|
find / -perm -4000 -type f | Find all SUID files |
find / -perm -2000 -type f | Find all SGID files |
find / -perm -002 -type f | Find world-writable files |
find / -perm -002 -type d | Find world-writable directories |
find /home -perm 777 | Find files with exactly 777 permissions |
Summary
In this comprehensive guide, you've mastered Linux file permissions and ownership:
ā
Understanding permission notation (rwx) for users, groups, and others
ā
Reading and interpreting ls -l
output with file types and permissions
ā
Changing permissions with chmod
using both symbolic and numeric modes
ā
Managing ownership with chown
for users and chgrp
for groups
ā
Understanding special permissions: SUID, SGID, and sticky bit
ā
Working with SELinux security contexts and troubleshooting access issues
ā
Implementing security best practices for file protection
ā
Troubleshooting common permission-related problems
File permissions are fundamental to Linux security. Proper configuration protects sensitive data, prevents unauthorized access, and ensures system integrity. Always follow the principle of least privilege and regularly audit your permissions.
What's Next?
Expand your Linux security knowledge with these related topics:
- Access Control Lists (ACLs): Fine-grained permissions beyond owner/group/other
- File Attributes: Immutable and append-only files with
chattr
andlsattr
- Audit System: Track file access and modifications with
auditd
- Mandatory Access Control: Deep dive into SELinux policies and contexts
- Filesystem Security: Encrypted filesystems, secure mounting options
Master file permissions to build secure and well-managed Linux systems!