You grant a named user write access to a file with `setfacl`, but `getfacl` prints `#effective:r--` beside that entry and the user still cannot write. What is the POSIX ACL mask, and what typically leaves it too restrictive?
answer
- one entry caps the others
- not the owner, not other
- chmod touches it, not the group entry
- getfacl annotates the shortfall
- setfacl recalculates it by default
basics
~20 sThe mask entry is an upper bound on every named user, named group and the owning group; rights above it are granted but not effective. It is most often narrowed by a later chmod, because on an ACL-bearing file the group-class mode bits map to the mask, not to the owning group.
solid answer
~50 sWhen an ACL has named entries it also has a `mask::` entry, and the kernel intersects the mask with every named-user entry, every named-group entry and the owning-group entry before deciding access. The file owner and `other` are not subject to it. `getfacl` shows the result of that intersection as an `#effective:` comment, which is your signal that an entry grants more than it delivers. The usual cause is a subsequent `chmod`: on a file with an extended ACL the group triad of the mode *is* the mask, so `chmod 640` or `chmod g-w` silently clamps every named entry at once. Fix it by setting the mask explicitly with `setfacl -m m::rw file`, or by re-running a `setfacl -m` for the entry, which recalculates the mask to cover the granted bits unless you pass `-n`.
code
bash · 7 linesinstall -m 640 /dev/null report.txt
setfacl -m u:bob:rw report.txt
getfacl report.txt # mask::rw- , bob effectively rw-
chmod g-w report.txt # narrows the MASK, not group::
getfacl report.txt # user:bob:rw- #effective:r--
setfacl -m m::rw report.txt
getfacl report.txt # bob is effective rw- againgo deeper
Recognise the #effective: annotation in getfacl output as "granted but capped", and know that a single mask entry sits above the named entries rather than each entry standing on its own.
Explain that the mask bounds named users, named groups and the owning group but not the owner or other, and that on an ACL-bearing file the group-class mode bits map to the mask — so chmod is what usually breaks things.
Diagnose a permission-denied report from getfacl output in one pass, then chase the cause upstream: an automated chmod in deployment or configuration management will re-narrow the mask on the next run unless you fix it there.
Own the policy consequence: any tooling that applies modes recursively can silently void an ACL scheme fleet-wide, so decide whether ACL-managed trees are excluded from blanket chmod runs or whether the ACLs are declared in the same system that sets the modes.
## The problem the mask solves Once a file can carry arbitrarily many named entries, a program that only understands the nine classic mode bits has no way to see them. That program still asks `stat` for a mode and still calls `chmod`. The POSIX ACL design keeps those two worlds consistent through a single entry called the **mask**. The mask is the maximum permission that can be granted through the *group class* — which is defined as every named-user entry, every named-group entry, and the owning-group entry. Two entries are outside the group class and therefore unaffected by the mask: `user::` (the file owner) and `other::`. Effective rights for an entry are the bitwise AND of the entry and the mask: ``` user:bob:rw- & mask::r-- = r-- ``` `getfacl` never hides this from you — it annotates any entry whose granted bits exceed the mask: ``` $ getfacl report.txt # file: report.txt # owner: alice # group: analysts user::rw- user:bob:rw- #effective:r-- group::rw- #effective:r-- mask::r-- other::r-- ``` Both bob and the owning group were granted write; both are delivering read only. Nothing is broken and nothing was deleted — the grants are intact and would come back the moment the mask widens. ## Why the mask usually shrinks: chmod This is the mechanism that catches people, and it is the point of the interview question. On a file with an extended ACL, the middle triad of the mode — the one everybody calls "the group permissions" — is *mapped to the mask entry*, not to the `group::` entry. So: ``` $ chmod 640 report.txt # looks like "owner rw, group r, other none" ``` did not merely change the owning group's rights. It set `mask::r--`, and every named user and named group on that file instantly lost write. `ls -l` will show `-rw-r-----+`, and that `r` in the middle is the mask, not the group's own entry. This has real operational consequences. A configuration-management run, a deployment script, or a well-meaning `chmod -R 750` over an application directory can silently defeat an entire ACL scheme without emitting a single error. The ACL survives; its effect does not. ## Why the mask exists at all The design goal is that a legacy tool that reduces permissions must actually reduce them. If `chmod g-w` only touched the `group::` entry, a named user entry granting write would sail straight through, and an administrator who believed they had removed group-class write access would be wrong. Routing the group-class bits through the mask makes the old, ACL-unaware interface safe: tightening the mode always tightens real access. ## Recalculation on setfacl `setfacl` recalculates the mask by default whenever it modifies the ACL: the new mask becomes the union of the permissions in all group-class entries, so a fresh `setfacl -m u:bob:rwx` will widen the mask to at least `rwx` and the grant takes effect immediately. That is why the problem almost never appears at the moment you add the entry — it appears afterwards. Two ways to override the default: ``` $ setfacl -n -m u:bob:rwx file # -n / --no-mask: leave the mask alone $ setfacl -m m::rw file # set the mask explicitly ``` `setfacl -n` is what you use when you have deliberately chosen a restrictive mask as a ceiling for a whole tree and do not want each new entry to raise it. ## Diagnosing it in practice The workflow when a user reports "permission denied but I was given access": 1. Confirm the file has an extended ACL — the `+` in `ls -l`. 2. Run `getfacl` and look for `#effective:` annotations. Their presence is the diagnosis; no further guessing is needed. 3. Decide whether the mask is wrong or the grant was supposed to be capped. If the mask is wrong, widen it with `setfacl -m m::rw`, and find out what narrowed it — usually an automated `chmod` you will need to fix at the source, or it will narrow again on the next run. ## The trap when the ACL is later removed A second, subtler consequence: because the group triad displays the mask, an ACL-bearing file whose mode reads `rwxrwx---` is *not* necessarily granting the owning group `rwx`. If the extended entries are later stripped — by `setfacl -b`, or by a restore that drops extended attributes — those bits become literal owning-group permissions again, which can be more generous than the group ever actually had. Always re-check permissions after removing ACLs from a tree rather than assuming the visible mode was accurate all along.
- Which ACL entries does the mask not constrain, and why is that deliberate?The `user::` (owner) and `other::` entries are outside the group class, so the mask never touches them. That is deliberate: the owner's rights and the world's rights already have their own mode-bit triads that ACL-unaware tools can read and set directly, so routing them through a mask would break the one-to-one correspondence between the mode and real access.
- What happens to the mask when you add a new named entry with setfacl?By default `setfacl` recalculates the mask as the union of all group-class entries, so the new grant is immediately effective. Pass `-n` (`--no-mask`) to leave the existing mask in place when you are intentionally using it as a ceiling, or set it yourself with `-m m::rw`. Because of that recalculation, a stale mask is almost always the work of a later `chmod`.
- How does the mask change what `ls -l` is actually telling you?On a file with an extended ACL the middle triad is the mask, not the owning group's own entry. So `-rw-rw-r--+` means "the group class may reach at most rw", and the owning group might in fact hold less. Anyone reading listings on an ACL-managed tree has to run `getfacl` to learn what the group itself is granted.
The mask is a ceiling on a room: you can install taller shelves in the corner labelled with someone's name, but nothing in that room can rise above the ceiling — while the owner's and everyone-else's shelves stand outside it.
saying these in an interview costs you the question
- Believing the mask applies to the file owner as well
- Thinking chmod deletes ACL entries rather than clamping them
- Reading the ls -l group triad as the owning group's real rights
- Assuming #effective is an error message rather than a computed result
- Fixing it by re-adding the entry without asking what narrowed the mask