Date: Thu, 3 Jun 1999 17:44:04 +0300 (EEST) From: netch@lucky.net (Valentin Nechayev) To: FreeBSD-gnats-submit@freebsd.org Subject: bin/12008: getpwent() YP bug Message-ID: <199906031444.RAA84607@sivka.carrier.kiev.ua>
next in thread | raw e-mail | index | archive | help
>Number: 12008 >Category: bin >Synopsis: getpwent() YP bug >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Jun 3 07:50:01 PDT 1999 >Closed-Date: >Last-Modified: >Originator: Valentin Nechayev >Release: FreeBSD 3.2-STABLE i386 >Organization: Lucky Net Ltd >Environment: FreeBSD 3.2-STABLE >Description: With YP/NIS or pseudo YP/NIS entries in password database, multiple setpwent() - getpwent() - endpwent() cycles result in null pointer usage with successive segmentation fault. YP support in getpwxxx() function group uses variable _yp_enabled to make decision in YP using policy. Its initial value (-1) causes getpwxxx() functions ( getpwnam, getpwuid, getpwent ) to call _ypinitdb(). _ypinitdb() creates cache DB in memory pointed by _ypcache pointer and changes _yp_enabled value to non-negative. When endpwent() called, it clears some variables and destruct the database, then _ypcache points to null, but _yp_enabled keeps its old state. When getpwent() is called after endpwent(), the following code is executed: ==== cut src/lib/libc/gen/getpwent.c line 122 === #ifdef YP if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { if (_yp_enabled == -1) _ypinitdb(); bzero((char *)&_ypnam, sizeof(_ypnam)); bcopy(_pw_passwd.pw_name, _ypnam, strlen(_pw_passwd.pw_name)); _pw_copy = _pw_passwd; if (unwind((char *)&_ypnam) == 0) goto tryagain; else return(&_pw_passwd); } #else === end cut === In this code, _yp_enabled is not equal to -1, therefore _ypinitdb() is not called; when getpwent() calls unwind(), unwind calls store(), store tries to write data to cache database, but cache database does not exist and _ypcache is equal to NULL. SEGV. >How-To-Repeat: Add the following comment line to /etc/master.passwd: ---:-:8:8::0:0:------------ SLIRP pseudo-users ------------:/no.such/dir:/dev/null but really line content is IMHO insensitive, when it matches /^+/ or /^-/. Rebuild password databases using pwd_mkdb program or vipw editing interface. Compile and run the following program: === cut here === #include <stdio.h> #include <stddef.h> #include <pwd.h> int main() { int i; for( i = 1; i <= 2; i++ ) { struct passwd* pwp; setpwent(); while( ( pwp = getpwent() ) != NULL ) ; endpwent(); } printf( "I am alive!\n" ); } === end cut === At second iteration of for(i), a segmentation fault occurs: === cut gdb output === Starting program: /usr/staff/netch/tmp/getpwbug/test2/test2 Program received signal SIGSEGV, Segmentation fault. 0x8049d43 in store (key=0x804ba25 "-") at getpwent.c:386 386 (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE); (gdb) print _ypcache $1 = (DB *) 0x0 === end cut === >Fix: Clear the variable _yp_enabled to default value (-1) when endpwent() clears _ypcache database: *** src/lib/libc/gen/getpwent.c.orig Thu Dec 17 18:31:02 1998 --- src/lib/libc/gen/getpwent.c Thu Jun 3 16:28:13 1999 *************** *** 255,260 **** --- 255,261 ---- _ypcache = (DB *)NULL; _yp_exclusions = 0; } + _yp_enabled = -1; #endif } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199906031444.RAA84607>