From: Todd C. Miller Date: Tue, 13 Dec 2016 17:39:32 +0000 (-0700) Subject: Use getgrouplist_2() on macOS if available. X-Git-Tag: SUDO_1_8_19^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ae76e1a2290313aaad7ea74813fee4a8898e41b4;p=sudo Use getgrouplist_2() on macOS if available. --- diff --git a/config.h.in b/config.h.in index 75b00825a..61462e4b5 100644 --- a/config.h.in +++ b/config.h.in @@ -95,6 +95,10 @@ don't. */ #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 don't. */ #undef HAVE_DECL_GETRESUID @@ -267,6 +271,9 @@ /* Define to 1 if you have the `getgrouplist' function. */ #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. */ #undef HAVE_GETGROUPS diff --git a/configure.ac b/configure.ac index 5625ef275..b27188516 100644 --- a/configure.ac +++ b/configure.ac @@ -2111,6 +2111,9 @@ case "$host" in fi 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 # 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])]) diff --git a/include/sudo_compat.h b/include/sudo_compat.h index eb47d9004..c2c951f4c 100644 --- a/include/sudo_compat.h +++ b/include/sudo_compat.h @@ -392,6 +392,9 @@ __dso_public int sudo_getgrouplist(const char *name, gid_t basegid, gid_t *group # undef getgrouplist # define getgrouplist(_a, _b, _c, _d) sudo_getgrouplist((_a), (_b), (_c), (_d)) #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 __dso_public ssize_t sudo_getline(char **bufp, size_t *bufsizep, FILE *fp); # undef getline diff --git a/plugins/sudoers/pwutil_impl.c b/plugins/sudoers/pwutil_impl.c index 8c469f583..88e14d76f 100644 --- a/plugins/sudoers/pwutil_impl.c +++ b/plugins/sudoers/pwutil_impl.c @@ -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); } 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; if (ngids < 0) 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) ngids = -1; } +#endif /* HAVE_GETGROUPLIST_2 */ } } if (ngids <= 0) { diff --git a/src/sudo.c b/src/sudo.c index 8d36b3df0..354b4b6bd 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -379,6 +379,7 @@ fix_fds(void) /* * Allocate space for groups and fill in using getgrouplist() * for when we cannot (or don't want to) use getgroups(). + * Returns 0 on success and -1 on failure. */ static int 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); ret = 0; } 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 * 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); } +#endif /* HAVE_GETGROUPLIST_2 */ } done: debug_return_int(ret);