From: Zbigniew Jędrzejewski-Szmek Date: Thu, 21 May 2026 07:55:56 +0000 (+0200) Subject: user-util: add getgrouplist_malloc and initgroups_wrapper X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5c2bd19f40577873b68f645a2cd22431aa677786;p=thirdparty%2Fsystemd.git user-util: add getgrouplist_malloc and initgroups_wrapper --- diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 5c7f783f5ce..fe4c0e6a368 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -1445,6 +1445,50 @@ ssize_t lookup_groups_in_files( return n_arr; } +int getgrouplist_malloc(const char *user, gid_t gid, gid_t **ret) { +#if BUILD_STATIC + return lookup_groups_in_files(GROUP_FILES, user, gid, ret); +#else + int ngroups_max = sysconf_ngroups_max(); + if (ngroups_max < 0) + return ngroups_max; + + _cleanup_free_ gid_t *gids = new(gid_t, ngroups_max); + if (!gids) + return -ENOMEM; + + int k = ngroups_max; + if (getgrouplist(user, gid, gids, &k) < 0) + return -EIO; /* getgrouplist does not set errno */ + + if (ret) + *ret = TAKE_PTR(gids); + return k; +#endif +} + +int initgroups_wrapper(const char *user, gid_t gid) { +#if BUILD_STATIC + _cleanup_free_ gid_t *groups = NULL; + int r, n_groups; + + n_groups = getgrouplist_malloc(user, gid, &groups); + if (n_groups <= 0) + return n_groups; + + /* Try to set the maximum number of groups the kernel can handle. This is what glibc does. */ + for (; n_groups > 0; n_groups--) { + r = RET_NERRNO(setgroups(n_groups, groups)); + if (r != -EINVAL) + break; + } + + return r; +#else + return RET_NERRNO(initgroups(user, gid)); +#endif +} + #if !BUILD_STATIC static size_t getgr_buffer_size(void) { diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 6f90c8c4530..ab9222c5003 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -189,11 +189,14 @@ int lookup_grent_in_files( const char *name, gid_t gid, struct group **ret); + ssize_t lookup_groups_in_files( char * const *files, const char *name, gid_t gid, gid_t **ret); +int getgrouplist_malloc(const char *user, gid_t gid, gid_t **ret); +int initgroups_wrapper(const char *user, gid_t gid); int getpwuid_malloc(uid_t uid, struct passwd **ret); int getpwnam_malloc(const char *name, struct passwd **ret);