Sticky‑Bit Directories and ACLs: Why “Permission denied” Still Happens
When you try to move a file into a directory that has the sticky bit set, the kernel first checks the directory’s owner and the user’s write permission. If the directory is owned by someone else, the sticky bit forces it to also check the file’s owner. ACLs can grant write access to a group or user, but the sticky‑bit logic still requires the file’s owner to match the directory’s owner unless the moving user has the write permission on the file itself. That subtle rule is the source of a lot of “Permission denied” errors that only surface when ACLs are involved.
Typical Scenario
# /srv/shared is owned by root:root, sticky bit set
chmod 1770 /srv/shared
# user alice has an ACL that allows writing to /srv/shared
setfacl -m u:alice:rwx /srv/shared
# alice creates a file in her home
touch /home/alice/tmp.txt
# she tries to move it into /srv/shared
mv /home/alice/tmp.txt /srv/shared/
The move fails with:
mv: cannot move '/home/alice/tmp.txt' to '/srv/shared/tmp.txt': Permission denied
Even though the ACL grants write access, the sticky bit blocks the operation because the file’s owner (alice) does not match the directory’s owner (root).
Fixes
| Approach | Command | Trade‑offs |
|---|---|---|
| Change the file’s owner | sudo chown root:root /home/alice/tmp.txt | Requires sudo; changes ownership permanently. |
Use --no-preserve-root | mv --no-preserve-root /home/alice/tmp.txt /srv/shared/ | Bypasses ownership check; risky if the file contains sensitive data. |
| Add the user to the directory’s group | sudo usermod -aG root alice | Grants group write; may expose other root‑owned files. |
| Remove the sticky bit | chmod -t /srv/shared | Loses the “delete‑by‑owner‑only” protection. |
| Create a dedicated group | sudo groupadd shared; sudo chown :shared /srv/shared; chmod 1770 /srv/shared; setfacl -m g:shared:rwx /srv/shared | Keeps sticky bit, isolates permissions. |
The most common production‑ready pattern is the last one: create a group that owns the directory, grant that group write access, and set the sticky bit. This preserves the delete‑by‑owner‑only rule while allowing any member of the group to move files into the directory.
Practical Example
# Create group and set ownership
sudo groupadd shared
sudo chown :shared /srv/shared
chmod 1770 /srv/shared
# Grant group write via ACL
setfacl -m g:shared:rwx /srv/shared
# Add users
sudo usermod -aG shared alice
sudo usermod -aG shared bob
# alice can now move files
mv /home/alice/tmp.txt /srv/shared/
Because the directory is owned by root:shared, the sticky bit only blocks deletions by users who are not the owner. Moving a file is allowed as long as the moving user is in the shared group.
Security Considerations
- Sticky bit is a delete guard, not a write guard. Removing it removes the protection against accidental or malicious deletions by non‑owners.
- Group membership should be limited. Adding too many users to the owning group dilutes the security boundary.
- ACL inheritance. When a new file is created inside the directory, it inherits the ACL. Verify that
getfacl /srv/sharedshows the expected defaults.
Troubleshooting Checklist
- Check sticky bit:
ls -ld /srv/shared→ look for thetin the permission string. - Verify ownership:
stat /srv/shared→ ensure the owner matches the intended policy. - Inspect ACLs:
getfacl /srv/shared→ confirm group write and default entries. - Test with a minimal file:
touch /tmp/testfile && mv /tmp/testfile /srv/shared/→ isolates the problem from user‑specific ACLs.
References
- Linux sticky bit behavior
- POSIX ACL documentation
See also
- Web Application and API Protection (WAAP) platforms and Next-Generation WAFs (NGWAF)
- How to Use systemd‑resolved to Serve a Local Search Domain on My Home Network
- Pulling a Single File from a Borg Backup Without Unpacking the Whole Archive
- Stop systemd‑journald from filling your Raspberry Pi’s 8 GB SD card with logs – how to cap its size
- Send a Telegram Alert When Your Home Server’s /home Reaches 90% Usage With a Tiny systemd Service and curl