[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#245029: libc6: SIGSEGV in getgrouplist()/getpwnam()



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

Reply to: