Package: libc6 Version: 2.2.5-11.5 Severity: important Tags: Found that under certain circumstances my program got SIGSEGV in getgrouplist(). Tryed it on three different machines, with the same result. When all of these hold true, it segfaults: * two calls to getgrouplist() (the second yields the segmentation fault) (these two calls can be unrelated - I mean they need not have any of their arguments be the same, unlike in the sample program) * a getpwnam() call must precede the getgrouplist() * the user must be a member of at least 6 supplementary groups * (this is rather strange to me) the malloc() that gets the space to hold the group list must be preceded by the getpwnam() call (Seems to be some bounds violation in the heap to me, even may have security concerns.) I attached two sample 'proglets' that demonstrate the last argument, and a backtrace using libc6-dbg (plus some additional info). norbi -- System Information Debian Release: 3.0 Architecture: i386 Kernel: Linux ***** 2.4.24 #1 Wed Mar 3 21:16:10 CET 2004 i686 Locale: LANG=C, LC_CTYPE=hu_HU
#include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <pwd.h> #include <grp.h> gid_t *supplementary_groups(char *user) { struct passwd *pw; int ngroups = 1; gid_t *groups; /* Order is significant for the next two calls. This works: */ groups = (gid_t *) malloc(ngroups * sizeof(gid_t)); pw = getpwnam(user); if (!pw) return NULL; if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) < 0) { groups = realloc(groups, ngroups * sizeof(gid_t)); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); } return groups; } main() { supplementary_groups("norbi"); }
#include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <pwd.h> #include <grp.h> gid_t *supplementary_groups(char *user) { struct passwd *pw; int ngroups = 1; gid_t *groups; /* Order is significant for the next two calls. This generates a SIGSEGV: */ pw = getpwnam(user); groups = (gid_t *) malloc(ngroups * sizeof(gid_t)); if (!pw) return NULL; if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) < 0) { groups = realloc(groups, ngroups * sizeof(gid_t)); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); } return groups; } main() { supplementary_groups("norbi"); }
Attachment:
Makefile
Description: Binary data
Script started on Wed Apr 21 04:43:22 2004 norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ make cc -g -O0 works.c -o works cc -g -O0 dies.c -o dies norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ ./works norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ ./dies Segmentation fault (core dumped) norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ export LD_LIBRARY_PATH=/usr/lib/debug norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ gdb dies (gdb) r Starting program: /home/norbi/Scratch/toroljle/getgrouplist-bug/dies Program received signal SIGSEGV, Segmentation fault. 0x400f0248 in known_compare (p1=0xbffff828, p2=0x72) at nsswitch.c:259 259 nsswitch.c: No such file or directory. in nsswitch.c (gdb) bt #0 0x400f0248 in known_compare (p1=0xbffff828, p2=0x72) at nsswitch.c:259 #1 0x400e23b8 in __tsearch (key=0xbffff828, vrootp=0x8049dac, compar=0x400f0228 <known_compare>) at tsearch.c:260 #2 0x400f02a9 in __nss_lookup_function (ni=0x8049d90, fct_name=0x40121425 "initgroups_dyn") at nsswitch.c:280 #3 0x400b2ab5 in internal_getgrouplist (user=0x8049728 "norbi", group=100, size=0xbffff8a4, groupsp=0xbffff8a8, limit=-1) at initgroups.c:163 #4 0x400b2bc8 in getgrouplist (user=0x8049728 "norbi", group=100, groups=0x804a588, ngroups=0xbffff8d4) at initgroups.c:209 #5 0x08048566 in supplementary_groups (user=0x80485e4 "norbi") at dies.c:22 #6 0x08048587 in main () at dies.c:29 (gdb) q A debugging session is active. Do you still want to close the debugger?(y or n) y norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ dpkg -l libc6 libc6-dbg Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed |/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad) ||/ Name Version Description +++-==============-==============-============================================ ii libc6 2.2.5-11.5 GNU C Library: Shared libraries and Timezone ii libc6-dbg 2.2.5-11.5 GNU C Library: Libraries with debugging symb norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ cat /etc/nsswitch.conf # /etc/nsswitch.conf # # Example configuration of GNU Name Service Switch functionality. # If you have the `glibc-doc' and `info' packages installed, try: # `info libc "Name Service Switch"' for information about this file. passwd: compat group: compat shadow: compat hosts: files dns networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: nis norbi@mymachine:~/tmp/toroljle/getgrouplist-bug$ Script done on Wed Apr 21 04:45:18 2004