Hi,

I noticed that setpassent(1) probably doesn't work as intended, as this
program should open the spwd.db file once, not four times?

int main() {
        setpassent(1);
        getpwnam("root"); getpwnam("root"); getpwuid(0); getpwuid(0);
        return 0;
}

It seems to be due to faulty logic in libc/gen/getpwent.c. In short

...
        savedb = _pw_db;
        if (!_pw_db && !__initdb())
...
_pw_db begin as NULL
so savedb is set to NULL
_pw_db is NULL and __initdb() is run, _pw_db is set
...
        if (savedb != _pw_db || !_pw_stayopen) {
...
savedb is still NULL, _pwd_db is not, so the first condition is true
_pw_db get closed, and set to NULL

This following patch fixes this.

--- lib/libc/gen/getpwent.c.orig        Thu Nov 14 21:06:13 2013
+++ lib/libc/gen/getpwent.c     Thu Nov 14 21:18:45 2013
@@ -708,10 +708,8 @@
 {
        struct passwd *pwret = NULL;
        int flags = 0, *flagsp;
-       DB *savedb;

        _THREAD_PRIVATE_MUTEX_LOCK(pw);
-       savedb = _pw_db;
        if (!_pw_db && !__initdb())
                goto fail;

@@ -728,7 +726,7 @@
        if (!pwret)
                pwret = _pwhashbyname(name, buf, buflen, pw, flagsp);

-       if (savedb != _pw_db || !_pw_stayopen) {
+       if (!_pw_stayopen) {
                (void)(_pw_db->close)(_pw_db);
                _pw_db = NULL;
        }
@@ -755,10 +753,8 @@
 {
        struct passwd *pwret = NULL;
        int flags = 0, *flagsp;
-       DB *savedb;

        _THREAD_PRIVATE_MUTEX_LOCK(pw);
-       savedb = _pw_db;
        if (!_pw_db && !__initdb())
                goto fail;

@@ -775,7 +771,7 @@
        if (!pwret)
                pwret = _pwhashbyuid(uid, buf, buflen, pw, flagsp);

-       if (savedb != _pw_db || !_pw_stayopen) {
+       if (!_pw_stayopen) {
                (void)(_pw_db->close)(_pw_db);
                _pw_db = NULL;
        }

Reply via email to