mirror of
https://github.com/troglobit/finit.git
synced 2026-09-30 13:02:37 +07:00
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:
+16
-1
@@ -116,10 +116,25 @@ Non-privileged Services
|
||||
|
||||
Every `run`, `task`, or `service` can also list the privileges the
|
||||
`/path/to/cmd` should be executed with. Prefix the command with
|
||||
`@USR[:GRP]`, group is optional, like this:
|
||||
`@USR[:GRP[,SUPP,...]]`, where group and supplementary groups are
|
||||
optional, like this:
|
||||
|
||||
run [2345] @joe:users logger "Hello world"
|
||||
|
||||
Finit reads the user's supplementary group membership from `/etc/group`
|
||||
automatically. Any groups the user belongs to will be inherited by
|
||||
the service.
|
||||
|
||||
To specify additional supplementary groups beyond those in `/etc/group`,
|
||||
append them after the primary group, separated by commas:
|
||||
|
||||
service @caddy:caddy,ssl-cert /usr/bin/caddy run
|
||||
|
||||
This runs the `caddy` service as user `caddy`, with primary group
|
||||
`caddy`, inheriting any groups `caddy` is a member of in `/etc/group`,
|
||||
plus the additional `ssl-cert` group. This is useful when a service
|
||||
needs access to resources owned by groups not listed in `/etc/group`.
|
||||
|
||||
For multiple instances of the same command, e.g. a DHCP client or
|
||||
multiple web servers, add `:ID` somewhere between the `run`, `task`,
|
||||
`service` keyword and the command, like this:
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -101,6 +101,7 @@ typedef enum {
|
||||
#define MAX_STR_LEN 64
|
||||
#define MAX_COND_LEN (MAX_ARG_LEN * 3)
|
||||
#define MAX_USER_LEN 16
|
||||
#define MAX_NUM_SUPGROUPS 4
|
||||
#define MAX_NUM_FDS 64 /* Max number of I/O plugins */
|
||||
#define MAX_NUM_SVC_ARGS 64
|
||||
|
||||
@@ -191,6 +192,8 @@ typedef struct svc {
|
||||
/* Identity */
|
||||
char username[MAX_USER_LEN];
|
||||
char group[MAX_USER_LEN];
|
||||
char supgroups[MAX_NUM_SUPGROUPS][MAX_USER_LEN];
|
||||
int num_supgroups;
|
||||
char capabilities[MAX_CMD_LEN];
|
||||
|
||||
/* Command, arguments and service description */
|
||||
|
||||
Reference in New Issue
Block a user