File Permission
Problems

Diagnose and correct file permission problems

CIS126RH | RHEL System Administration 1
Mesa Community College

Permission denied errors are among the most common problems an administrator encounters. Understanding how Linux evaluates permission — checking ownership, group membership, and the nine permission bits in sequence — allows precise diagnosis. Knowing chmod, chown, chgrp, special bits, and the umask allows precise correction. This module covers the complete permission model and diagnostic workflow. These skills appear throughout the RHCSA exam.

Learning Objectives

  1. Read and interpret permission output from ls -l — Decode the permission string, owner, group, and file type from the long listing format
  2. Understand how Linux evaluates permissions — Explain the owner → group → other evaluation order and why it matters for diagnosis
  3. Change permissions with chmod — Use both symbolic (u+x) and octal (755) notation to set file and directory permissions
  4. Change ownership and apply special bits — Use chown and chgrp to change ownership, and apply setuid, setgid, and sticky bit as needed

Reading ls -l Output

The long listing format shows every piece of information needed to diagnose a permission problem.

$ ls -l /var/www/html/
total 16
drwxr-xr-x. 2 root  root  4096 May 25 10:00 images
-rw-r--r--. 1 root  root   512 May 25 10:00 index.html
-rwxr-x---. 1 apache www    89 May 25 10:00 cgi-bin/app.sh
-rw-rw-r--. 1 alice  dev  1024 May 25 10:00 draft.html

# Anatomy of one line:
-  rw-  r--  r--.  1  root  root  512  May 25 10:00  index.html
# ^  ^    ^    ^   ^   ^     ^
# |  |    |    |   |   |     group
# |  |    |    |   |   owner
# |  |    |    |   hard link count
# |  |    |    other permissions
# |  |    group permissions
# |  owner permissions
# file type: - file, d directory, l symlink, b block, c char
The dot after permissions is an SELinux indicator

The . after the permission string means the file has an SELinux security context. A + means ACLs are set. Neither affects standard permission evaluation — but they are important for SELinux and ACL diagnostics.

How Linux Evaluates Permissions

Linux checks permissions in a strict sequence. The first match applies — no further checks are made.

  1. Is the user the file owner?
    If yes → apply owner permissions (first three bits) — done
  2. Is the user a member of the file's group?
    If yes → apply group permissions (middle three bits) — done
  3. Otherwise → apply other permissions (last three bits)
root bypasses all permission checks

The root user is never denied access by standard file permissions. root can read, write, and execute any file regardless of the permission bits. SELinux is the layer that restricts root — standard permissions do not.

Owner evaluated first — even if group has more access

If a file is ----rwxrwx and owned by alice, and alice tries to access it — she is denied! Linux sees she is the owner, applies the owner bits (---), and stops. It never looks at the group or other bits for alice.

Permission Bits: Files vs Directories

The same three bits — read, write, execute — mean different things depending on whether they are applied to a file or a directory.

Bit On a regular file On a directory
r (read, 4) Read the file contents (cat, less) List the directory contents (ls)
w (write, 2) Modify or truncate the file Create, delete, or rename files within the directory
x (execute, 1) Run the file as a program Enter the directory (cd) and access files within it
Execute on a directory is required to access its contents

A directory with r but not x allows listing filenames but not accessing them. A directory with x but not r allows accessing files by name but not listing them. Both rx together are needed for normal directory access.

chmod: Symbolic Notation

Symbolic notation is readable and precise for making targeted changes to specific permission bits without affecting others.

# Syntax: chmod [ugoa][+/-/=][rwxst] FILE

# Add execute for the file owner
$ chmod u+x script.sh

# Remove write from group and other
$ chmod go-w config.conf

# Set group to read-only (replace, not add)
$ chmod g=r report.txt

# Add read and execute for all (u, g, o)
$ chmod a+rx /opt/shared/

# Remove execute from owner only
$ chmod u-x norun.sh

# Multiple changes in one command
$ chmod u+x,g-w,o=r file.txt

# Apply recursively to a directory tree
$ sudo chmod -R g+rX /var/www/html/
# Capital X = execute only if already executable or a directory

chmod: Octal Notation

Octal notation sets all nine permission bits at once with a three-digit number. Each digit is the sum of the active bits for that category.

# Bit values: r=4, w=2, x=1
# Digit = sum of active bits for owner | group | other

