]> granicus.if.org Git - sudo/commitdiff
Use getgrouplist_2() on macOS if available.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 13 Dec 2016 17:39:32 +0000 (10:39 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 13 Dec 2016 17:39:32 +0000 (10:39 -0700)
config.h.in
configure.ac
include/sudo_compat.h
plugins/sudoers/pwutil_impl.c
src/sudo.c

index 75b00825ad896219c9d4b4ebc748422d1cf5976d..61462e4b595ca8ec665767f5c1efbf90105fbd28 100644 (file)
    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
 /* 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
 
index 5625ef27570797bd75b4c3cd8bd831eb568cb01d..b2718851643ce7187b7e57a6ebdd447feea38d75 100644 (file)
@@ -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])])
index eb47d9004bab41748deaa06ccd6ee0fff0a7c641..c2c951f4cd652bd269fb54732fb952f12a0d9ccd 100644 (file)
@@ -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
index 8c469f583d33b8ef3a52b2c73f81fe9fbcf777fa..88e14d76f8ebdfac471157e2a11647000a9d778e 100644 (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);
        } 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) {
index 8d36b3df0b2675aeaf09acb0991fb8531268d4f0..354b4b6bd33baa605d381c350d21a3bfdf6aee3f 100644 (file)
@@ -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);