diff --git a/config.h.in b/config.h.in index 45f54445b..b48acabb7 100644 --- a/config.h.in +++ b/config.h.in @@ -1371,6 +1371,11 @@ # undef _LINUX_SOURCE_COMPAT #endif +/* Enable unlimited getgroups(2) support on macOS. */ +#ifndef _DARWIN_UNLIMITED_GETGROUPS +# undef _DARWIN_UNLIMITED_GETGROUPS +#endif + /* Enable prototypes in GCC fixed includes on older systems. */ #ifndef __USE_FIXED_PROTOTYPES__ # undef __USE_FIXED_PROTOTYPES__ diff --git a/configure b/configure index 984b96460..0346e346c 100755 --- a/configure +++ b/configure @@ -16183,6 +16183,10 @@ fi done + # macOS >= 10.6 getgroups(2) can support more than > 16 groups + $as_echo "#define _DARWIN_UNLIMITED_GETGROUPS 1" >>confdefs.h + + # We need to force a flat namespace to make libc # symbol hooking work like it does on ELF. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-force_flat_namespace" >&5 diff --git a/configure.ac b/configure.ac index 5ddec69ae..5d0dc9d5f 100644 --- a/configure.ac +++ b/configure.ac @@ -2292,6 +2292,9 @@ case "$host" in # Undocumented API that dynamically allocates the groups. AC_CHECK_FUNCS([getgrouplist_2], [AC_CHECK_DECLS([getgrouplist_2])]) + # macOS >= 10.6 getgroups(2) can support more than > 16 groups + AC_DEFINE([_DARWIN_UNLIMITED_GETGROUPS]) + # 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])]) @@ -5019,6 +5022,11 @@ AH_BOTTOM([/* Symbol visibility controls */ # undef _LINUX_SOURCE_COMPAT #endif +/* Enable unlimited getgroups(2) support on macOS. */ +#ifndef _DARWIN_UNLIMITED_GETGROUPS +# undef _DARWIN_UNLIMITED_GETGROUPS +#endif + /* Enable prototypes in GCC fixed includes on older systems. */ #ifndef __USE_FIXED_PROTOTYPES__ # undef __USE_FIXED_PROTOTYPES__ diff --git a/src/sudo.c b/src/sudo.c index 4a556db8d..9d60e1b6d 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -431,9 +431,10 @@ get_user_groups(struct user_details *ud) if (maxgroups < 0) maxgroups = NGROUPS_MAX; + /* Note that macOS may return ngroups > NGROUPS_MAX. */ if ((ud->ngroups = getgroups(0, NULL)) > 0) { - /* Use groups from kernel if not too many or source is static. */ - if (ud->ngroups < maxgroups || group_source == GROUP_SOURCE_STATIC) { + /* Use groups from kernel if not at limit or source is static. */ + if (ud->ngroups != maxgroups || group_source == GROUP_SOURCE_STATIC) { ud->groups = reallocarray(NULL, ud->ngroups, sizeof(GETGROUPS_T)); if (ud->groups == NULL) goto done;