# 755 = rwxr-xr-x  (owner: 4+2+1=7, group: 4+0+1=5, other: 4+0+1=5)
$ chmod 755 script.sh

# 644 = rw-r--r--  (owner: 4+2=6, group: 4, other: 4)
$ chmod 644 index.html

# 600 = rw-------  (owner: 6, group: 0, other: 0)
$ chmod 600 ~/.ssh/id_rsa

# 700 = rwx------  (owner has all, nobody else)
$ chmod 700 ~/.ssh/

# 664 = rw-rw-r--  (owner and group can write)
$ chmod 664 shared.txt

# 000 = ---------  (no permissions for anyone)
$ chmod 000 locked.txt
Octal Symbolic Common use
755rwxr-xr-xExecutable files, directories
644rw-r--r--Regular files (web content, configs)
600rw-------Private key files, sensitive configs
700rwx------Private directories (~/.ssh)
664rw-rw-r--Group-editable shared files
640rw-r-----Config files readable by group only

Changing Ownership: chown and chgrp

Ownership determines which set of permission bits applies to a user. Only root can change file ownership.

# Change owner only
$ sudo chown alice report.txt

# Change owner and group simultaneously
$ sudo chown alice:developers report.txt

# Change group only (using chown with colon notation)
$ sudo chown :developers report.txt

# Change group only (using chgrp)
$ sudo chgrp developers report.txt

# Change ownership recursively
$ sudo chown -R apache:apache /var/www/html/

# Verify ownership change
$ ls -l report.txt
-rw-r--r--. 1 alice developers 1024 May 25 10:00 report.txt
chown syntax: user:group or user.group

Both colon and dot separate user from group in chown: chown alice:developers and chown alice.developers are equivalent. Colon is the modern preferred form.

Special Permission Bits

Three additional bits extend the permission system beyond basic read/write/execute.

Bit Octal On executable files On directories
setuid (SUID) 4000 Process runs as the file's owner, not the caller (passwd, sudo) No standard effect on Linux
setgid (SGID) 2000 Process runs with the file's group, not the caller's group New files inherit the directory's group, not the creator's primary group
Sticky bit 1000 Historically prevented swapping — no modern effect on files Only the file owner, directory owner, or root can delete files in the directory (/tmp)
# Set setuid on a file (shown as 's' in owner execute position)
$ sudo chmod 4755 /usr/bin/myapp   # or: chmod u+s

# Set setgid on a directory (shown as 's' in group execute position)
$ sudo chmod 2775 /opt/shared/    # or: chmod g+s

# Set sticky bit on a directory (shown as 't' in other execute position)
$ sudo chmod 1777 /tmp/public/    # or: chmod +t

The umask: Default Permission Mask

The umask defines which permissions are removed from newly created files and directories. It subtracts permissions from the maximum possible.

# View the current umask
$ umask
0022

# How umask works:
# Max permissions: file=666 (rw-rw-rw-)  directory=777 (rwxrwxrwx)
# umask 022:       remove --w--w- from files, --w--w- from directories
# Result:          file=644 (rw-r--r--)  directory=755 (rwxr-xr-x)

# Set umask for the current shell session
$ umask 027    # files=640, directories=750
$ umask 002    # files=664, directories=775 (group-write allowed)

# Set umask persistently in user's shell config
$ echo "umask 027" >> ~/.bashrc

# Set system-wide default umask
$ sudo vim /etc/profile.d/umask.sh
umask 022
umask 0022 is the RHEL 9 default

New files are created with 644 (666 - 022). New directories are created with 755 (777 - 022). The leading zero is the special bits mask — normally zero.

Diagnosing Permission Problems

A "Permission denied" error is caused by one of a small number of root causes. A systematic check identifies which one applies.

  1. Identify the acting user and what they are trying to do
    id — show current user, UID, and group memberships
  2. Check the file's permissions and ownership
    ls -l FILE — read type, permission string, owner, group
  3. Check all parent directories for execute permission
    ls -ld /path /path/to /path/to/file
  4. Apply the evaluation model
    Is the user the owner? Is the user in the file's group? What do the applicable bits allow?
  5. Check SELinux if standard permissions look correct
    ls -Z FILE and ausearch -m avc -ts recent

Common Permission Problem Patterns

