You try to delete a file as root, and Linux tells you “Operation not permitted.” This happens when a file has the immutable attribute set – a kernel-level flag that prevents any modification, even by root. The rm, mv, unlink, and even truncate commands all fail against it. Other causes include SELinux policies, read-only mount options, POSIX ACLs, and processes holding the file open.
This guide covers every common reason Linux refuses to delete a file, starting with the most likely cause (immutable attributes) and working through SELinux, mount options, ACLs, and special filesystem cases. These steps work on any Linux distribution – RHEL, Ubuntu, Debian, Rocky Linux, AlmaLinux, and others. You can reference the official chattr man page for the full list of extended attributes.
Step 1: Understand the Error
When you run rm on a file and get “Operation not permitted,” Linux is not complaining about standard file permissions. Normal permission errors show “Permission denied” instead. The “Operation not permitted” (EPERM) error means something deeper is blocking the operation – usually an extended file attribute or a kernel-level restriction.
Here is what the error looks like in practice:
rm /etc/resolv.conf
Even as root, this returns the EPERM error:
rm: cannot remove '/etc/resolv.conf': Operation not permitted
The same error occurs when trying to move, rename, or overwrite the file. Standard chmod and chown commands also fail with the same message. This is your signal to check extended file attributes first.
Step 2: Check File Attributes with lsattr
The lsattr command shows extended attributes that ls -l does not display. This is the first tool to reach for when you hit “Operation not permitted” on a file you know you have ownership of.
lsattr /etc/resolv.conf
If the immutable flag is set, you will see an i in the attribute string:
----i---------e------- /etc/resolv.conf
The i flag means the file is immutable – it cannot be modified, deleted, renamed, or linked to. Not even root can touch it while this flag is active. The e flag indicates the file uses extents for storage, which is normal on ext4 filesystems.
To check all files in a directory, use the -a flag to include hidden files:
lsattr -a /etc/
This lists every file and its extended attributes. Look for the i (immutable) or a (append-only) flags – both can cause “Operation not permitted” errors. You can reference the lsattr man page for additional options.
Step 3: Remove the Immutable Flag with chattr
Once you confirm the immutable flag is the problem, remove it with chattr. You need root access for this – the immutable attribute can only be changed by the root user or a process with the CAP_LINUX_IMMUTABLE capability.
sudo chattr -i /etc/resolv.conf
Verify the flag is removed:
lsattr /etc/resolv.conf
The output should no longer show the i flag:
---------e------- /etc/resolv.conf
Now you can delete, move, or modify the file normally. If you need to remove the immutable flag from multiple files in a directory, use a recursive approach:
sudo chattr -R -i /path/to/directory/
Be careful with recursive removal – the immutable flag is often set intentionally to protect critical system files. Check why the flag was there before removing it.
Step 4: Understand chattr Attributes
The chattr command supports several attributes beyond the immutable flag. Understanding them helps you diagnose “Operation not permitted” errors and protect your own files when needed.
Set an attribute with + and remove it with -:
sudo chattr +i /path/to/file
The most commonly used attributes are:
- i (immutable) – file cannot be modified, deleted, renamed, or hard-linked. No process can write to it, not even root
- a (append-only) – file can only be opened in append mode for writing. Existing content cannot be changed or deleted. Useful for log files
- s (secure delete) – when the file is deleted, its blocks are zeroed on disk. Not all filesystems honor this
- u (undeletable) – when the file is deleted, its contents are saved for potential recovery. Not widely implemented
- e (extents) – file uses extents for mapping blocks on disk. Set automatically on ext4 and cannot be removed manually
- A (no atime updates) – access timestamp is not modified when the file is read. Reduces disk I/O on frequently read files
- S (synchronous updates) – changes are written to disk immediately, similar to the
syncmount option for that file
The a (append-only) attribute is particularly relevant because it also triggers “Operation not permitted” when you try to delete or truncate a file. Sysadmins use it on log files to prevent tampering – a compromised process can add lines but cannot erase evidence. Remove it with:
sudo chattr -a /var/log/secure
Step 5: Check for SELinux Context Issues
On RHEL, Rocky Linux, AlmaLinux, and Fedora systems, SELinux can block file operations even when standard permissions and extended attributes look correct. SELinux uses mandatory access control policies that override normal discretionary permissions.
Check if SELinux is enforcing:
getenforce
If the output is Enforcing, SELinux is actively controlling file access. Check the SELinux context of your file:
ls -Z /path/to/file
The output shows the security context label:
system_u:object_r:etc_t:s0 /etc/resolv.conf
If the context is wrong (for example, a file restored from backup may have a different label), fix it by restoring the default context:
sudo restorecon -v /path/to/file
Check the SELinux audit log for denied operations. This is the fastest way to confirm SELinux is the cause:
sudo ausearch -m avc -ts recent
If you see AVC denial messages related to your file, the SELinux policy is blocking the operation. You can temporarily set SELinux to permissive mode to test:
sudo setenforce 0
If the file operation succeeds with SELinux in permissive mode, the SELinux policy is the root cause. Fix the context label rather than leaving SELinux permissive in production.
Step 6: Check for Mount Options
A filesystem mounted as read-only prevents all write operations, including file deletion. This is common after disk errors (when the kernel remounts the filesystem read-only to prevent data loss) or when the mount was intentionally configured that way.
Check how the filesystem is mounted:
mount | grep "$(df /path/to/file --output=source | tail -1)"
Look for ro (read-only) in the mount options. If the filesystem is mounted read-only, you will see output like:
/dev/sda1 on / type ext4 (ro,relatime)
To remount a filesystem as read-write:
sudo mount -o remount,rw /
If the kernel forced a read-only remount, check dmesg for filesystem errors:
dmesg | grep -i "remount\|error\|ext4\|xfs"
Disk errors that trigger a read-only remount need immediate attention. Run a filesystem check before remounting read-write, or you risk data corruption.
Step 7: Check for POSIX ACLs
POSIX Access Control Lists provide fine-grained permissions beyond the standard owner/group/other model. An ACL entry can deny specific operations to specific users, even root in some configurations.
Check the ACL on a file with getfacl:
getfacl /path/to/file
The output shows both standard and extended permissions:
# file: path/to/file
# owner: root
# group: root
user::rw-
user:deploy:---
group::r--
mask::r--
other::r--
In this example, the user deploy has been explicitly denied all access. The mask line also limits the maximum effective permissions for named users and groups.
To remove all extended ACL entries and return to standard permissions:
sudo setfacl -b /path/to/file
To remove a specific user’s ACL entry:
sudo setfacl -x u:deploy /path/to/file
Also check the parent directory – you need write and execute permissions on the directory to delete a file inside it, regardless of the file’s own permissions. A ls -la on the parent directory confirms those permissions.
Step 8: Check for Processes Holding the File
A running process with a mandatory lock on a file can prevent deletion. While this is less common on Linux (advisory locking is the default), some applications use mandatory file locks, and certain filesystem-level operations can cause similar behavior.
Find processes that have the file open:
sudo lsof /path/to/file
The output shows which processes hold the file open:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1234 root 10w REG 253,0 45678 123456 /path/to/file
If lsof is not installed, use fuser as an alternative:
sudo fuser -v /path/to/file
To free the file, stop the process gracefully first, then retry the deletion. Only force-kill as a last resort:
sudo kill 1234
For stubborn processes that refuse to release the file, check if they are zombie processes or are stuck in an uninterruptible sleep state (D state in ps). A process in D state is waiting on I/O and cannot be killed – the underlying storage issue must be resolved first.
Step 9: Special Cases – NFS, CIFS, and Snap Mounts
Network filesystems and containerized mounts add extra layers that can cause “Operation not permitted” even when everything looks correct locally.
NFS mounts
NFS servers can export directories with root_squash enabled (the default). This maps root on the client to the nobody user on the server, stripping root privileges for file operations. Check the export options on the NFS server:
exportfs -v
The output shows mount options per export:
/data 192.168.1.0/24(rw,wdelay,root_squash,no_subtree_check)
If you need root access on the NFS share, change root_squash to no_root_squash in /etc/exports on the server and re-export. Be aware this is a security risk – only use it in trusted networks.
CIFS/SMB mounts
Windows shares mounted via CIFS may not support Linux permission operations. The mount options uid, gid, and file_mode control local permissions. If the remote server denies the operation, Linux reports “Operation not permitted.”
Check CIFS mount details:
mount | grep cifs
Snap and overlay mounts
Snap packages on Ubuntu create read-only squashfs mounts under /snap/. Files inside these mounts cannot be modified or deleted by design. Check if your file path falls within a snap mount:
df /path/to/file
If the filesystem type is squashfs, the file is inside a snap package. You cannot delete it directly – manage the snap package instead using snap remove.
Quick Reference – chattr Flags
This table summarizes the most useful chattr flags and their effects on file operations.
| Flag | Name | Effect |
|---|---|---|
i | Immutable | Cannot modify, delete, rename, or link. Blocks all changes including by root |
a | Append-only | File can only be opened for appending. Cannot delete content or the file itself |
s | Secure delete | Blocks are zeroed on disk when file is deleted |
u | Undeletable | Contents saved for recovery when deleted (filesystem dependent) |
e | Extents | File uses extents for block mapping. Auto-set on ext4, not removable |
A | No atime | Access time not updated on read. Reduces I/O on hot files |
S | Synchronous | Changes written to disk immediately. No write caching for this file |
c | Compressed | File is automatically compressed on disk by the kernel (filesystem dependent) |
d | No dump | File is not included in dump backups |
j | Journaled | File data is written to the ext3/ext4 journal before the file itself |
Conclusion
The “Operation not permitted” error when deleting files on Linux almost always comes down to immutable file attributes. Run lsattr first – it solves the problem in the majority of cases. When it is not the immutable flag, work through SELinux contexts, mount options, ACLs, and process locks in that order. For network filesystems, check NFS root_squash settings and CIFS mount permissions on the server side.
On production systems, always investigate why a file was made immutable before removing the flag. System administrators set the immutable attribute intentionally to protect critical files like /etc/resolv.conf or /etc/passwd from accidental modification. If you remove it, consider re-applying it after your changes are done.