mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-02 01:45:17 +00:00
util: add virGetGroupList
https://bugzilla.redhat.com/show_bug.cgi?id=964358 Since neither getpwuid_r() nor initgroups() are safe to call in between fork and exec (they obtain a mutex, but if some other thread in the parent also held the mutex at the time of the fork, the child will deadlock), we have to split out the functionality that is unsafe. At least glibc's initgroups() uses getgrouplist under the hood, so the ideal split is to expose getgrouplist for use before a fork. Gnulib already gives us a nice wrapper via mgetgroups; we wrap it once more to look up by uid instead of name. * bootstrap.conf (gnulib_modules): Add mgetgroups. * src/util/virutil.h (virGetGroupList): New declaration. * src/util/virutil.c (virGetGroupList): New function. * src/libvirt_private.syms (virutil.h): Export it. Signed-off-by: Eric Blake <eblake@redhat.com> (cherry picked from commit 75c125641ac73473ba4b0542524d67a184769c8e)
This commit is contained in:
parent
eae6310649
commit
c3c8689e7f
@ -71,6 +71,7 @@ listen
|
||||
localeconv
|
||||
maintainer-makefile
|
||||
manywarnings
|
||||
mgetgroups
|
||||
mkdtemp
|
||||
mkostemp
|
||||
mkostemps
|
||||
|
@ -2003,6 +2003,7 @@ virGetDeviceID;
|
||||
virGetDeviceUnprivSGIO;
|
||||
virGetFCHostNameByWWN;
|
||||
virGetGroupID;
|
||||
virGetGroupList;
|
||||
virGetGroupName;
|
||||
virGetHostname;
|
||||
virGetUnprivSGIOSysfsPath;
|
||||
|
@ -67,6 +67,7 @@
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "mgetgroups.h"
|
||||
#include "virerror.h"
|
||||
#include "virlog.h"
|
||||
#include "virbuffer.h"
|
||||
@ -999,6 +1000,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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user