I have some ACLs defined on a directory as so:
# owner: root
# group: root
user::rwx
group::r--
mask::r-x
other::r--
default:user::r--
default:group::r--
default:mask::r-x
default:other::r--
I would like any new files created in that folder to be u:apache:r-- and any new directories to be u:apache:r-x. How do I specify that intent using ACLs?
I've tried the -dm u:apache:rX
and it doesn't seem to do anything different compared to just rx
overt htdocs # getfacl .
# file: .
# owner: root
# group: root
user::rwx
user:apache:r--
group::r--
mask::r-x
other::r--
default:user::r--
default:user:apache:r--
default:group::r--
default:mask::r--
default:other::r--
overt htdocs # setfacl -dm u:apache:rx .
overt htdocs # touch blah.txt
overt htdocs # getfacl blah.txt
# file: blah.txt
# owner: root
# group: root
user::r--
user:apache:r-x #effective:r--
group::r--
mask::r--
other::r--
overt htdocs # rm blah.txt
overt htdocs # setfacl -dm u:apache:rX .
overt htdocs # touch blah.txt
overt htdocs # getfacl blah.txt
# file: blah.txt
# owner: root
# group: root
user::r--
user:apache:r-x #effective:r--
group::r--
mask::r--
other::r--
The capital X permission only seems to be useful for setting current permissions, not for setting default permissions:
overt htdocs # setfacl -x u:apache blah.txt
overt htdocs # getfacl blah.txt
# file: blah.txt
# owner: root
# group: root
user::r--
group::r--
mask::r--
other::r--
overt htdocs # setfacl -m u:apache:rX blah.txt
overt htdocs # getfacl blah.txt
# file: blah.txt
# owner: root
# group: root
user::r--
user:apache:r--
group::r--
mask::r--
other::r--
Well, but your example does exactly what you want ;)
Look at the second one:
The important line is:
user:apache:r-x #effective:r--
Even though acl is set to r-x it is effectively r-- for files. It is because of the mask.
And the mask will be always only rw- for files if the user created it with the rw- permissions for user. (I'm not 100% sure but mask cannot be less restrictive then the basic permissions).
So effectively you get r-- for files and r-x for directories.
Because created directories will have user:r-x -> mask will be r-x -> effective permission will be r-x.
For files: they will have r-- so mask will be r-- and effective permissions for ACLs will be r--, too. (If you create a file and give it a user::r-x permissions, then mask will be modified and users form acl's will get the x, too)
Unfortunately, there is just no way to do this with Linux ACL's. It's true that the mask will appear to do exactly what you want, as far as effective permissions. But next time you do an operation that recalculates the rights mask, bam, all your files will be made executable.
You might as well just resign yourself to expect all files in an ACL to be executable. That's really just a convenience rather than a security feature, and as long as you don't put those folders in your $PATH, should not be an issue. If it still bothers you, the only choice is to put your ACL controlled folders on a file system mounted with no execute option.
-d (or --default) is used to set the defaults on the directory so that things created in it inherit the perms (as you seem to be doing).
Here is a quick overview. http://www.vanemery.com/Linux/ACL/linux-acl.html#default
It is not possible to have files have one default and dirs have a different default.
You could run a script out of cron that does a setfacl on all the dirs every minute - though that is less then ideal of a solution.
find /path/to/top/dir -type d -exec setfacl -dm u:apache:rx {} \;
or
find /path/to/top/dir -type d |xargs setfacl -dm u:apache:rx
This post on ACLs and Masks really helped me to understand how to do what I wanted, and why.
The missing part of my understanding was that when creating a file the kernel uses a default permission set of 0666 and for new directories 0777. So by default directories will have the execute (traverse) bit set.
The ACL mask is basically a way to set a
umask
on an directory/file/user level.