176

Suppose I have two users Alice and Bob and a group GROUPNAME and a folder foo, both users are members of GROUPNAME (using Linux and ext3).

If I save as user Alice a file under foo, the permissions are: -rw-r--r-- Alice Alice. However, is it possible to achieve that every file saved under some subdirectory of foo has permissions -rwxrwx--- Alice GROUPNAME (i.e. owner Alice, group GROUPNAME)?

student
  • 18,305

3 Answers3

148

If at all possible, use access control lists (ACL).

Under Linux, make sure that the filesystem you're using supports ACLs (most unix filesystems do). You may need to change the mount options to enable ACLs: with ext2/ext3/ext4, the kernel default since 2.6.39 is to enable ACLs. On older kernels you may to need to specify the acl mount option explicitly, so the entry in /etc/fstab should look like /dev/sda1 / ext4 errors=remount-ro,acl 0 1. Run mount -o remount,acl / to activate ACLs without rebooting. Also install the ACL command line tools getfacl and setfacl, typically provided in a package called acl.

Now that the one-time setup is over, change the directory's ACL to give the group write permissions and to make these permissions inherited by newly created files. Under Linux:

setfacl -d -m group:GROUPNAME:rwx /path/to/directory
setfacl -m group:GROUPNAME:rwx /path/to/directory

If ACLs are not an option, make the directory owned by the group GROUPNAME, and set its permissions to 2775 or 2770: chmod g+rwxs /path/to/directory. The s here means the setgid bit; for a directory, it means that files created in this directory will belong to the group that owns the directory.

You'll also need to set Alice and Bob's umask to make all their files group-writable by default. The default umask on most systems is 022, meaning that files can have all permissions except write by group and other. Change that to 002, meaning to forbid only write-by-other permission. You would typically put that setting in your ~/.profile:

