Date: Mon, 12 Feb 1996 01:22:38 -0500 (EST) From: Bill Paul <wpaul@skynet.ctr.columbia.edu> To: current@freebsd.org Subject: Proposed change to getpwent and getgrent Message-ID: <199602120622.BAA08093@skynet.ctr.columbia.edu>
next in thread | raw e-mail | index | archive | help
Bug bin/517 points out a problem with the NIS +group matching code in src/lib/libc/gen/getpwent.c clobbering getgrent(3) buffers being held by user programs. In a nutshell, the getpwent(3) code can call getgrnam() internally if NIS is enabled and +group overrides are being used in /etc/master.passwd. This call to getgrnam() scrambles the contents of the static buffers allocated by the getgrent(3) code; if a user program has called a getgrent(3) function immediately prior to calling a getpwent(3) function, it will end up with bogus data. In other words, calling getgrnam() inside getpwent(3) is bogus because getgrnam() isn't reentrant. So, how to fix. I came up with the following choices: #1 Remove the +group override feature; it's FreeBSD-specific anyway. (I implemented the idea after Justin Gibbs suggested it; it's not something you'll find on any other platform that supports NIS.) #2 Add some magic hooks to getgrnam() so that it can be called safely from inside getpwent(3) without affecting user programs. #3 Implement a real reentrant interface to getgrent(3). #1 is the chicken's way out. I like the +group override mechanism. I coded and tested several versions of #2, but they all involved either exporting global symbols from inside getgrent(3) or adding extra entry points. Exporting global symbols, even with lots of leading underscores, seemed messy, as did adding an extra undocumented function call. Besides, this only addresses this one instance of the problem. I finally decided that #3 was the best solution. I imagine that someday, someone will want real multi-threading support, which means we'll need this sort of thing eventually anyway. So, stealing a peek at the Solaris getgrent(3) man page, I modified getgrent(3) to support reentrancy and added three new functions: getgrgid_r(), getgrnam_r() and getgrent_r(). Anyone who's familiar with Solaris knows how these work: they accept a pre-allocated group structure, line buffer and buffer length in addition to their usual arguments. While I was in the neighborhood, I also did the same to getpwent(3). The getpwent(3) code calls getgrent_r() internally using its own pre-allocated buffers, so it no longer clobbers buffers being held by user programs. I'd like some people here to peek at the new code before I commit it since the changes take affect with or without YP being #defined. Even though it works for me, Murphy's Law says there's probably something wrong with it that I missed. Comments are welcome. I have new versions of getgrent.c and getpwent.c in ~wpaul/reentrant on freefall. There are also context diffs against getpwent.c and getgrent.c from -current, which is what the changes are based on. I also threw in new pwd.h and grp.h headers with prototypes for the new functions. I have the same files available for anon ftp from skynet.ctr.columbia.edu:/pub/ftp/freebsd/reentrant if others want to look at them. (Go easy on skynet: it's sitting behind a SLIP link.) There's one matter still unresolved which is that getpwent(3) also calls getnetgrent(3) to resolve netgroups. I suppose I'll have to whip up a reentrant interface to getnetgrent(3) now too. This will probably take me a little longer since getnetgrent() is a little more complicated. -Bill -- ============================================================================= -Bill Paul (212) 854-6020 | System Manager Work: wpaul@ctr.columbia.edu | Center for Telecommunications Research Home: wpaul@skynet.ctr.columbia.edu | Columbia University, New York City ============================================================================= License error: The license for this .sig file has expired. You must obtain a new license key before any more witty phrases will appear in this space. =============================================================================
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199602120622.BAA08093>