Symptom Likely cause Diagnostic command Fix
User cannot read a file they should access Wrong group, or other has no read ls -l FILE, id USER chmod o+r FILE or add user to group
User cannot enter a directory Directory missing execute bit ls -ld DIR chmod u+x DIR or chmod 755 DIR
Web server cannot serve files Files not readable by apache/nginx ls -la /var/www/html/, id apache chmod -R 644 files; chmod -R 755 dirs
Script runs but produces "Permission denied" Script lacks execute bit ls -l script.sh chmod +x script.sh
User can list files but cannot open them Directory has r but not x ls -ld DIR chmod +x DIR
Shared directory: new files not accessible to group setgid not set on directory ls -ld DIR (no s in group pos) chmod g+s DIR

Practical Diagnosis Example

The apache web server cannot serve /var/www/html/index.html. Diagnose and fix the problem step by step.

# Step 1: Check what user apache runs as
$ id apache
uid=48(apache) gid=48(apache) groups=48(apache)

# Step 2: Check file permissions
$ ls -l /var/www/html/index.html
-rw-------. 1 root root 512 May 25 10:00 index.html
#  ^^^ only root can read — apache cannot

# Step 3: Check parent directory permissions
$ ls -ld /var/www/html/
drwxr-xr-x. 2 root root 4096 May 25 10:00 /var/www/html/
#  ^^^^^^^ apache can enter (has r-x as "other") — dir OK

# Diagnosis: file is 600 — only owner (root) can read it
# apache is "other" — gets --- from the 600 permission

# Fix: make file world-readable
$ sudo chmod 644 /var/www/html/index.html

# Verify
$ ls -l /var/www/html/index.html
-rw-r--r--. 1 root root 512 May 25 10:00 index.html
#  ^^^^^^^ apache (other) now has r-- — can read

Setting Up a Collaborative Directory

A common exam task: create a directory where all members of a group can read and write files, and new files inherit the group automatically.

# Scenario: /opt/team should be readable/writable by the 'devs' group

# Step 1: Create the group and add users
$ sudo groupadd devs
$ sudo usermod -aG devs alice
$ sudo usermod -aG devs bob

# Step 2: Create directory with group ownership
$ sudo mkdir /opt/team
$ sudo chown root:devs /opt/team

# Step 3: Set permissions — rwxrwsr-x (setgid = 2775)
$ sudo chmod 2775 /opt/team

# Verify
$ ls -ld /opt/team
drwxrwsr-x. 2 root devs 4096 May 25 10:00 /opt/team
#     ^ s in group execute = setgid is set

# Test: alice creates a file — it gets group 'devs' automatically
$ su - alice -c "touch /opt/team/myfile.txt"
$ ls -l /opt/team/myfile.txt
-rw-rw-r--. 1 alice devs 0 May 25 10:00 myfile.txt
#                   ^^^^ group is devs, not alice's primary group

Permission Management Quick Reference

Task Command
View permissions (long format)ls -l FILE
View directory permissionsls -ld DIR
View current user and groupsid
Set permissions (octal)chmod 644 FILE
Add execute for ownerchmod u+x FILE
Remove write from group and otherchmod go-w FILE
Recursive permission changechmod -R 755 DIR
Change file ownersudo chown USER FILE
Change owner and groupsudo chown USER:GROUP FILE
Change group onlysudo chgrp GROUP FILE
Set setuidchmod u+s FILE or chmod 4755 FILE
Set setgid on directorychmod g+s DIR or chmod 2775 DIR
Set sticky bit on directorychmod +t DIR or chmod 1777 DIR
View and change umaskumask / umask 027

Common Mistakes

Mistake What goes wrong Correct approach
Forgetting to check parent directory permissions File permissions look correct but access is still denied Use ls -ld /path /path/to /path/to/file to check entire path
Using chmod -R 777 to fix a permission problem Secures the symptom but creates a severe security risk Diagnose the actual cause and apply the minimum required permissions
Confusing owner-check-first with "most permissive wins" File owner cannot access a file that group members can (e.g. ----rwxrwx) Remember: owner bits are checked first and only — group/other are never checked for the owner
Not using setgid on a shared directory New files get the creator's primary group — other group members cannot access them Apply chmod g+s DIR to make new files inherit the directory's group
Setting execute on a regular data file Security risk — file could potentially be executed; also confusing in listings Execute is for programs and scripts only — data files should not have execute
Using chmod -R with same mode for files and directories chmod -R 755 makes all files executable; most data files should not be Use capital X: chmod -R u=rwX,go=rX DIR — sets execute on directories only

