diff --git a/bootstrap.conf b/bootstrap.conf index 410e4f5dc4..1c59c22c35 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -71,6 +71,7 @@ listen localeconv maintainer-makefile manywarnings +mgetgroups mkdtemp mkostemp mkostemps diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 59583ec7e2..e56c7a9b29 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2002,6 +2002,7 @@ virGetDeviceID; virGetDeviceUnprivSGIO; virGetFCHostNameByWWN; virGetGroupID; +virGetGroupList; virGetGroupName; virGetHostname; virGetUnprivSGIOSysfsPath; diff --git a/src/util/virutil.c b/src/util/virutil.c index d7e61db37f..136ff25652 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -67,6 +67,7 @@ #endif #include "c-ctype.h" +#include "mgetgroups.h" #include "virerror.h" #include "virlog.h" #include "virbuffer.h" @@ -970,6 +971,35 @@ virGetGroupID(const char *group, gid_t *gid) return 0; } + +/* Compute the list of supplementary groups associated with @uid, and + * including @gid in the list (unless it is -1), storing a malloc'd + * result into @list. Return the size of the list on success, or -1 + * on failure with error reported and errno set. May not be called + * between fork and exec. */ +int +virGetGroupList(uid_t uid, gid_t gid, gid_t **list) +{ + int ret = -1; + char *user = NULL; + + *list = NULL; + if (uid == (uid_t)-1) + return 0; + + if (virGetUserEnt(uid, &user, + gid == (gid_t)-1 ? &gid : NULL, NULL) < 0) + return -1; + + ret = mgetgroups(user, gid, list); + if (ret < 0) + virReportSystemError(errno, + _("cannot get group list for '%s'"), user); + VIR_FREE(user); + return ret; +} + + /* Set the real and effective uid and gid to the given values, and call * initgroups so that the process has all the assumed group membership of * that uid. return 0 on success, -1 on failure (the original system error diff --git a/src/util/virutil.h b/src/util/virutil.h index 280a18dc6e..6480b073e8 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -115,6 +115,8 @@ char *virGetUserCacheDirectory(void); char *virGetUserRuntimeDirectory(void); char *virGetUserName(uid_t uid); char *virGetGroupName(gid_t gid); +int virGetGroupList(uid_t uid, gid_t group, gid_t **groups) + ATTRIBUTE_NONNULL(3); int virGetUserID(const char *name, uid_t *uid) ATTRIBUTE_RETURN_CHECK; int virGetGroupID(const char *name,