The `sg_adm` and `sg_mem` fields are not always set in shadow groups,
which can lead to issues with foreign tools like shadow's `sg` command.
Since other NSS implementations properly set these fields and it would
otherwise be impossible to access `administrators` and `members`
information from JSON files, it's bets to always fill these fields.
Even though `sg` is a nice example which should be already installed,
the issue itself can be reproduced with this simple program as well. It
relies on filled `sg_adm` and `sg_mem` fields just like `sg` does:
```
#include <err.h>
#include <gshadow.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
struct sgrp *s;
char **p;
if (argc != 2)
errx(1, "usage: poc group");
s = getsgnam(argv[1]);
printf("name: %s\n", s->sg_namp);
printf("admins:\n");
p = s->sg_adm;
while (*p != NULL) {
printf("- %s\n", *p);
p++;
}
printf("members:\n");
p = s->sg_mem;
while (*p != NULL) {
printf("- %s\n", *p);
p++;
}
}
```
Run it like this: `./poc root`
Proof of Concept (Arch Linux, which uses systemd with systemd-userdbd
and shadow's sg):
```
$ grep systemd /etc/nsswitch.conf
passwd: files systemd
group: files [SUCCESS=merge] systemd
shadow: files systemd
gshadow: files systemd
```
Issue with intrinsic groups:
Run as unprivileged user, who has no access to `/etc/gshadow` to trigger
nss-systemd (strace disables setuid of sg)
```
$ strace sg root
write(2, "sg: list.c:169: is_on_list: Asse"..., 61sg: list.c:169: is_on_list: Assertion `NULL != list' failed.
) = 61
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa7e9c0c000
gettid() = 1882
getpid() = 1882
tgkill(1882, 1882, SIGABRT) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=1882, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++
Aborted (core dumped) strace sg root
```
Issue with groups through systemd-userdbd:
1. Create a custom group (as root)
```
cat > /etc/userdb/sg-poc.group << EOF
{
"groupName": "sg-poc",
"gid": 6123,
"administrators": [
"root"
],
"members": [
"bin"
]
}
EOF
ln -s sg-poc.group /etc/userdb/6123.group
```
2. Verify that group actually exists
```
$ userdbctl group sg-poc
Group name: sg-poc
Disposition: regular
GID: 6123
Admins: root
Service: io.systemd.NameServiceSwitch
```
3. Run `sg` to switch into group `sg-poc` as regular user, this time
with setuid, i.e. no strace as before
```
$ sg sg-poc
sg: list.c:169: is_on_list: Assertion `NULL != list' failed.
Aborted (core dumped) sg sg-poc
```