Bug 11049 - pam_winbind does not populate the entire list of groups
pam_winbind does not populate the entire list of groups
Status: NEW
Product: Samba 4.1 and newer
Classification: Unclassified
Component: Winbind
4.1.11
All All
: P5 normal
: 4.3
Assigned To: Samba QA Contact
Samba QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2015-01-12 23:18 UTC by Steinar H. Gunderson
Modified: 2015-12-07 22:29 UTC (History)
3 users (show)

See Also:


Attachments
Samba logs (debug level 10) from a fresh start, immediately followed by a login and "id" (174.30 KB, application/gzip)
2015-01-12 23:19 UTC, Steinar H. Gunderson
no flags Details
smb.conf from the machine running winbind (9.38 KB, text/plain)
2015-01-12 23:20 UTC, Steinar H. Gunderson
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steinar H. Gunderson 2015-01-12 23:18:37 UTC
Hi,

I have a winbind machine against a Samba 4.1 AD DC. I use pam_winbind and nss_winbind (and Kerberized mount.cifs with pam_mount :-) ). Somehow the list of supplementary groups is incomplete, though:

nemesis:~> id
uid=20053(sesse) gid=123(itk) groups=123(itk),1123(zomg),1170(domain users)

The funny thing is, if I give the username to id (which makes it look up the list of groups I am _supposed_ to have, instead of the ones I have in my supplementary list right now), it gets it right:

nemesis:~> id sesse
uid=20053(sesse) gid=123(itk) groups=123(itk),1170(domain users),1123(zomg),4294967295,30057(uka-eksternfiler),1101(uka11-admin-it-utv),4294967295,1007(uka09-adm),1008(uka09-adm-it),1009(uka09-adm-it-utv),30067(uka-admin-it-utv),242(usrp),1144(uka09-eksternfiler),4294967295,30050(uka-admin),1065(uka11-admin),1053(svurr),1000001(BUILTIN\users)

Also, I am properly a member of them if I just ask nicely, e.g.:

nemesis:~> sg uka09-adm
nemesis:~> id
uid=20053(sesse) gid=1007(uka09-adm) groups=123(itk),1007(uka09-adm),1123(zomg),1170(domain users)
nemesis:~> id
uid=20053(sesse) gid=1053(svurr) groups=123(itk),1007(uka09-adm),1053(svurr),1123(zomg),1170(domain users)

I wonder if this is somehow related to the two “4294967295” groups, which I suppose are groups I'm a member of but that don't have a POSIX GID inside the range. (I am using the AD winbind backend, and there's seemingly no way of saying “if there's no gid, or it's out-of-range, just assign one from the default winbind backend”.)
Comment 1 Steinar H. Gunderson 2015-01-12 23:19:30 UTC
Created attachment 10611 [details]
Samba logs (debug level 10) from a fresh start, immediately followed by a login and "id"
Comment 2 Steinar H. Gunderson 2015-01-12 23:20:21 UTC
Created attachment 10612 [details]
smb.conf from the machine running winbind
Comment 3 Steinar H. Gunderson 2015-01-14 01:12:21 UTC
I looked a bit more at this. It's definitely related to the unmappable groups; the list gets truncated at -1 somehow. You can see this the easiest when I su to my user from root (with NSS_DEBUG on):

root@nemesis:~# su sesse
[ 3957]: getpwuid_r -1
[ 3957]: getpwuid -1 returns NSS_STATUS_NOTFOUND (0)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: initgroups sesse (123)
[ 3957]: initgroups sesse: got NSS_STATUS_SUCCESS and 18 gids
[ 3957]: initgroups sesse (123): processing gid 123 
[ 3957]: initgroups sesse (123): processing gid 1170 
[ 3957]: initgroups sesse (123): processing gid 1123 
[ 3957]: initgroups sesse (123): processing gid -1 
[ 3957]: initgroups sesse (123): processing gid 30057 
[ 3957]: initgroups sesse (123): processing gid 1101 
[ 3957]: initgroups sesse (123): processing gid -1 
[ 3957]: initgroups sesse (123): processing gid 1007 
[ 3957]: initgroups sesse (123): processing gid 1008 
[ 3957]: initgroups sesse (123): processing gid 1009 
[ 3957]: initgroups sesse (123): processing gid 30067 
[ 3957]: initgroups sesse (123): processing gid 242 
[ 3957]: initgroups sesse (123): processing gid 1144 
[ 3957]: initgroups sesse (123): processing gid -1 
[ 3957]: initgroups sesse (123): processing gid 30050 
[ 3957]: initgroups sesse (123): processing gid 1065 
[ 3957]: initgroups sesse (123): processing gid 1053 
[ 3957]: initgroups sesse (123): processing gid 1000001 
[ 3957]: initgroups sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)
[ 3957]: getgrgid 123
[ 3957]: getgrgid 123 returns NSS_STATUS_SUCCESS (1)
[ 3957]: getpwnam_r sesse
[ 3957]: getpwnam sesse returns NSS_STATUS_SUCCESS (1)

