Simple fix — 30 seconds
You're sitting there, ls -l shows -rw------- 1 root root 1024 Jan 1 12:00 secret.txt, and you own it. But cat secret.txt spits back Permission denied. What's actually happening here is the kernel's permission check. Even though you're the owner, the kernel looks at the file's permission bits — and if they don't include read for the owner, you're locked out.
The quickest fix: add read permission for the owner.
chmod u+r secret.txt
If it's a directory you can't enter, you also need execute:
chmod u+rx mydir
That's it. 30 seconds. If that works, you're done. No need to read further. But if you're still getting Permission denied after that, something else is blocking you.
Moderate fix — 5 minutes
So you ran chmod u+r and it silently succeeded, but cat still fails. The reason step 3 works is there are two more layers the kernel checks after file permissions: the immutable attribute and ACLs.
Immutable flag — chattr
If someone ran chattr +i secret.txt as root, that file is immutable. Even root can't modify it without clearing the flag first. Check with:
lsattr secret.txt
If you see ----i-------- in the output, that's the problem. Remove it with:
sudo chattr -i secret.txt
You need sudo here because changing attributes is a privileged operation. Once it's gone, your chmod will actually take effect.
ACL overrides
POSIX ACLs (Access Control Lists) can silently override the standard permission bits. Check with:
getfacl secret.txt
If you see something like user:root:--- where it should be r--, the ACL is blocking you. Fix it with:
setfacl -m u::r secret.txt
Or just remove all ACLs entirely:
setfacl -b secret.txt
Be careful — that wipes out any custom ACLs you might have set.
Advanced fix — 15+ minutes
If you've done both of the above and Permission denied still stares at you, you're dealing with one of two things: SELinux or AppArmor. These are mandatory access control (MAC) systems that run after the discretionary checks (ownership, permissions, ACLs). They can deny access even when Unix permissions say yes.
Check SELinux
First, confirm SELinux is even running:
getenforce
If it says Enforcing, SELinux is active. Now check the file's context against what the policy expects:
ls -Z secret.txt
You'll see something like unconfined_u:object_r:user_home_t:s0. If you moved this file from /tmp or another location, the context might be wrong. The real fix is to restore the default context for where the file lives:
restorecon -v secret.txt
If that doesn't work, you need to find out exactly what SELinux is blocking. Check the audit log:
sudo ausearch -m avc -ts recent
Or if you're on a system without auditd, use:
sudo cat /var/log/messages | grep AVC
The AVC denial message will tell you the exact source context, target context, and class. Sometimes the fix is as simple as changing the file's type to match what the policy expects. For example, if a web server needs to read it:
sudo semanage fcontext -a -t httpd_sys_content_t secret.txt
sudo restorecon -v secret.txt
Check AppArmor
If you're on Ubuntu or Debian, you're more likely dealing with AppArmor. Check its status:
sudo aa-status
Look for profiles that might apply to the process accessing the file. If you're blocked by an AppArmor profile, the audit log will show it:
sudo journalctl -k | grep -i apparmor
You'll see messages like DENIED with the profile name and path. The nuclear option is to disable the profile entirely, but don't do that in production. Instead, edit the profile in /etc/apparmor.d/ and add the appropriate allow rule for the file path, then reload:
sudo apparmor_parser -r /etc/apparmor.d/your-profile
One last check — filesystem mount options
I've seen this trip up people on shared hosts or Docker containers. Check the mount options of the filesystem:
mount | grep secret.txt
Or just run mount alone and look for noexec, nosuid, or nodev. While noexec doesn't block reads, it blocks execute — and if you're trying to run a binary, you'll see Permission denied. Rarely, a mount with ro (read-only) can confuse things if you're root. Check with cat /proc/mounts for the exact options.
Bottom line: When you own a file and still get denied, work through this checklist in order — permissions, then immutable flag, then ACLs, then MAC, then mount options. Nine times out of ten, it's the first one. But when it's not, knowing these deeper layers saves you from reinstalling your OS.