umask 002    # or 007 to have files not readable by others
muru
  • 72,889
  • 9
    +1 - Very thorough answer. I never knew one could remount / on-the-fly. Good to know. – boehj May 08 '11 at 19:56
  • 1
    Thie setfacl -d command does not work for me because the files contained within that directory have an r-- mask that negates any write permissions. Would love some help. See http://unix.stackexchange.com/questions/71743/using-setfacl-to-allow-group-members-to-write-to-any-file-in-a-directory – Ben McCann Apr 08 '13 at 22:26
  • 1
    Nice answer, but after following all these steps, it seems that when I untar a file, it inherits the permissions of the file as it was inside the .tar file. So I end up with something that works for normal usage, but as soon as someone extracts a .tar file, no one else can edit anything inside it. Do you know if there is anything I can do about that? – mpontillo Jun 05 '14 at 22:20
  • Q1. Are you sure you should add acl as an option in mount command when you have it added in /etc/fstab? I think it's redundant and especially because when you run the mount command in your answer (i.e. mount -o remount,acl /), you'll get an output like this: /dev/vda1 on / type ext4 (rw,errors=remount-ro,acl,acl) (see acl,acl in the end). Is that okay? Please correct it if I am not wrong. – its_me Jun 18 '14 at 21:04
  • Q2. You said, "Now that the one-time setup is over, change the directory's ACL to give the group write permissions and to make these permissions inherited by newly created files." But you've got the order of the commands wrong, haven't you? i.e. the one with the -d option should come next as it's the command that sets permissions for the newly created files. Right? – its_me Jun 18 '14 at 21:05
  • 3
    @its_me Q1: I show a mount command with the remount option, so it doesn't use fstab. Having acl twice means that the filesystem was mounted with the acl option already, and it harmless. acl is the default for ext4 in recent kernels, by the way (the patch was still brand new back when I wrote this answer). Q2: You can run the commands in either order. – Gilles 'SO- stop being evil' Jun 18 '14 at 21:30
  • Q2: I understand that the commands can be run in either order. But was I correct about the ordering w.r.t what they do? (Thanks for the clarification.) – its_me Jun 18 '14 at 21:37
  • @Mike I think I see what's happening: the ACL is present, but the mask is set to e.g. r-- for a 644 file which kills a w bit in a group entry. Hmmm. I would have thought that adding a default:mask rwx entry on the directory would solve this (see Ben's question), but it doesn't, I don't understand why. – Gilles 'SO- stop being evil' Jun 18 '14 at 21:39
  • 1
    @its_me Yes, your understanding is correct, it's just that it doesn't matter in what order you add the entries – Gilles 'SO- stop being evil' Jun 18 '14 at 21:39
  • @Gilles wrt acl being the default for ext4 in recent kernels, that's true for the standard system-installed mount points but not for partitions added manually post-install. Those still need an explicit "acl" option in fstab. wrt the default:mask:rwx not overriding an existing mask:r--, the default mask only applies to the creation of new files and directories. One of two things can be done: set the mask (not default mask) with setfacl -m m:rwx [file] or touch a group permission: chmod g+rwx or setfacl -m g::rwx. That will force a recalculation of the mask to not interfere. – Binary Phile Sep 25 '15 at 18:47
  • 1
    Also, setfacl -d -m group:G:rwx /path/to/directory setfacl -m group:G:rwx /path/to/directory can be shortened to: setfacl -m d:g:G:rwx,g:G:rwx /path/to directory. I usually default the mask as well a la: setfacl -m d:g:G:rwx,g:G:rwx,d:m:rwx. – Binary Phile Sep 25 '15 at 18:54
  • all these commands give me this error: setfacl: Option -m: Invalid argument near character 1, using ubuntu 16.04LTS – knocte Aug 06 '16 at 07:46
  • 1
    @knocte You must have made a mistake when copying them. I've just checked, and no, there is no strange bug that makes them fail on Ubuntu 16.04. You need to replace G by a valid group name, but if you forget to do that, you get an error message referring to character 7, not character 1. – Gilles 'SO- stop being evil' Aug 16 '16 at 17:18
  • 8
    you should improve the answer then to use GROUPNAME instead of G, to make it more clear – knocte Aug 16 '16 at 18:28
  • 1
    @mopsled Please don't edit an answer is a way that doesn't match the question. GROUPNAME may be clearer than G, but if you make that edit, you need to edit the question and the other answers to match. – Gilles 'SO- stop being evil' Aug 15 '19 at 10:21
  • @Gilles My mistake, thank you for cleaning up the question and other answers. – mopsled Aug 16 '19 at 02:58
  • Group inheriting will only work for newly created or copied files in a setgid dir, but not for files or dirs moved into the setgid dir. Why is that? This is making me crazy. – red-o-alf Feb 12 '24 at 04:35
  • 1
    @red-o-alf mv preserves all the attributes of the moved file, because it moves the file with all of its metadata. It's a limitation of the Unix group approach to permissions: it only has settings on each file, it doesn't have an “inherit” setting that would be preserved when moving. The semantics of mv foo bar/ with respect to permissions is “keep the original access permissions of foo”, not “adapt foo to a new permissions context”. – Gilles 'SO- stop being evil' Feb 12 '24 at 10:43
  • @Gilles'SO-stopbeingevil' thanks, now I understand the reason why natively it works that way. But after decades of Unix systems I still can't see how some additional standard software interface was not built to allow for moved files , unzipped files, downloaded files, and so on, to work in a consistent way with regards to the acquisition of permissions., should a sys admin decide so. It would slow down the system operation? OK! Deal! It's all about pros and cons... We've been dealing for ages with incredibly slow DB solutions, and not setgid? -WAIT!- a DB is probably what I'm looking for !?! – red-o-alf Feb 12 '24 at 17:26
125

You can control the assigned permission bits with umask, and the group by making the directory setgid to GROUPNAME.

$ umask 002            # allow group write; everyone must do this
$ chgrp GROUPNAME .    # set directory group to GROUPNAME
$ chmod g+s .          # files created in directory will be in group GROUPNAME

Note that you have to do the chgrp/chmod for every subdirectory; it doesn't propagate automatically for existing directories. On OS X, subsequently created directories under a setgid directory will be setgid, although the latter will be in group GROUPNAME. On most Linux distros, the setgid bit will propagate to new subdirectories.

Also note that umask is a process attribute and applies to all files created by that process and its children (which inherit the umask in effect in their parent at fork() time). Users may need to set this in ~/.profile, and may need to watch out for things unrelated to your directory that need different permissions. modules may be useful if you need different settings when doing different things.

