git: 5619d49e07d3 - main - libc/nss: Restore iterator state when doing passwd/group lookups

Mark Johnston markj at FreeBSD.org
Thu Jan 21 19:30:47 UTC 2021


The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=5619d49e07d3942e438f3d06269f3c1c466cf5b7

commit 5619d49e07d3942e438f3d06269f3c1c466cf5b7
Author:     Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2021-01-21 19:30:19 +0000
Commit:     Mark Johnston <markj at FreeBSD.org>
CommitDate: 2021-01-21 19:30:19 +0000

    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 at dukhovni.org>
    MFC after:      1 month
---
 lib/libc/gen/getgrent.c | 34 +++++++++++++++-------------------
 lib/libc/gen/getpwent.c | 18 +++++++++++-------
 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;


More information about the dev-commits-src-all mailing list