From 5c2bd19f40577873b68f645a2cd22431aa677786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 21 May 2026 09:55:56 +0200 Subject: [PATCH] user-util: add getgrouplist_malloc and initgroups_wrapper --- src/basic/user-util.c | 44 +++++++++++++++++++++++++++++++++++++++++++ src/basic/user-util.h | 3 +++ 2 files changed, 47 insertions(+) diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 5c7f783f5c..fe4c0e6a36 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 6f90c8c453..ab9222c500 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);