Don't use sysconf(_SC_NGROUPS_MAX) on macOS for getgroups()
[samba.git] / source3 / lib / system.c
index 5d57ffadda10f86796054757b7b11460a88213eb..a14fc51ca63e3d704b1364681106b5c27426a4b0 100644 (file)
@@ -756,7 +756,7 @@ void sys_srandom(unsigned int seed)
  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
 ****************************************************************************/
 
-int groups_max(void)
+int setgroups_max(void)
 {
 #if defined(SYSCONF_SC_NGROUPS_MAX)
        int ret = sysconf(_SC_NGROUPS_MAX);
@@ -766,6 +766,24 @@ int groups_max(void)
 #endif
 }
 
+int getgroups_max(void)
+{
+#if defined(DARWINOS)
+       /*
+        * On MacOS sysconf(_SC_NGROUPS_MAX) returns 16 due to MacOS's group
+        * nesting. However, The initgroups() manpage states the following:
+        * "Note that OS X supports group membership in an unlimited number
+        * of groups. The OS X kernel uses the group list stored in the process
+        * credentials only as an initial cache.  Additional group memberships
+        * are determined by communication between the operating system and the
+        * opendirectoryd daemon."
+        */
+       return INT_MAX;
+#else
+       return setgroups_max();
+#endif
+}
+
 /**************************************************************************
  Wrap setgroups and getgroups for systems that declare getgroups() as
  returning an array of gid_t, but actuall return an array of int.
@@ -831,7 +849,7 @@ static int sys_broken_setgroups(int setlen, gid_t *gidset)
        if (setlen == 0)
                return 0 ;
 
-       if (setlen < 0 || setlen > groups_max()) {
+       if (setlen < 0 || setlen > setgroups_max()) {
                errno = EINVAL; 
                return -1;   
        }
@@ -882,7 +900,7 @@ static int sys_bsd_setgroups(gid_t primary_gid, int setlen, const gid_t *gidset)
        int ret;
 
        /* setgroups(2) will fail with EINVAL if we pass too many groups. */
-       max = groups_max();
+       max = setgroups_max();
 
        /* No group list, just make sure we are setting the efective GID. */
        if (setlen == 0) {