You can control things a bit better if you can use POSIX ACLs; it should be possible to specify both a permissions mask and a group, and have them propagate sensibly. Support for POSIX ACLs is somewhat variable, though.

geekosaur
  • 32,047
  • 14
    Subdirectories created after setting setgid on the parent directory will have setgid set automatically. – Arrowmaster May 08 '11 at 21:14
  • 2
    @Arrowmaster: On some systems, perhaps, but not all; I tested on OSX and it doesn't propagate, at least for non-root. – geekosaur May 08 '11 at 21:16
  • 3
    Well on Debian (and I assume most other Linux distros) the setgid and group name both propagate. – Arrowmaster May 08 '11 at 21:19
  • 3
    On OS X, the setgid bit on a directory is just ignored; new files and directories are always given the group of their containing directory. – John Flatness May 09 '11 at 01:52
  • 1
    Is it also possible that files copied or moved to foo (using cp resp. mv) gain the desired permissions automatically (-rwxrwx--- A G)? – student May 10 '11 at 20:15
  • If your OS doesn't support ACLs, or your file system can't be configured to use ACLs, then this is a good answer. However if you can use ACLs, that is a better approach. See the answer from @Gilles below. – Chris Johnson Jun 03 '14 at 10:44
  • Note that you have to do the chgrp/chmod for every subdirectory; it doesn't propagate automatically — is there a reason why the -R flag can't fix this? Or is that flag non-portable? – Mark K Cowan Apr 28 '17 at 16:26
  • I have made it, and test, it works! But this doesn't help a lot in my case as new folders are creating with drwxrwxr-x BUT files with -rw-r--r-- and it is not writeable for users in the same group. – fdrv Nov 01 '17 at 01:12
  • @fdrv Remember to run umask 002 for each new shell, or put it into .bashrc or /etc/profile to make it permanent. – David Harkness Jan 17 '18 at 22:13
28

This question is a good fit for linux acl. Since you don't state your OS, I'll assume Linux in what follows. Here is an example session.

I don't know of a really good acl tutorial, but you could do worse than "Using ACLs with Fedora Core 2 (Linux Kernel 2.6.5)" by Van Emery.

Note that the default acl behaves like a local umask. Since at least in Linux, umasks are applied globally, this is the only way I know to get the effect of a local umask. For some reason this a little known feature. The net is littered with people asking about a local umask override, but almost nobody seems to think of using acl.

Also note that you need to mount the partition you are working in with acl support, eg.

/dev/mapper/debian-acl /mnt/acl        ext3    defaults,acl        0       2

Session follows:

/mnt/acl$ mkdir foo
/mnt/acl$ getfacl foo
# file: foo
# owner: faheem
# group: faheem
user::rwx
group::r-x
other::r-x

Set the group of foo to be staff, and set the acl of group and user of foo to rwx.

/mnt/acl$ chgrp staff foo
/mnt/acl$ setfacl -R -m u::rwx,g::rwx foo
/mnt/acl$ getfacl foo
# file: foo
# owner: faheem
# group: staff
user::rwx
group::rwx
other::r-x

Set default acls of user and group to rwx as well. This defines permissions that files and directories inherit from foo. So all files and directories created under foo will have group permissions rw.

/mnt/acl$ setfacl -d --set u::rwx,g::rwx,o::- foo
/mnt/acl$ getfacl foo
# file: foo
# owner: faheem
# group: staff
user::rwx
group::rwx
other::r-x
default:user::rwx
default:group::rwx
default:other::---

Now create some files in foo as users faheem and john.

/mnt/acl$ cd foo
/mnt/acl/foo$ touch bar

switch to user john for this next command.

/mnt/acl/foo$ touch baz

List files. Notice that both files owned by faheem and files owned by john are created with group permissions rw.

/mnt/acl/foo$ ls -la
total 3
drwxrwxr-x+ 2 faheem staff  1024 May  9 01:22 .
drwxr-xr-x  4 faheem faheem 1024 May  9 01:20 ..
-rw-rw----  1 faheem faheem    0 May  9 01:20 bar
-rw-rw----  1 john   john      0 May  9 01:22 baz
Faheem Mitha
  • 35,108