Setting differing ACLs on directories and files

15

9

I want to set up default permissions for a file share so that everyone can rwx all of the directories and so that all newly created files are rw.

Everyone who is accessing this share is in the same group, so this isn't a concern.

I have looked at doing this via ACLs without changing all of the users' umasks and such. Here are my current invocations:

setfacl -Rdm g:mygroup:rwx share_name
setfacl -Rm g:mygroup:rwx share_name

My problem is that while I want all of the newly created sub-directories to be rwx, I only want newly created files to be rw.

Does anyone have a better method to achieve my desired end-result? Is there some way to set ACLs on directories separately from files, in a similar vein to chmod +x vs. chmod +X?

Thanks

durandal

Posted 2010-08-25T14:05:49.233

Reputation: 153

Answers

12

As Gilles points out, setfacl default permissions specify the maximum permissions, basically replacing the umask. So newly created files will be rw unless the application that created the file asked specially for it to be executable.

$ mkdir test
$ touch test/oldfile
$ getfacl test/oldfile
# file: test/oldfile
# owner: myuser
# group: myuser
user::rw-
group::r--
other::r--

$ setfacl -m d:g:mygroup:rwx test
$ touch test/newfile
$ getfacl test/newfile
# file: test/newfile
# owner: myuser
# group: myuser
user::rw-
group::r-x                         #effective:r--
group:mygroup:rwx                  #effective:rw-
mask::rw-
other::r--

Note the effective perms above. (There are only a few programs that will ask to set the execute bit on files that it creates, e.g. gcc for executables and cp if the file being copied was executable.)

Or did you mean that the first setfacl command was working the way you wanted, but the second one wasn't? In other words, you're looking to fix up permissions on the old files, making sure that directories are traversable, without giving other regular files execute permissions?

My version of setfacl allows X exactly like you want, e.g.:

setfacl g:mygroup:rwX

$ setfacl --version
setfacl 2.2.49
$ rm -r test
$ mkdir test
$ mkdir test/olddir
$ touch test/oldfile
$ find test -ls
107513    4 drwxr-xr-x   3 myuser    myuser        4096 Dec 22 01:56 test
107539    0 -rw-r--r--   1 myuser    myuser           0 Dec 22 01:56 test/oldfile
107529    4 drwxr-xr-x   2 myuser    myuser        4096 Dec 22 01:56 test/olddir
$ setfacl -Rm g:somegroup:rwx test
$ find test -ls
107513    4 drwxrwxr-x   3 myuser    myuser        4096 Dec 22 01:56 test
107539    0 -rw-rwxr--   1 myuser    myuser           0 Dec 22 01:56 test/oldfile
107529    4 drwxrwxr-x   2 myuser    myuser        4096 Dec 22 01:56 test/olddir
$ rm -r test
$ mkdir test
$ mkdir test/olddir
$ touch test/oldfile
$ setfacl -Rm g:somegroup:rwX test
$ find test -ls
107513    4 drwxrwxr-x   3 myuser    myuser        4096 Dec 22 01:56 test
107539    0 -rw-rw-r--   1 myuser    myuser           0 Dec 22 01:56 test/oldfile
107529    4 drwxrwxr-x   2 myuser    myuser        4096 Dec 22 01:56 test/olddir

If your version of setfacl doesn't support that, why not use find?

overwrite permissions, setting them to rw for files and rwx for dirs

$ find . \( -type f -exec setfacl -m g:mygroup:rw '{}' ';' \) \
      -o \( -type d -exec setfacl -m g:mygroup:rwx '{}' ';' \)

set mygroup ACL permissions based on existing group permissions

$ find . \( -perm -g+x -exec setfacl -m g:mygroup:rw '{}' ';' \) \
      -o \( -exec setfacl -m g:mygroup:rwx '{}' ';' \)

You'll probably want to check that the group mask provides effective permissions. If not, you'll have to run this too:

$ find . -type d -exec chmod g+rwX '{}' ';'

Mikel

Posted 2010-08-25T14:05:49.233

Reputation: 7 890

4

For future readers, to use setfacl on existing files/folders without adding the executable bit to your files, the solution is this part of @Mikel's answer:

My version of setfacl allows X exactly like you want, e.g.:

setfacl g:mygroup:rwX

Relevant excerpt from the setfacl documentation:

The perms field is a combination of characters that indicate the permissions: read (r), write (w), execute (x), execute only if the file is a directory or already has execute permission for some user (X).

Erik Koopmans

Posted 2010-08-25T14:05:49.233

Reputation: 141

2

As far as I understand Linux ACLs, setfacl -Rdm g:mygroup:rwx share_name does exactly what you want. Experiment:

umask 007
mkdir foo
chgrp mygroup foo
chmod 2700 foo
setfacl -d -m group:mygroup:rwx foo
setfacl -m group:mygroup:rwx foo
touch foo/data
echo '#!/bin/ls' >foo/exec
chmod +x foo/exec

Then as a different user in group mygroup:

$ cat foo/*
#!/bin/ls
#!/bin/ls
$ ./foo/data
ash: ./foo/data: Permission denied
$ ./foo/exec
./foo/exec

What's going on?

$ getfacl foo/data
# file: foo/data
# owner: myuser
# group: mygroup
user::rw-
group::---
group:mygroup:rwx                 #effective:rw-
mask::rw-
other::---

The effective ACL for mygroup is the result of and'ing the ACL_GROUP entry for mygroup (rwx) with the ACL_MASK entry (rw-).

The acl(5) man page explains calculation this under “Access check algorithms”. It doesn't explain how ACL_MASK entries are generated, but in practice the right thing seems to happen.

Gilles 'SO- stop being evil'

Posted 2010-08-25T14:05:49.233

Reputation: 58 319