| Summary: | setpassent() in libc does not function properly | ||
|---|---|---|---|
| Product: | Base System | Reporter: | robertw <robertw> |
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 3.3-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
|
Description
robertw
1999-10-08 07:00:00 UTC
The patch in this bug report does not work fully. I patched the endpwent() function, and it works correctly now: 244,246d243 < if (_pw_stayopen) < return; < It will keep the fd open when setpassent(int stayopen) is passed 1. It's now behaving the way it should ;) Thanks, Robert S. Wojciechowski Jr. robertw@wojo.com PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc On Fri, Oct 08, 1999 at 12:00:01AM -0700, Robert Wojciechowski Jr. wrote: > > The patch in this bug report does not work fully. I patched the endpwent() > function, and it works correctly now: > > 244,246d243 > < if (_pw_stayopen) > < return; > < > > It will keep the fd open when setpassent(int stayopen) is passed 1. It's > now behaving the way it should ;) > And endpwent() will never close the file :-( -- Ruslan Ermilov Sysadmin and DBA of the ru@ucb.crimea.ua United Commercial Bank, ru@FreeBSD.org FreeBSD committer, +380.652.247.647 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age robertw@wojo.com writes: > > >Number: 14201 > >Category: kern > >Synopsis: setpassent() in libc does not function properly > >Confidential: no > >Severity: serious > >Priority: high > >Responsible: freebsd-bugs > >State: open > >Quarter: > >Keywords: > >Date-Required: > >Class: sw-bug > >Submitter-Id: current-users > >Arrival-Date: Thu Oct 7 23:00:00 PDT 1999 > >Closed-Date: > >Last-Modified: > >Originator: Robert S. Wojciechowski Jr. > >Release: FreeBSD 3.3-RELEASE i386 > >Organization: > >Environment: > FreeBSD max.millenniumworks.com 3.3-RELEASE FreeBSD 3.3-RELEASE #9: > Sun Oct 3 02:40:16 EDT 1999 > root@max.millenniumworks.com:/usr/src/sys/compile/MYKERNEL i386 > >Description: > (This was taken from another post, just reposting this bug on 3.3-RELEASE) > Yes, indeed :) . This is the same bug report than the kern/7781. > The manual page for the setpassent(int stayopen) function says : > > "The setpassent() function accomplishes two purposes. First, it > causes getpwent() to ``rewind'' to the beginning of the database. > Additionally, if stayopen is non-zero, file descriptors are left open, > significantly speeding up subsequent accesses for all of the routines. > (This latter functionality is unnecessary for getpwent() as it doesn't > close its file descriptors by default.)" > > The problem is that in the file getpwent.c which implements the > setpassent() function in the libc, the stayopen variable seems not > used. And then, code like setpassent(1) doesn't work as expected. > > This problem is particularly annoying with ProFTPD > (/usr/ports/net/proftpd) which uses a such code. > > >How-To-Repeat: > The problem is visible using ProFTPD (latest at the time of this bug report is 1.2.0pre8). > >Fix: > (Again taken from the previous post. It's a quick one line fix!!) > > A patch has been proposed by Adam Mackler > (mackler@barter.dewline.com). It adds a "if" to check the value of > "_pw_stayopen" BEFORE calling "endpwent()". > > > Adam Mackler writes: > > > Date: Thu, 6 Aug 1998 17:50:08 -0400 > > > From: Floody <flood@evcom.net> > > > Reply-To: proftpd-l@evcom.net > > > To: Karl Pielorz <kpielorz@tdx.co.uk> > > > Cc: proftpd-l@evcom.net > > > Subject: Re: [proftpd-l] New ProFTPd user - Security, Incoming and pwd.db? > > > > > > Ok. I put up a test FreeBSD 2.2.7 system. There appears to be a libc > > > problem with the setpassent() function, which doesn't work on FreeBSD as > > > documented in the man pages (or on any other BSD). This is the heart of > > > the problem. There is no workaround until libc is fixed. > > > > Hi: > > > > I think the following patch may fix the problem, but I'm afraid > > I don't know how to rebuild my c library. If you find out if this > > works can you let me know? Thanks. > > > > > > *** getpwent.c Wed Aug 19 02:00:13 1998 > > --- getpwent.c.dist Wed Aug 19 01:58:33 1998 > > *************** > > *** 194,201 **** > > if (rval && (_pw_passwd.pw_name[0] == '+'|| > > _pw_passwd.pw_name[0] == '-')) rval = 0; > > > > ! if (!_pw_stayopen) > > ! endpwent(); > > return(rval ? &_pw_passwd : (struct passwd *)NULL); > > } > > > > --- 194,200 ---- > > if (rval && (_pw_passwd.pw_name[0] == '+'|| > > _pw_passwd.pw_name[0] == '-')) rval = 0; > > > > ! endpwent(); > > return(rval ? &_pw_passwd : (struct passwd *)NULL); > > } > > > > > > -- > > Adam Mackler > > Dewline Communications, LLC > > 212-505-9149 > > > -- Stephane.Legrand@bigfoot.com FreeBSD Francophone : http://www.freebsd-fr.org/ A test for this bug is:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
int main()
{
setpassent(1);
getpwent();
chroot("/usr");
chdir("/");
if(!getpwuid(0)) {
printf("setpassent doesn't appear to work\n");
} else {
if(!getpwuid(0))
printf("second getpwuid(0) didn't work\n");
else
printf("setpassent works\n");
}
return 0;
}
Right now, the second getpwuid(0) call fails. Adding the if (!_pw_stayopen)
before the endpwent() in both getpwnam() and getpwuid() lets this test pass,
but is it a sufficient fix?
Is a closing call to endpwent() necessary for a program to correctly close
the database?
Robert S. Wojciechowski Jr.
robertw@wojo.com
PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
Ruslan,
Looks like the original patch works the best. It works well too. If you
look in getgrent.c, it contains the right code to handle the stayopen flag:
/* correct, from getgrent.c */
if (!_gr_stayopen)
endgrent();
return(rval ? &_gr_group : NULL);
instead of
/* incorrect */
endgrent();
return(rval ? &_gr_group : NULL);
The incorrect code is what getpwent.c contains. A test for this
functionality is the following program:
--SNIP--
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
int main()
{
setpassent(1);
getpwent();
chroot("/usr");
chdir("/");
if(!getpwuid(0)) {
printf("setpassent doesn't appear to work\n");
} else {
if(!getpwuid(0))
printf("second getpwuid(0) didn't work\n");
else
printf("setpassent works\n");
}
return 0;
}
--SNIP--
It passes with flying colors after the fix.
Best regards,
Robert S. Wojciechowski Jr.
robertw@wojo.com
PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
-----Original Message-----
From: Ruslan Ermilov [mailto:ru@ucb.crimea.ua]
Sent: Friday, October 08, 1999 3:20 AM
To: Robert Wojciechowski Jr.
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/14201: setpassent() in libc does not function properly
On Fri, Oct 08, 1999 at 12:00:01AM -0700, Robert Wojciechowski Jr. wrote:
>
> The patch in this bug report does not work fully. I patched the
endpwent()
> function, and it works correctly now:
>
> 244,246d243
> < if (_pw_stayopen)
> < return;
> <
>
> It will keep the fd open when setpassent(int stayopen) is passed 1. It's
> now behaving the way it should ;)
>
And endpwent() will never close the file :-(
--
Ruslan Ermilov Sysadmin and DBA of the
ru@ucb.crimea.ua United Commercial Bank,
ru@FreeBSD.org FreeBSD committer,
+380.652.247.647 Simferopol, Ukraine
http://www.FreeBSD.org The Power To Serve
http://www.oracle.com Enabling The Information Age
Problem crept in on this update (1.11): http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/gen/getpwent.c.diff?r1=1. 10&r2=1.11 Robert S. Wojciechowski Jr. robertw@wojo.com PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc Working and tested patch (adopted from OpenBSD and NetBSD):
-- BEGIN PATCH --
--- getpwent.c.orig Mon Oct 11 15:34:56 1999
+++ getpwent.c Mon Oct 11 14:59:42 1999
@@ -176,7 +176,10 @@
if (rval && (_pw_passwd.pw_name[0] == '+'||
_pw_passwd.pw_name[0] == '-')) rval = 0;
- endpwent();
+ if (!_pw_stayopen) {
+ (void)(_pw_db->close)(_pw_db);
+ _pw_db = (DB *)NULL;
+ }
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
@@ -216,7 +219,10 @@
if (rval && (_pw_passwd.pw_name[0] == '+'||
_pw_passwd.pw_name[0] == '-')) rval = 0;
- endpwent();
+ if (!_pw_stayopen) {
+ (void)(_pw_db->close)(_pw_db);
+ _pw_db = (DB *)NULL;
+ }
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
-- END PATCH --
Robert S. Wojciechowski Jr.
robertw@wojo.com
PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
State Changed From-To: open->closed Just fixed |