Knowledge Check

Answer these before moving to the next slide.

  1. A file has permissions -rw-r----- owned by alice:sales. Can bob (who is in the sales group) read the file? Can carol (not in any relevant group) read it?
  2. Write the chmod command (octal) to set a file to be readable and writable by the owner, readable by group, and not accessible by others.
  3. A user runs ls /data/reports/ and sees the filenames, but when they try cat /data/reports/q1.txt they get "Permission denied". What is the likely permission configuration, and what is the fix?
  4. Write the three commands to set up /opt/shared so that all members of the staff group can read and write files, and new files automatically inherit the staff group.
  5. What is the current umask if newly created files have permissions 640 and new directories have permissions 750?
  6. What do the setuid, setgid, and sticky bits do, and where is each commonly used?

Knowledge Check — Answers

  1. Bob is in the sales group — Linux applies the group bits (r--) — yes, bob can read. Carol is neither the owner nor in sales — Linux applies other bits (---) — carol cannot read.
  2. chmod 640 FILE — owner: 4+2=6 (rw-), group: 4 (r--), other: 0 (---).
  3. The directory has r but not x for the user — they can see the names (r) but cannot access the files (no x). Fix: chmod +x /data/reports/ or chmod 755 /data/reports/ to grant execute permission.
  4. (1) sudo chown :staff /opt/shared — set group ownership
    (2) sudo chmod 2775 /opt/shared — rwxrwsr-x (setgid + group write)
    (3) Verify: ls -ld /opt/shared — should show s in group execute position
  5. umask 027 — files: 666 − 027 = 640; directories: 777 − 027 = 750. The umask subtracts its bits from the maximum permissions.
  6. setuid: process runs as the file owner — used on executables like passwd that need elevated privilege. setgid: on files — process runs with file's group; on directories — new files inherit the directory's group (shared workspace directories). Sticky bit: on directories — only the file owner, directory owner, or root can delete files (used on /tmp to prevent users deleting each other's files).

Key Takeaways

  1. Linux evaluates permissions in order: owner → group → other. First match wins. The owner's bits always apply to the owner — even if group or other has more access. Check the full path: a file with 644 is inaccessible if its parent directory lacks execute permission.
  2. Use ls -l to read, chmod to set permissions. Octal (644, 755, 700) sets all nine bits at once. Symbolic (u+x, go-w) makes targeted changes. Use capital X with -R to set execute on directories only.
  3. Use chown USER:GROUP to fix ownership issues. Only root can change ownership. The right ownership combined with the right permissions eliminates most access problems. For shared directories, combine chown :GROUP with chmod 2775 (setgid) so new files inherit the group.
  4. The umask subtracts from default permissions for new files and directories. Default umask 022 → new files 644, new directories 755. umask 027 → new files 640, new directories 750. Set persistent umask in ~/.bashrc or /etc/profile.d/.

Graded Lab

  • Create three files: public.txt (644), private.txt (600), and group.txt (660). Verify with ls -l. Log in as a second user and confirm which files are accessible and which are not.
  • Create a directory /tmp/testdir with permissions 444 (read-only for all). Attempt to enter it with cd. Observe the error. Fix with chmod +x and confirm you can now enter.
  • Create a group labteam. Create /opt/labshare owned by root:labteam with permissions 2775. Add two lab users to the group. As each user, create a file and verify it gets group labteam automatically.
  • Check the current umask. Change it to 027. Create a new file and directory. Verify the new file has 640 and the directory has 750. Reset the umask to 022.
  • Break a permission intentionally: set /etc/hosts permissions to 000 (as a copy in /tmp). Then use ls -l to diagnose, and chmod to restore 644. Verify cat works again.
  • Diagnose this scenario: a file /data/report.txt is owned by root:root with permissions 640. A user in no relevant group reports they cannot read it. Determine the correct fix and apply it.
RHCSA Objective

"Diagnose and correct file permission problems." Read with ls -l. Evaluate using owner→group→other. Fix with chmod and chown. Check parent directories. Check SELinux last.