Use getgrouplist_2() on macOS if available.

This commit is contained in:
Todd C. Miller
2016-12-13 10:39:32 -07:00
parent 56cc9aa02d
commit ae76e1a229
5 changed files with 30 additions and 0 deletions

View File

@@ -95,6 +95,10 @@
don't. */ don't. */
#undef HAVE_DECL_GETDOMAINNAME #undef HAVE_DECL_GETDOMAINNAME
/* Define to 1 if you have the declaration of `getgrouplist_2', and to 0 if
you don't. */
#undef HAVE_DECL_GETGROUPLIST_2
/* Define to 1 if you have the declaration of `getresuid', and to 0 if you /* Define to 1 if you have the declaration of `getresuid', and to 0 if you
don't. */ don't. */
#undef HAVE_DECL_GETRESUID #undef HAVE_DECL_GETRESUID
@@ -267,6 +271,9 @@
/* Define to 1 if you have the `getgrouplist' function. */ /* Define to 1 if you have the `getgrouplist' function. */
#undef HAVE_GETGROUPLIST #undef HAVE_GETGROUPLIST
/* Define to 1 if you have the `getgrouplist_2' function. */
#undef HAVE_GETGROUPLIST_2
/* Define to 1 if your system has a working `getgroups' function. */ /* Define to 1 if your system has a working `getgroups' function. */
#undef HAVE_GETGROUPS #undef HAVE_GETGROUPS

View File

@@ -2111,6 +2111,9 @@ case "$host" in
fi fi
RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES" RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
# Undocumented API that dynamically allocates the groups.
AC_CHECK_FUNCS([getgrouplist_2], [AC_CHECK_DECLS([getgrouplist_2])])
# We need to force a flat namespace to make libc # We need to force a flat namespace to make libc
# symbol hooking work like it does on ELF. # symbol hooking work like it does on ELF.
AX_CHECK_LINK_FLAG([-Wl,-force_flat_namespace], [AX_APPEND_FLAG([-Wl,-force_flat_namespace], [SUDO_LDFLAGS])]) AX_CHECK_LINK_FLAG([-Wl,-force_flat_namespace], [AX_APPEND_FLAG([-Wl,-force_flat_namespace], [SUDO_LDFLAGS])])

View File

@@ -392,6 +392,9 @@ __dso_public int sudo_getgrouplist(const char *name, gid_t basegid, gid_t *group
# undef getgrouplist # undef getgrouplist
# define getgrouplist(_a, _b, _c, _d) sudo_getgrouplist((_a), (_b), (_c), (_d)) # define getgrouplist(_a, _b, _c, _d) sudo_getgrouplist((_a), (_b), (_c), (_d))
#endif /* GETGROUPLIST */ #endif /* GETGROUPLIST */
#if defined(HAVE_GETGROUPLIST_2) && !defined(HAVE_DECL_GETGROUPLIST_2)
int getgrouplist_2(const char *name, gid_t basegid, gid_t **groups);
#endif /* HAVE_GETGROUPLIST_2 && !HAVE_DECL_GETGROUPLIST_2 */
#ifndef HAVE_GETLINE #ifndef HAVE_GETLINE
__dso_public ssize_t sudo_getline(char **bufp, size_t *bufsizep, FILE *fp); __dso_public ssize_t sudo_getline(char **bufp, size_t *bufsizep, FILE *fp);
# undef getline # undef getline

View File

@@ -256,6 +256,14 @@ sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1)
} }
(void)getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids); (void)getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids);
} else { } else {
#ifdef HAVE_GETGROUPLIST_2
ngids = getgrouplist_2(pw->pw_name, pw->pw_gid, &gids);
if (ngids == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to allocate memory");
debug_return_ptr(NULL);
}
#else
ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2; ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2;
if (ngids < 0) if (ngids < 0)
ngids = NGROUPS_MAX * 2; ngids = NGROUPS_MAX * 2;
@@ -276,6 +284,7 @@ sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1)
if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1)
ngids = -1; ngids = -1;
} }
#endif /* HAVE_GETGROUPLIST_2 */
} }
} }
if (ngids <= 0) { if (ngids <= 0) {

View File

@@ -379,6 +379,7 @@ fix_fds(void)
/* /*
* Allocate space for groups and fill in using getgrouplist() * Allocate space for groups and fill in using getgrouplist()
* for when we cannot (or don't want to) use getgroups(). * for when we cannot (or don't want to) use getgroups().
* Returns 0 on success and -1 on failure.
*/ */
static int static int
fill_group_list(struct user_details *ud, int system_maxgroups) fill_group_list(struct user_details *ud, int system_maxgroups)
@@ -401,6 +402,12 @@ fill_group_list(struct user_details *ud, int system_maxgroups)
(void)getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups); (void)getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);
ret = 0; ret = 0;
} else { } else {
#ifdef HAVE_GETGROUPLIST_2
ud->groups = NULL;
ud->ngroups = getgrouplist_2(ud->username, ud->gid, &ud->groups);
if (ud->ngroups != -1)
ret = 0;
#else
/* /*
* It is possible to belong to more groups in the group database * It is possible to belong to more groups in the group database
* than NGROUPS_MAX. We start off with NGROUPS_MAX * 4 entries * than NGROUPS_MAX. We start off with NGROUPS_MAX * 4 entries
@@ -418,6 +425,7 @@ fill_group_list(struct user_details *ud, int system_maxgroups)
} }
ret = getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups); ret = getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);
} }
#endif /* HAVE_GETGROUPLIST_2 */
} }
done: done:
debug_return_int(ret); debug_return_int(ret);