Here is a patch to replace a getpwuid() call in the backend, for
thread-safety.
This is AFAICT the only call in the getpw*() family that needs to be
dealt with.
(There is also a getgrnam() call, but that is called very early in the
postmaster, before multiprocessing, so we can leave that as is.)
The solution here is actually quite attractive: We can replace the
getpwuid() call by the existing wrapper function pg_get_user_name(),
which internally uses getpwuid_r(). This also makes the code a bit
simpler. The same function is already used in libpq for a purpose that
mirrors the backend use, so it's also nicer to use the same function for
consistency.
From 090c800afd6271885d345f72bbd1d3b535dd6886 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Sat, 24 Aug 2024 10:35:56 +0200
Subject: [PATCH] thread-safety: getpwuid_r()
There was one getpwuid() call in the backend. We can replace that one
by the existing wrapper function pg_get_user_name(), which internally
uses getpwuid_r() for thread-safety. And this also makes the code a
bit simpler. The same function is already used in libpq for a purpose
that mirrors the backend use.
---
src/backend/libpq/auth.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 2b607c52704..85dcf9e9fc9 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -1857,7 +1857,7 @@ auth_peer(hbaPort *port)
uid_t uid;
gid_t gid;
#ifndef WIN32
- struct passwd *pw;
+ char pwdbuf[BUFSIZ];
int ret;
#endif
@@ -1876,25 +1876,18 @@ auth_peer(hbaPort *port)
}
#ifndef WIN32
- errno = 0; /* clear errno before
call */
- pw = getpwuid(uid);
- if (!pw)
+ if (!pg_get_user_name(uid, pwdbuf, sizeof pwdbuf))
{
- int save_errno = errno;
-
- ereport(LOG,
- (errmsg("could not look up local user ID %ld:
%s",
- (long) uid,
- save_errno ?
strerror(save_errno) : _("user does not exist"))));
+ ereport(LOG, errmsg_internal("%s", pwdbuf));
return STATUS_ERROR;
}
/*
- * Make a copy of static getpw*() result area; this is our authenticated
- * identity. Set it before calling check_usermap, because
authentication
- * has already succeeded and we want the log file to reflect that.
+ * Make a copy of result; this is our authenticated identity. Set it
+ * before calling check_usermap, because authentication has already
+ * succeeded and we want the log file to reflect that.
*/
- set_authn_id(port, pw->pw_name);
+ set_authn_id(port, pwdbuf);
ret = check_usermap(port->hba->usermap, port->user_name,
MyClientConnectionInfo.authn_id, false);
--
2.46.0