Add support for supplementary groups

Implement supplementary group support for services, allowing them to
access resources owned by multiple groups. Uses the @user:group,sup1,sup2
syntax to explicitly specify supplementary groups, in addition to now
reading group membership from /etc/group.
This commit is contained in:
Aaron Andersen committed 2025-12-24 09:54:37 -05:00
1 parent 702a606d26
commit b46592e818
3 files changed
+78 -1

No files matched your search

+59
View File
@@ -25,6 +25,7 @@
#include "config.h" /* Generated by configure script */
#include <ctype.h> /* isblank() */
#include <grp.h> /* setgroups() */
#include <sched.h> /* sched_yield() */
#include <string.h>
#include <sys/reboot.h>
@@ -560,6 +561,42 @@ static pid_t service_fork(svc_t *svc)
svc_ident(svc, NULL, 0), rlim2str(i));
}
#ifndef ENABLE_STATIC
/* Set supplementary groups from /etc/group and config */
{
gid_t supgids[NGROUPS_MAX];
int ngroups = NGROUPS_MAX;
int i, j, n = 0;
/* Get user's supplementary groups from /etc/group */
if (uid >= 0 && getgrouplist(svc->username, gid >= 0 ? gid : 0, supgids, &ngroups) >= 0)
n = ngroups;
/* Add explicitly configured supplementary groups */
for (i = 0; i < svc->num_supgroups && n < NGROUPS_MAX; i++) {
int g = getgroup(svc->supgroups[i]);
int found = 0;
if (g < 0) {
warn("%s: unknown supplementary group '%s'",
svc_ident(svc, NULL, 0), svc->supgroups[i]);
continue;
}
/* Skip if already in list from /etc/group */
for (j = 0; j < n; j++) {
if (supgids[j] == (gid_t)g) {
found = 1;
break;
}
}
if (!found)
supgids[n++] = g;
}
if (n > 0 && setgroups(n, supgids))
err(1, "%s: failed setgroups()", svc_ident(svc, NULL, 0));
}
#endif
/* Set desired user+group */
if (gid >= 0) {
if (setgid(gid))
@@ -1957,7 +1994,29 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
char *ptr = strchr(username, ':');
if (ptr) {
char *sup;
*ptr++ = 0;
/* Check for supplementary groups: group,sup1,sup2,... */
sup = strchr(ptr, ',');
if (sup) {
*sup++ = 0;
svc->num_supgroups = 0;
while (sup) {
char *next = strchr(sup, ',');
if (next)
*next++ = 0;
if (svc->num_supgroups >= MAX_NUM_SUPGROUPS) {
warn("%s: too many supplementary groups, max %d",
svc->cmd, MAX_NUM_SUPGROUPS);
break;
}
strlcpy(svc->supgroups[svc->num_supgroups], sup,
sizeof(svc->supgroups[0]));
svc->num_supgroups++;
sup = next;
}
}
strlcpy(svc->group, ptr, sizeof(svc->group));
}
strlcpy(svc->username, username, sizeof(svc->username));