How does ACL calculate the effective permissions on a file?
I ran the following command to give the
rwx permissions on new files and subdirectories created:
[belmin@server1]$ ls -la total 24 drwxr-sr-x+ 2 guards guards 4096 Aug 27 15:30 . drwxr-xr-x 104 root root 12288 Aug 27 15:19 .. [belmin@server1]$ sudo setfacl -m d:g:wheel:rwX . [belmin@server1]$ getfacl . # file: . # owner: guards # group: guards # flags: -s- user::rwx group::r-x group:wheel:rwx other::r-x default:user::rwx default:group::r-x default:group:wheel:rwx default:mask::rwx default:other::r-x
However, when I create a file as root, I am not completely clear how the
effective permissions are calculated:
[belmin@server1]$ sudo touch foo [belmin@server1]$ getfacl foo # file: foo # owner: root # group: guards user::rw- group::r-x #effective:r-- group:wheel:rwx #effective:rw- group:guards:rwx #effective:rw- mask::rw- other::r--
Can someone elaborate on what this means?
effective permissions are formed by ANDing the actual (real?) permissions with the
mask. Since the
mask of your file is
rw-, all the
effective permissions have the
x bit turned off.
Short answer: If you want mask with the execute bit on, you must explicitly set it using
touch. Security forbids its implicit setting.
setfacl -n -m m::rwx foo
“-n” to suppress recalculation of the mask (may not be needed).
“m::rwx” sets the mask value to ‘rwx’. Note that “m::x” would disable all reads and writes.
I am unable to show why the mask is “rw-“. I assume that the default directory where
touch creates the file remains unchanged for the entire OP example.
The directory entry for ‘foo’ should show owner ‘root’ (because of the sudo command and group ‘guards’ because the directory has the SUID bit set. The permissions will be defaults ‘-rw-…r–‘ with the group permissions of the directory ‘-…r-x…’ (due to the SUID bit showins as little s).
Next comes the ACLes, which should be the directory default. Given that ACLs inherit, I wouldn’t expect any ACLe’s to created, and the ACLE mask to be the directory default, ‘rwx’.
But if they are created, I would expect the new ACLe’s to be primed from the default, again leaving the mask at ‘rwx’. If they are not primed from the defaults, this would seem to defeat the idea of a default ACL — the “default” ACL would only provide named user and named group ACLes.
This now begs the question of what the mask ACLe should be. I’d expect it to be ‘rwx’ from the default mask entry. But it could be created with a blank mask, and then all sorts of legalese applies.
- With a tentative ACL of user::rw-, group::r-x, other::r–, group:wheel:rwx, group:guards:rwx, and mask::: (unset), we consult the documentation for
setfacl, assuming the same rules apply to file creation.
There is a clause:
If an ACL contains named user or named group entries, and no mask entry exists, a mask entry containing the same permissions as the group entry is created.
This would set the ACL mask to “r-x”, if the ACL group entry was created from the file directory entry, or “r-x” if the ACL group entry came from the default ACL. (Ether way, for this case, the result is the same.)
There is also a clause:
If a Default ACL contains named user entries or named group entries, and no mask entry exists, a mask entry containing the same permissions as the default Default ACL’s group entry is added. … the permissions of the mask entry are further adjusted to include the union of all permissions affected by the mask entry.
If this rule applies, the the mask will start as “r-x” (same logic) as previous clause), and then it will be adjusted to be the “union of all permissions affected by the mask entry”.
“permissions affected by the mask entry” is not defined in the
setfacl command documentation. The POSIX ACL documentation says:
The mask is the combination of all access permissions of the owning group and all of the user and group entries.
Give the word “union”, which is additive, I would read “combination” to be a logical or-ing. In other words, if any group or user ACLe has “x” permission, the mask will contain “x”.
- By all this logic, the mask value in the OP’s example should be ‘rwx’, no mater which logical path was followed.
The above reasoning must be flawed, as the x for execute does not appear in the mask.
Therefore, there must be some rule about how mask is calculated that has been “hidden” from common documentation sources (or we have found a bug).
My conclusion is that the ‘x’ is always being unconditionally removed, and the documentation is lax.
This change was probably made on the justification of “security” — no file shall be implicitly executable, but must have the executable bit turned on after it is created.