ERROR

How to Fix Linux Error EACCES (13): Permission Denied

Quick Fix Summary

TL;DR

Run `ls -la` on the target file/directory, then use `chmod` or `chown` to correct the user/group permissions.

The EACCES (Error ACCESs) error, represented by errno 13, occurs when a process lacks the necessary filesystem permissions to perform an operation (read, write, or execute). It's a security enforcement mechanism, not a system failure, but it can halt critical services.

Diagnosis & Causes

  • Process user lacks read/write/execute permission on the target.
  • File or directory is owned by a different user/group.
  • Parent directory lacks execute ('x') permission for traversal.
  • SELinux or AppArmor security policy is blocking access.
  • File is mounted with restrictive options (e.g., `noexec`).
  • Recovery Steps

    1

    Step 1: Diagnose the Permission Issue

    First, identify the exact file/directory and the current user/context. Use `ls -la` and `id` to gather facts.

    bash
    # Identify the problematic file/directory and current user
    ls -la /path/to/target
    id
    ps aux | grep <your_process>
    2

    Step 2: Fix Standard File Permissions (chmod/chown)

    If standard Unix permissions are the issue, correct them using `chmod` to change modes or `chown` to change ownership. Be precise to avoid over-permissioning.

    bash
    # Grant read/write to owner, read-only to group/others (common for configs)
    sudo chmod 644 /path/to/file
    # Change ownership to the service user (e.g., nginx, postgres)
    sudo chown nginx:nginx /path/to/file
    # Add execute permission for a script
    sudo chmod +x /path/to/script.sh
    3

    Step 3: Check and Fix Directory Traversal Permissions

    To access a file, the user needs execute ('x') permission on every parent directory. Missing this is a common oversight.

    bash
    # Check permissions on all parent directories
    namei -l /path/to/deep/file
    # Grant execute permission on a directory for user/group/others as needed
    sudo chmod +x /path/to/parent/directory
    4

    Step 4: Investigate Mandatory Access Control (SELinux/AppArmor)

    If standard permissions look correct, a MAC system like SELinux (common on RHEL/CentOS/Fedora) is likely blocking access. Check and adjust the security context.

    bash
    # Check for SELinux denials (tail audit log)
    sudo tail -f /var/log/audit/audit.log | grep avc
    # View file's SELinux context
    ls -laZ /path/to/file
    # Temporarily set permissive mode to test (Production: use `semanage fcontext` & `restorecon`)
    sudo setenforce 0
    # Restore default context after policy change
    sudo restorecon -Rv /path/to/target
    5

    Step 5: Verify Filesystem Mount Options

    Filesystem mounts can have options like `noexec`, `nosuid`, or `ro` that override local permissions. Check `/etc/fstab` and the current mount table.

    bash
    # Check mount options for the target filesystem
    findmnt -T /path/to/target
    grep /path/to/target /proc/mounts
    # Review persistent mount settings
    cat /etc/fstab | grep <relevant_mount_point>
    6

    Step 6: Resolve Sticky Bit or Special Permission Issues

    Special permissions like the sticky bit on directories (e.g., /tmp) or setuid/setgid bits can cause unexpected EACCES for non-owners.

    bash
    # Identify special permissions (look for 't', 's', 'S' in ls -la output)
    ls -la /directory
    # Example: Remove setgid bit if causing issues
    sudo chmod g-s /path/to/directory

    Architect's Pro Tip

    "For containerized apps (Docker/K8s), EACCES often stems from mismatched UIDs/GIDs between the host volume and container user. Use `stat` to compare and set `podman run --user` or securityContext in Kubernetes."

    Frequently Asked Questions

    I fixed permissions with chmod 777, but it still doesn't work. Why?

    This strongly points to SELinux/AppArmor (Step 4) or filesystem mount options like `noexec` (Step 5). Never use `chmod 777` in production; it's a major security anti-pattern.

    How do I differentiate EACCES from ENOENT (No such file or directory)?

    ENOENT (errno 2) means the path doesn't exist. EACCES (errno 13) means the path exists, but access is denied. Check your error logs or use `strace` on the failing process for the exact errno.

    My script runs manually but fails via cron/crontab. Is this EACCES?

    Yes, likely. Cron jobs run with a minimal environment and a different user (often root or the crontab owner). Ensure the script and all files/directories it accesses have correct permissions for the cron user, and that environment variables (like PATH) are fully set within the script.

    Related Linux Guides