libc/nss: Restore iterator state when doing passwd/group lookups
The getpwent(3) and getgrent(3) implementations maintain some internal iterator state. Interleaved calls to functions which do passwd/group lookups using a key, such as getpwnam(3), would in some cases clobber this state, causing a subsequent getpwent() or getgrent() call to restart iteration from the beginning of the database or to terminate early. This is particularly troublesome in programming environments where execution of green threads is interleaved within a single OS thread. Take care to restore any iterator state following a keyed lookup. The "files" provider for the passwd database was already handling this correctly, but "compat" was not, and both providers had this problem when accessing the group database. PR: 252094 Submitted by: Viktor Dukhovni <ietf-dane@dukhovni.org> MFC after: 1 month
This commit is contained in:
parent
7abc10098b
commit
5619d49e07
@ -882,16 +882,12 @@ files_group(void *retval, void *mdata, va_list ap)
|
||||
}
|
||||
fresh = 1;
|
||||
}
|
||||
if (how == nss_lt_all)
|
||||
stayopen = 1;
|
||||
else {
|
||||
if (!fresh)
|
||||
rewind(st->fp);
|
||||
stayopen = st->stayopen;
|
||||
}
|
||||
rv = NS_NOTFOUND;
|
||||
stayopen = (how == nss_lt_all || !fresh) ? 1 : st->stayopen;
|
||||
if (stayopen)
|
||||
pos = ftello(st->fp);
|
||||
if (how != nss_lt_all && !fresh)
|
||||
rewind(st->fp);
|
||||
rv = NS_NOTFOUND;
|
||||
while ((line = fgetln(st->fp, &linesize)) != NULL) {
|
||||
if (line[linesize-1] == '\n')
|
||||
linesize--;
|
||||
@ -913,13 +909,15 @@ files_group(void *retval, void *mdata, va_list ap)
|
||||
&buffer[linesize + 1], bufsize - linesize - 1, errnop);
|
||||
if (rv & NS_TERMINATE)
|
||||
break;
|
||||
if (stayopen)
|
||||
if (how == nss_lt_all)
|
||||
pos = ftello(st->fp);
|
||||
}
|
||||
if (st->fp != NULL && !stayopen) {
|
||||
fclose(st->fp);
|
||||
st->fp = NULL;
|
||||
}
|
||||
if (st->fp != NULL && how != nss_lt_all)
|
||||
fseeko(st->fp, pos, SEEK_SET);
|
||||
if (rv == NS_SUCCESS && retval != NULL)
|
||||
*(struct group **)retval = grp;
|
||||
else if (rv == NS_RETURN && *errnop == ERANGE && st->fp != NULL)
|
||||
@ -1364,13 +1362,11 @@ compat_group(void *retval, void *mdata, va_list ap)
|
||||
}
|
||||
fresh = 1;
|
||||
}
|
||||
if (how == nss_lt_all)
|
||||
stayopen = 1;
|
||||
else {
|
||||
if (!fresh)
|
||||
rewind(st->fp);
|
||||
stayopen = st->stayopen;
|
||||
}
|
||||
stayopen = (how == nss_lt_all || !fresh) ? 1 : st->stayopen;
|
||||
if (stayopen)
|
||||
pos = ftello(st->fp);
|
||||
if (how != nss_lt_all && !fresh)
|
||||
rewind(st->fp);
|
||||
docompat:
|
||||
switch (st->compat) {
|
||||
case COMPAT_MODE_ALL:
|
||||
@ -1431,8 +1427,6 @@ compat_group(void *retval, void *mdata, va_list ap)
|
||||
break;
|
||||
}
|
||||
rv = NS_NOTFOUND;
|
||||
if (stayopen)
|
||||
pos = ftello(st->fp);
|
||||
while ((line = fgetln(st->fp, &linesize)) != NULL) {
|
||||
if (line[linesize-1] == '\n')
|
||||
linesize--;
|
||||
@ -1473,7 +1467,7 @@ compat_group(void *retval, void *mdata, va_list ap)
|
||||
&buffer[linesize + 1], bufsize - linesize - 1, errnop);
|
||||
if (rv & NS_TERMINATE)
|
||||
break;
|
||||
if (stayopen)
|
||||
if (how == nss_lt_all)
|
||||
pos = ftello(st->fp);
|
||||
}
|
||||
fin:
|
||||
@ -1481,6 +1475,8 @@ compat_group(void *retval, void *mdata, va_list ap)
|
||||
fclose(st->fp);
|
||||
st->fp = NULL;
|
||||
}
|
||||
if (st->fp != NULL && how != nss_lt_all)
|
||||
fseeko(st->fp, pos, SEEK_SET);
|
||||
if (rv == NS_SUCCESS && retval != NULL)
|
||||
*(struct group **)retval = grp;
|
||||
else if (rv == NS_RETURN && *errnop == ERANGE && st->fp != NULL)
|
||||
|
@ -1733,6 +1733,7 @@ compat_passwd(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
char keybuf[MAXLOGNAME + 1];
|
||||
DBT key, entry;
|
||||
pwkeynum keynum;
|
||||
struct compat_state *st;
|
||||
enum nss_lookup_type how;
|
||||
const char *name;
|
||||
@ -1783,9 +1784,10 @@ compat_passwd(void *retval, void *mdata, va_list ap)
|
||||
rv = NS_NOTFOUND;
|
||||
goto fin;
|
||||
}
|
||||
keynum = st->keynum;
|
||||
stayopen = 1;
|
||||
} else {
|
||||
st->keynum = 0;
|
||||
keynum = 0;
|
||||
stayopen = st->stayopen;
|
||||
}
|
||||
docompat:
|
||||
@ -1829,13 +1831,13 @@ compat_passwd(void *retval, void *mdata, va_list ap)
|
||||
}
|
||||
key.data = keybuf;
|
||||
rv = NS_NOTFOUND;
|
||||
while (st->keynum >= 0) {
|
||||
st->keynum++;
|
||||
while (keynum >= 0) {
|
||||
keynum++;
|
||||
if (st->version < _PWD_CURRENT_VERSION) {
|
||||
memcpy(&keybuf[1], &st->keynum, sizeof(st->keynum));
|
||||
key.size = sizeof(st->keynum) + 1;
|
||||
memcpy(&keybuf[1], &keynum, sizeof(keynum));
|
||||
key.size = sizeof(keynum) + 1;
|
||||
} else {
|
||||
store = htonl(st->keynum);
|
||||
store = htonl(keynum);
|
||||
memcpy(&keybuf[1], &store, sizeof(store));
|
||||
key.size = sizeof(store) + 1;
|
||||
}
|
||||
@ -1846,7 +1848,7 @@ compat_passwd(void *retval, void *mdata, va_list ap)
|
||||
rv = NS_UNAVAIL;
|
||||
goto fin;
|
||||
} else if (rv == 1) {
|
||||
st->keynum = -1;
|
||||
keynum = -1;
|
||||
rv = NS_NOTFOUND;
|
||||
goto fin;
|
||||
}
|
||||
@ -1931,6 +1933,8 @@ compat_passwd(void *retval, void *mdata, va_list ap)
|
||||
break;
|
||||
}
|
||||
fin:
|
||||
if (how == nss_lt_all)
|
||||
st->keynum = keynum;
|
||||
if (st->db != NULL && !stayopen) {
|
||||
(void)st->db->close(st->db);
|
||||
st->db = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user