aboutsummaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-01-21 19:30:19 +0000
committerMark Johnston <markj@FreeBSD.org>2021-01-21 19:30:19 +0000
commit5619d49e07d3942e438f3d06269f3c1c466cf5b7 (patch)
tree811c4c808e657eef2f31c9570a4470e62fb7b6b3 /lib/libc
parent7abc10098b3d9c23d611294714b3058e8048aec0 (diff)
downloadsrc-5619d49e07d3942e438f3d06269f3c1c466cf5b7.tar.gz
src-5619d49e07d3942e438f3d06269f3c1c466cf5b7.zip
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
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/getgrent.c34
-rw-r--r--lib/libc/gen/getpwent.c18
2 files changed, 26 insertions, 26 deletions
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c
index b3699cae3c45..6abccea30c6b 100644
--- a/lib/libc/gen/getgrent.c
+++ b/lib/libc/gen/getgrent.c
@@ -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 @@ docompat:
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 @@ docompat:
&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 @@ fin:
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)
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c
index 09f84f9576ee..a07ee109e2df 100644
--- a/lib/libc/gen/getpwent.c
+++ b/lib/libc/gen/getpwent.c
@@ -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 @@ docompat:
}
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 @@ docompat:
rv = NS_UNAVAIL;
goto fin;
} else if (rv == 1) {
- st->keynum = -1;
+ keynum = -1;
rv = NS_NOTFOUND;
goto fin;
}
@@ -1931,6 +1933,8 @@ docompat:
break;
}
fin:
+ if (how == nss_lt_all)
+ st->keynum = keynum;
if (st->db != NULL && !stayopen) {
(void)st->db->close(st->db);
st->db = NULL;