Linux – Why the supplementary groups of “bash” also contains the primary group

grouplinuxprocess

Based on my understanding, when bash (or any process as long as I don't intentionally change this behavior) runs, it will have (along with other information) a list of the supplementary groups for the logged in user.

The following is the ps result for the supplementary groups of bash:

PID    COMMAND    SUPGRP
1409   bash       adm dialout cdrom plugdev lpadmin admin sambashare chris

chris is the primary group for the logged in user, so why is it listed as part of the supplementary groups?

Best Answer

initgroup(), the libc function that is typically called by login applications to set supplementary group list of the process it runs in your name does add the primary group id to that list.

If it didn't, that would be a security issue, as that would give you a way to relinquish access to that group by creating a setgid executable with one of your other groups, and execute that to lose your primary gid (that executable would have to call setgid() for the real gid to also change), which would give you access to resources that have been explicitly denied access to your primary group for instance.

Example:

$ ls -l file
-rw----r-- 1 root chazelas 7 Dec 12 15:33 file

Access has been denied to my primary gid:

$ cat file
cat: file: Permission denied

Now, let's start a shell as me where the supplementary group ids doesn't include that group to see what we could do if login didn't add that group to our supplementary group id list:

$ sudo perl -le '$( = $) =  "1000 2"; $< = $> = 1000; exec zsh'
$ ps -o rgroup,egroup,supgrp -p $$
RGROUP   EGROUP   SUPGRP
chazelas chazelas bin
$ id -a
uid=1000(chazelas) gid=1000(chazelas) groups=1000(chazelas),2(bin)

1000 is in gid, egid, but not the supplementary group list. As I'm also a member of bin, I can create a setgid bin executable:

$ cp -f /usr/bin/env .
$ chgrp bin env
$ chmod g+s env
$ ./env perl -U -le '$( = $); exec qw(/usr/bin/id -a)'
uid=1000(chazelas) gid=2(bin) groups=2(bin)

I'm using perl to call setgid() ($( = $)). And then I've lost membership of the chazelas group. So:

$ ./env perl -U -le '$( = $); exec qw(cat file)'
secret

By adding the group to the supplementary list, login makes sure you can't get out of it (as only root can change that list and it's not affected by the execution of setgid executables).

Related Question