Linux Permission Denied Error When Accessing .ssh Directory Despite Correct Permissions


2 views

I recently encountered a perplexing permission issue on a RHEL system where a user couldn't access their own .ssh directory despite apparently correct permissions. Here's the complete picture:

$ ls -lah
drwxrwxrwx 6 g    g    4.0K Jun 23 13:27 .
drwxrw-r-x 6 root root 4.0K Jun 23 13:15 ..
-rwxrw---- 1 g    g     678 Jun 23 13:26 .bash_history
-rwxrw---- 1 g    g      33 Jun 23 13:15 .bash_logout
-rwxrw---- 1 g    g     176 Jun 23 13:15 .bash_profile
-rwxrw---- 1 g    g     124 Jun 23 13:15 .bashrc
drw-r----- 2 g    g    4.0K Jun 23 13:25 .ssh

The user 'g' (uid=504, gid=506) couldn't perform basic operations:

$ ls -lah .ssh/
ls: .ssh/: Permission denied

$ cat .ssh/authorized_keys
cat: .ssh/authorized_keys: Permission denied

Oddly, changing permissions to any variant with execute (x) permission for user (like 700, 744) resolved the issue when done as root.

After thorough investigation, I discovered several potential culprits:

$ getfacl .ssh
# file: .ssh
# owner: g
# group: g
user::rw-
group::r--
other::---

The critical findings:

  • Parent directory has 777 permissions (world-writable)
  • .ssh directory has 640 permissions (lacking execute bit)
  • SELinux context might be interfering
  • Potential NFS or filesystem mount options issue

Here's the complete fix that worked:

# As root:
chmod 750 /home/g/.ssh
restorecon -Rv /home/g/.ssh
chown g:g /home/g/.ssh/*

# Verify SELinux context:
ls -Z /home/g/.ssh

For automated checks, create a verification script:

#!/bin/bash
USER="g"
SSH_DIR="/home/${USER}/.ssh"

check_access() {
    sudo -u $USER ls $SSH_DIR >/dev/null 2>&1
    return $?
}

if ! check_access; then
    echo "Fixing permissions for ${SSH_DIR}"
    chmod 750 $SSH_DIR
    chown ${USER}:${USER} $SSH_DIR
    restorecon -Rv $SSH_DIR
fi

To avoid recurrence:

# Add to user's .bashrc
if [ "$(stat -c %a ~/.ssh)" != "750" ]; then
    chmod 750 ~/.ssh
fi

# SELinux boolean for ssh home dirs
setsebool -P ssh_home_dir 1

Remember that SSH is particularly sensitive to permission issues. The .ssh directory should typically have 700 permissions and files inside 600 for security.


I recently encountered a perplexing Linux permission issue that had me scratching my head for hours. Here's the scenario:

$ ls -lah
drwxrwxrwx 6 g    g    4.0K Jun 23 13:27 .
drwxrw-r-x 6 root root 4.0K Jun 23 13:15 ..
-rwxrw---- 1 g    g     678 Jun 23 13:26 .bash_history
-rwxrw---- 1 g    g      33 Jun 23 13:15 .bash_logout
-rwxrw---- 1 g    g     176 Jun 23 13:15 .bash_profile
-rwxrw---- 1 g    g     124 Jun 23 13:15 .bashrc
drw-r----- 2 g    g    4.0K Jun 23 13:25 .ssh

Despite having ownership (user 'g' in group 'g') and what appears to be correct permissions, attempts to access the .ssh directory fail:

$ ls -lah .ssh/
ls: .ssh/: Permission denied

Here's what I tried initially:

  1. Verified user identity: id g returns uid=504(g) gid=506(g) groups=506(g)
  2. Checked parent directory permissions (which are wide open at 777)
  3. Confirmed group membership with groups command

The critical insight came when I realized the .ssh directory had permissions drw-r----- (640). While this grants read permission to the owner, it's missing the execute bit (x), which is required to actually enter or traverse the directory.

This explains why changing to 700 (drwx------) worked:

$ chmod 700 .ssh
$ ls -ld .ssh
drwx------ 2 g g 4096 Jun 23 13:25 .ssh

You mentioned this configuration worked on another identical box. This could be due to:

  • SELinux contexts being different between systems
  • ACLs (Access Control Lists) modifying the effective permissions
  • Filesystem mount options (like noexec on the parent directory)

To check for SELinux:

$ ls -Z .ssh
$ getenforce

To verify ACLs:

$ getfacl .ssh

For .ssh directories, here are recommended permission sets:

# Minimum functional permissions
chmod 700 ~/.ssh

# For authorized_keys (if present)
chmod 600 ~/.ssh/authorized_keys

# For SSH config
chmod 600 ~/.ssh/config

When facing permission problems, this checklist helps:

1. Check basic permissions: ls -ld /path
2. Verify ownership: ls -ldn /path
3. Check group membership: groups $USER
4. Look for ACLs: getfacl /path
5. Check SELinux: ls -Z /path
6. Verify mount options: mount | grep 'on /path'
7. Test with strace: strace ls /path 2>&1 | grep EACCES