From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Jul 2026 17:49:16 +0000 (+0200) Subject: core: convert exec-invoke to use the new static-friendly functions X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b0dfec9fa498a056b6f0cd0639f76931e2ff654a;p=thirdparty%2Fsystemd.git core: convert exec-invoke to use the new static-friendly functions The libc API is rather ugly: it requires the caller to pass an array of the maximum possible size (or to repeatedly query the group list to discover the actual size). With our "static-friendly" helpers, we reallocate the array on the fly. --- diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 00378903074..7a7f7f2a709 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -890,7 +890,7 @@ static int get_supplementary_groups( assert(ret_gids); /* - * If user is given, then lookup GID and supplementary groups list. + * If user is given, then look up GID and supplementary groups list. * We avoid NSS lookups for gid=0. Also we have to initialize groups * here and as early as possible so we keep the list of supplementary * groups of the caller. @@ -898,15 +898,16 @@ static int get_supplementary_groups( bool keep_groups = false; if (user && gid_is_valid(gid) && gid != 0) { /* First step, initialize groups from /etc/groups */ - if (initgroups(user, gid) < 0) { + r = initgroups_wrapper(user, gid); + if (r < 0) { /* If our primary gid is already the one specified in Group= (i.e. we're running in * user mode), gracefully handle the case where we have no privilege to re-initgroups(). * * Note that group memberships of the current user might have been modified, but * the change will only take effect after re-login. It's better to continue on with * existing credentials rather than erroring out. */ - if (!ERRNO_IS_PRIVILEGE(errno) || gid != getgid()) - return -errno; + if (!ERRNO_IS_PRIVILEGE(r) || gid != getgid()) + return r; } keep_groups = true; @@ -917,29 +918,30 @@ static int get_supplementary_groups( return 0; } - int ngroups_max = sysconf_ngroups_max(); - if (ngroups_max < 0) - return ngroups_max; - - _cleanup_free_ gid_t *l_gids = new(gid_t, ngroups_max); - if (!l_gids) - return -ENOMEM; + /* If SupplementaryGroups= was passed then NGROUPS_MAX has to be positive, otherwise fail. */ + _cleanup_free_ gid_t *l_gids = NULL; int k = 0; if (keep_groups) { - /* - * Lookup the list of groups that the user belongs to, we - * avoid NSS lookups here too for gid=0. - */ - k = ngroups_max; - if (getgrouplist(user, gid, l_gids, &k) < 0) - return -EINVAL; + /* Look up the list of groups that the user belongs to. + * We avoid NSS lookups here too for gid=0. */ + + k = getgrouplist_malloc(user, gid, &l_gids); + if (k < 0) + return k; } + int ngroups_max = sysconf_ngroups_max(); + if (ngroups_max < 0) + return ngroups_max; + STRV_FOREACH(i, c->supplementary_groups) { if (k >= ngroups_max) return -E2BIG; + if (!GREEDY_REALLOC(l_gids, k + 1)) + return -ENOMEM; + r = get_group_creds(*i, /* flags= */ 0, /* ret_name= */ NULL, l_gids + k); if (r < 0) return r; @@ -952,12 +954,11 @@ static int get_supplementary_groups( return 0; } - /* Otherwise get the final list of supplementary groups */ - gid_t *groups = newdup(gid_t, l_gids, k); - if (!groups) - return -ENOMEM; + /* We *could* trim the array size with realloc(3), but right now the only caller frees the array + * quickly anyway, so this is not worth the trouble. If other users pop up, this should be + * reconsidered. */ - *ret_gids = groups; + *ret_gids = TAKE_PTR(l_gids); return k; }