Just a heads-up, because this bug took me absolutely ages to chase down, and I want to save others the same pain.
Samba is perhaps the most prominent reason why you might find a user in more than 16 groups on a Unix system, and so this bug may at first appear to be a 'Samba issue' (that certainly is why it found it's way to my attention :-) https://www.illumos.org/issues/3691 In short, unless the group list we supply to setgroups() is sorted, if there are more than 16 groups, the Illumos kernel fails to honour some of the groups. Presumably there is a bisection search being done. The symptom for Samba users is that as a user is added to more groups, they loose access to folders they previously had access too. Attached is a total hack that appears to resolve the issue, but the real fix needs to be in glibc or the kernel. Andrew Bartlett -- Andrew Bartlett http://samba.org/~abartlet/ Authentication Developer, Samba Team http://samba.org
diff --git a/source3/lib/system.c b/source3/lib/system.c index 7c0bb3f..be7d94d 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1174,14 +1174,14 @@ int groups_max(void) returning an array of gid_t, but actuall return an array of int. ****************************************************************************/ -#if defined(HAVE_BROKEN_GETGROUPS) - #ifdef HAVE_BROKEN_GETGROUPS #define GID_T int #else #define GID_T gid_t #endif +#if defined(HAVE_BROKEN_GETGROUPS) + static int sys_broken_getgroups(int setlen, gid_t *gidset) { GID_T gid; @@ -1224,6 +1224,13 @@ static int sys_broken_getgroups(int setlen, gid_t *gidset) return ngroups; } +#endif /* HAVE_BROKEN_GETGROUPS */ + +static int gid_compare(void *gid_1, void *gid_2) +{ + return (*(GID_T *)gid_1 - *(GID_T *)gid_2); +} + static int sys_broken_setgroups(int setlen, gid_t *gidset) { GID_T *group_list; @@ -1250,6 +1257,8 @@ static int sys_broken_setgroups(int setlen, gid_t *gidset) for(i = 0; i < setlen; i++) group_list[i] = (GID_T) gidset[i]; + TYPESAFE_QSORT(group_list, setlen, gid_compare); + if(setgroups(setlen, group_list) != 0) { int saved_errno = errno; SAFE_FREE(group_list); @@ -1261,8 +1270,6 @@ static int sys_broken_setgroups(int setlen, gid_t *gidset) return 0 ; } -#endif /* HAVE_BROKEN_GETGROUPS */ - /* This is a list of systems that require the first GID passed to setgroups(2) * to be the effective GID. If your system is one of these, add it here. */ @@ -1353,11 +1360,8 @@ int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset) #if defined(USE_BSD_SETGROUPS) return sys_bsd_setgroups(primary_gid, setlen, gidset); -#elif defined(HAVE_BROKEN_GETGROUPS) - return sys_broken_setgroups(setlen, gidset); -#else - return setgroups(setlen, gidset); #endif + return sys_broken_setgroups(setlen, gidset); } /**************************************************************************
-- To unsubscribe from this list go to the following URL and read the instructions: https://lists.samba.org/mailman/options/samba