Root Cause Diagnosis
rm: cannot remove 'file': Operation not permitted (errno EPERM) appearing even for root means the inode carries a protection that overrides normal permission checks, most commonly the ext2/3/4 immutable attribute (i) or append-only attribute (a). With either flag set, the kernel refuses unlink, rename, truncate, write, and hard-link operations until the flag is cleared, regardless of UID or mode bits. Other sources of the same error are filesystem-level read-only or special flags on XFS, Btrfs, and NFS, SELinux or AppArmor policy, a non-root user lacking ownership of a sticky directory, and the CAP_LINUX_IMMUTABLE capability being dropped.
Quick Fix
Inspect the attributes, clear the flag, and delete:
lsattr /path/to/file
sudo chattr -i -a /path/to/file
sudo rm -f /path/to/file
For a directory tree:
sudo chattr -R -i -a /path/to/dir
sudo rm -rf /path/to/dir
If chattr itself returns Operation not permitted, continue with the steps below.
Step-by-Step Resolution
1. Identify the attribute blocking the operation.
lsattr -d /path/to/file # file or directory itself
lsattr /path/to/parent/ # parent directory contents
Sample output and meaning:
| Flag | Meaning | Blocks |
|---|---|---|
i | Immutable | Delete, rename, write, link, truncate |
a | Append-only | Delete, rename, overwrite (appends allowed) |
s | Secure deletion (ignored on most kernels) | Nothing in practice |
e | Extent format (ext4 default) | Nothing; informational |
Check the parent directory as well. A directory with i or a prevents deleting any entry inside it, even when the file itself has no flags.
2. Remove the flags.
sudo chattr -i /path/to/file
sudo chattr -a /path/to/file
lsattr /path/to/file # verify the flags are gone
Apply the same commands to the parent directory if it carries a flag. Use -R for recursive removal, but note that chattr -R does not follow symlinks.
3. Delete the file.
sudo rm -f /path/to/file
sudo rm -rf /path/to/dir # directories
4. If chattr fails with Operation not permitted, check the capability bound.
Changing i and a requires CAP_LINUX_IMMUTABLE. Containers and hardened systems often drop it.
capsh --print | grep -i linux_immutable
grep CapBnd /proc/self/status
capsh --decode=$(awk '/CapBnd/{print $2}' /proc/self/status) | tr ',' '\n' | grep -i immutable
If it is missing:
- Docker: run the container with
--cap-add=LINUX_IMMUTABLE, or modify the file from the host. - Kubernetes: add
LINUX_IMMUTABLEundersecurityContext.capabilities.addin the pod spec. - System-wide bound:
sysctl kernel.cap_boundis not exposed on mainline kernels. A lowered bounding set is set at boot byCapabilityBoundingSet=in the systemd unit or bylcap-style tooling. Check /etc/systemd/system/*.service, /etc/security/capability.conf, and the kernel command line.
5. Check for filesystem-level restrictions.
findmnt -T /path/to/file -o TARGET,SOURCE,FSTYPE,OPTIONS
mount | grep -E " on /path/to/mountpoint "
If the options include ro, remount writable (after confirming why it is read-only, since ext4 flips to ro on I/O errors):
dmesg | tail -50 # look for EXT4-fs error, remounting read-only
sudo mount -o remount,rw /mountpoint
If the filesystem went read-only due to errors, unmount and run fsck first:
sudo umount /mountpoint
sudo fsck -f /dev/sdXN
6. Handle filesystem-specific flags.
# Btrfs: the file may be in a read-only snapshot or subvolume
sudo btrfs property get -ts /path/to/subvol ro
sudo btrfs property set -ts /path/to/subvol ro false
# XFS: immutable and append-only are set through xfs_io, and lsattr/chattr work on modern kernels
xfs_io -c "lsattr" /path/to/file
sudo xfs_io -c "chattr -i" /path/to/file
7. Check mandatory access control.
# SELinux
getenforce
ls -Z /path/to/file
sudo ausearch -m avc -ts recent | tail
sudo setenforce 0 # diagnostic only; re-enable with setenforce 1
# AppArmor
sudo aa-status
sudo dmesg | grep -i apparmor | tail
If a denial appears, correct the label or profile rather than leaving enforcement disabled:
sudo restorecon -v /path/to/file
8. Check for processes holding the file and for immutable-setting services.
sudo lsof /path/to/file
sudo fuser -v /path/to/file
sudo systemctl list-units --type=service | grep -Ei 'aide|tripwire|fail2ban|clamav|immutable'
Some security tools, malware, and configuration management agents re-apply chattr +i automatically. If the flag returns after clearing, stop the responsible service first, and search for cron entries, systemd timers, or scripts calling chattr +i:
sudo grep -rI "chattr" /etc/cron* /etc/systemd /var/spool/cron /usr/local 2>/dev/null
9. Use a rescue environment as a last resort.
If the root filesystem is read-only, the capability is unavailable, or the system will not boot, boot from a live USB, mount the volume, and clear the flags offline:
sudo mount /dev/sdXN /mnt
sudo chattr -R -i -a /mnt/path/to/file
sudo rm -f /mnt/path/to/file
sudo umount /mnt
Why This Fails for Some Users
- Parent directory is immutable: The file shows clean flags, but the parent has
iora. Clear the flag on the directory, not the file. - Wrong tool for the filesystem:
chattrandlsattronly support ext2/3/4 flags and a subset on XFS (kernel 4.x+), Btrfs, and F2FS. On FAT, exFAT, NTFS (ntfs-3g), and most FUSE filesystems,lsattrreturnsInappropriate ioctl for device. Use the filesystem’s own tools or check mount options and permissions instead. - NFS and network mounts: Immutable flags set on the server cannot be cleared from the client. Run
chattron the NFS server, or on the exported directory. Root squash (root_squashin /etc/exports) also maps client root tonobody, which producesOperation not permittedon files owned by root. - Sticky bit on shared directories: In directories such as /tmp with mode
1777, only the file owner, directory owner, or root can delete an entry. Check withls -ld /tmpandstat. - Containers and overlayfs: On overlay filesystems, files from lower image layers cannot be modified in the upper layer when flags are set on the underlying layer. Delete from the host via the container’s
MergedDiror rebuild the image. - Mounted bind or loop device read-only: A read-only bind mount (
mount -o bind,ro) returnsRead-only file system, but some tools surface it asOperation not permitted. Verify withfindmnt. - Kernel lockdown and securelevel-style protections: Hardened kernels and some distributions limit modification of immutable flags on protected paths while a security module is active. Boot parameters such as
lockdown=integrityorsecurelevel(BSD) stop flag changes until reboot. - Cannot clear on special files: Some files in /proc, /sys, /dev, and device nodes are not regular inodes.
Operation not permittedthere indicates kernel-managed objects, not an attribute problem. - File is a mount point or in use as one:
rmcannot remove a mount point and may reportDevice or resource busyorOperation not permitted. Checkfindmnt /pathand unmount first. - Flag reappears: Configuration management (Ansible
attributes: +i, Puppet, Salt), IDS software, or malware re-applies the flag. Inspect cron, timers, and agents (Step 8) before concluding the removal failed. - Security note: An unexpected
iflag on a system file such as /etc/passwd, /etc/crontab, or a binary in /usr/bin is a common persistence technique used by malware to resist cleanup. Treat unexplained immutable system files as a possible compromise and investigate before removing them.