← Debugging Guides

阅读中文版本

Linux: Permission denied even after chmod

Diagnose Linux Permission denied that persists after chmod by checking ownership, parent directories, mount options, and SELinux or AppArmor.

intermediatedebugginglinuxpermissions

Symptoms

  • bash: ./script.sh: Permission denied
  • chmod +x was applied but execution still fails
  • Writes fail in a directory that shows rwx permissions

Possible causes

  • The user does not own the file and lacks the needed permission class
  • A parent directory lacks execute permission, blocking traversal
  • The filesystem is mounted noexec or read-only
  • SELinux or AppArmor denies access despite Unix permissions

Diagnosis steps

Check permissions on the file and every parent directory

namei -l /path/to/script.sh

Interpretation

namei lists permissions along the whole path, revealing a missing execute on a parent.

Test whether the filesystem forbids execution

mount | grep " /mnt "

Interpretation

A noexec or ro mount option blocks execution regardless of mode bits.

Check for mandatory access control denials

dmesg | grep -i denied

Interpretation

SELinux and AppArmor log denials that chmod cannot fix.

Root cause

Unix permission checks consider ownership class (user, group, other) and require execute on every parent directory to traverse a path. chmod changes mode bits but not ownership, mount options, or MAC policy, so a denial can persist when the real obstacle is a different layer.

Fix

Fix ownership with chown so the user is in the right permission class, grant execute on parent directories as needed, and remove noexec or remount rw where appropriate. For SELinux or AppArmor, adjust labels or policy rather than disabling enforcement. Never use blanket chmod 777 as a fix.

Verify the fix

Re-run the command; it executes or the write succeeds, and namei shows execute permission on the file and all parent directories, with no new MAC denial in dmesg.

Symptoms

A command fails with Permission denied even after chmod +x. The mode bits look correct, which means another layer is refusing access.

Diagnosis

Inspect the whole path and mount options:

namei -l /data/script.sh
mount | grep /data
dmesg | tail | grep -i denied

Fix

Correct ownership and traversal, not just file mode:

chown app:app /data/script.sh
chmod 750 /data/script.sh
chmod +x /data    # parent must be traversable

Remove noexec if the mount is the blocker, and fix MAC labels rather than disabling SELinux.

Verification

Run the script; it executes. namei confirms execute permission on the file and every parent directory, and dmesg shows no new denial, proving access now succeeds.

Four Layers That Can Deny Access

Permission denied in Linux is not a single check but four that run in order: the user-versus-group-versus-other class on the file, the same check on every parent directory for traversal, mount flags such as noexec or read-only, and mandatory access control from SELinux or AppArmor. chmod only touches the first, so it cannot fix a missing parent execute bit, a noexec mount, or an MAC denial. namei -l shows the whole path at once, mount output shows filesystem flags, and dmesg shows MAC denials, which together pinpoint the layer that is actually refusing access before you change anything.