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

Reply via email to