and then the list gets truncated at the first -1:

uid=20053(sesse) gid=123(itk) groups=123(itk),1123(zomg),1170(domain users)

stracing su yields insights:

root@nemesis:~# strace -vffF su sesse 2>&1 | grep setgrou
setgroups(18, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242, 1144, 4294967295, 30050, 1065, 1053, 1000001]) = -1 EINVAL (Invalid argument)
setgroups(17, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242, 1144, 4294967295, 30050, 1065, 1053]) = -1 EINVAL (Invalid argument)
setgroups(16, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242, 1144, 4294967295, 30050, 1065]) = -1 EINVAL (Invalid argument)
setgroups(15, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242, 1144, 4294967295, 30050]) = -1 EINVAL (Invalid argument)
setgroups(14, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242, 1144, 4294967295]) = -1 EINVAL (Invalid argument)
setgroups(13, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242, 1144]) = -1 EINVAL (Invalid argument)
setgroups(12, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067, 242]) = -1 EINVAL (Invalid argument)
setgroups(11, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009, 30067]) = -1 EINVAL (Invalid argument)
setgroups(10, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008, 1009]) = -1 EINVAL (Invalid argument)
setgroups(9, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007, 1008]) = -1 EINVAL (Invalid argument)
setgroups(8, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295, 1007]) = -1 EINVAL (Invalid argument)
setgroups(7, [123, 1170, 1123, 4294967295, 30057, 1101, 4294967295]) = -1 EINVAL (Invalid argument)
setgroups(6, [123, 1170, 1123, 4294967295, 30057, 1101]) = -1 EINVAL (Invalid argument)
setgroups(5, [123, 1170, 1123, 4294967295, 30057]) = -1 EINVAL (Invalid argument)
setgroups(4, [123, 1170, 1123, 4294967295]) = -1 EINVAL (Invalid argument)
setgroups(3, [123, 1170, 1123])         = 0

This mechanism is there to try to set the maximum possible list, but seemingly setgroups() fails whenever you try to include -1 in the list of supplementary groups.

This isn't documented in the setgroups manpage, and I find it a bit hard to trace this through the Linux kernel (there's so much stuff about namespace in the way), but it seems that (gid_t)-1 is indeed an invalid gid value to set to the kernel.

The conclusion seems to be that _nss_winbind_initgroups_dyn() should simply filter away every gid that's -1. I'm doing that now; the only thing that seems negative is that “id sesse” no longer returns the 4294967295 markers telling me that there's some group that mapping failed for, but honestly, that would sound much better than truncating the group list at some random place.

Proposed patch:

--- samba-4.1.11+dfsg.orig/nsswitch/winbind_nss_linux.c
+++ samba-4.1.11+dfsg/nsswitch/winbind_nss_linux.c
@@ -1102,6 +1101,9 @@ _nss_winbind_initgroups_dyn(char *user,
                        if (gid_list[i] == group) {
                                continue;
                        }
+                       if (gid_list[i] == (gid_t)-1) {
+                               continue;
+                       }

                        /* Filled buffer ? If so, resize. */