]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Don't use sysconf(_SC_NGROUPS_MAX) on macOS for getgroups()
authorAlex Richardson <Alexander.Richardson@cl.cam.ac.uk>
Fri, 5 Oct 2018 08:35:40 +0000 (09:35 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 9 Sep 2021 17:43:19 +0000 (17:43 +0000)
On MacOS sysconf(_SC_NGROUPS_MAX) always returns 16. However, this is not
the value used by getgroups(2). MacOS uses nested groups but getgroups(2)
will return the flattened list which can easily exceed 16 groups. In my
testing getgroups() already returns 16 groups on a freshly installed
system. And on a 10.14 system the root user is in more than 16 groups by
default which makes it impossible to run smbd without this change.
Setting _DARWIN_UNLIMITED_GETGROUPS allows getgroups() to return more than
16 groups. This also changes set_unix_security_ctx() to only set up to
16 groups since that is the limit for initgroups() according to the manpage.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=8773

Signed-off-by: Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Sep  9 17:43:19 UTC 2021 on sn-devel-184

buildtools/wafsamba/wscript
source3/include/proto.h
source3/lib/system.c
source3/lib/system_smbd.c
source3/smbd/sec_ctx.c
testsuite/smbd/sec_ctx_utils.c

index 7be61e80abb4367eec6d070477cb253ba0753330..d13dbd9791262ca5bce75fd71a7e2f6276f1ee37 100644 (file)
@@ -539,7 +539,10 @@ struct foo bar = { .y = 'X', .x = 1 };
     conf.CHECK_HEADERS('strings.h inttypes.h stdint.h unistd.h minix/config.h', add_headers=True)
     conf.CHECK_HEADERS('ctype.h', add_headers=True)
 
-    if sys.platform != 'darwin':
+    if sys.platform == 'darwin':
+        conf.DEFINE('_DARWIN_C_SOURCE', 1, add_to_cflags=True)
+        conf.DEFINE('_DARWIN_UNLIMITED_GETGROUPS', 1, add_to_cflags=True)
+    else:
         conf.CHECK_HEADERS('standards.h', add_headers=True)
 
     conf.CHECK_HEADERS('stdbool.h stdint.h stdarg.h vararg.h', add_headers=True)
index 938a71e808359804db8859887e8232e2c5e7197f..eb45179aebbb3638e2831ae0679e95c6eeba651e 100644 (file)
@@ -230,7 +230,8 @@ void set_effective_capability(enum smbd_capability capability);
 void drop_effective_capability(enum smbd_capability capability);
 long sys_random(void);
 void sys_srandom(unsigned int seed);
-int groups_max(void);
+int getgroups_max(void);
+int setgroups_max(void);
 int sys_getgroups(int setlen, gid_t *gidset);
 int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset);
 uint32_t unix_dev_major(SMB_DEV_T dev);
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) {
index 3b1ac9c1c2a986d7c04bef53f20fb0d74f73953e..73bffe05f7a05b51bb1a1c2a67171d4f885a12f7 100644 (file)
@@ -205,7 +205,7 @@ bool getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
                         gid_t primary_gid,
                         gid_t **ret_groups, uint32_t *p_ngroups)
 {
-       int max_grp = MIN(128, groups_max());
+       int max_grp = MIN(128, getgroups_max());
        gid_t stack_groups[max_grp];
        uint32_t ngrp;
        gid_t *temp_groups = stack_groups;
index 5e0710e0ecbd39dfbf3847d96e3ee8f3f734c52d..d6fd11cd4a37ed387c4cefa28474a9f5c35b1973 100644 (file)
@@ -282,7 +282,7 @@ static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *grou
 
 static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups)
 {
-       int max = groups_max();
+       int max = NGROUPS_MAX;
 
        /* Start context switch */
        gain_root();
index e72292b9864d1d4a7bc8a7ef9323df8dbe12d99b..3834cfd4a169ff6c4a788d51f0d4f442063b4c16 100644 (file)
@@ -30,7 +30,7 @@ void get_random_grouplist(int *ngroups, gid_t **groups)
 {
        int i;
 
-       *ngroups = random() % groups_max();
+       *ngroups = random() % setgroups_max();
        *groups = malloc(*ngroups * sizeof(gid_t));
 
        if (!groups) {