Skip to content

Commit 4d5111b

Browse files
committed
More use of getpwuid_r() directly
Remove src/port/user.c, call getpwuid_r() directly. This reduces some complexity and allows better control of the error behavior. For example, the old code would in some circumstances silently truncate the result string, or produce error message strings that the caller wouldn't use. src/port/user.c used to be called src/port/thread.c and contained various portability complications to support thread-safety. These are all obsolete, and all but the user-lookup functions have already been removed. This patch completes this by also removing the user-lookup functions. Also convert src/backend/libpq/auth.c to use getpwuid_r() for thread-safety. Originally, I tried to be overly correct by using sysconf(_SC_GETPW_R_SIZE_MAX) to get the buffer size for getpwuid_r(), but that doesn't work on FreeBSD. All the OS where I could find the source code internally use 1024 as the suggested buffer size, so I just ended up hardcoding that. The previous code used BUFSIZ, which is an unrelated constant from stdio.h, so its use seemed inappropriate. Reviewed-by: Heikki Linnakangas <[email protected]> Discussion: https://www.postgresql.org/message-id/flat/5f293da9-ceb4-4937-8e52-82c25db8e4d3%40eisentraut.org
1 parent 2313828 commit 4d5111b

File tree

10 files changed

+72
-123
lines changed

10 files changed

+72
-123
lines changed

src/backend/libpq/auth.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -1857,7 +1857,10 @@ auth_peer(hbaPort *port)
18571857
uid_t uid;
18581858
gid_t gid;
18591859
#ifndef WIN32
1860+
struct passwd pwbuf;
18601861
struct passwd *pw;
1862+
char buf[1024];
1863+
int rc;
18611864
int ret;
18621865
#endif
18631866

@@ -1876,16 +1879,18 @@ auth_peer(hbaPort *port)
18761879
}
18771880

18781881
#ifndef WIN32
1879-
errno = 0; /* clear errno before call */
1880-
pw = getpwuid(uid);
1881-
if (!pw)
1882+
rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1883+
if (rc != 0)
1884+
{
1885+
errno = rc;
1886+
ereport(LOG,
1887+
errmsg("could not look up local user ID %ld: %m", (long) uid));
1888+
return STATUS_ERROR;
1889+
}
1890+
else if (!pw)
18821891
{
1883-
int save_errno = errno;
1884-
18851892
ereport(LOG,
1886-
(errmsg("could not look up local user ID %ld: %s",
1887-
(long) uid,
1888-
save_errno ? strerror(save_errno) : _("user does not exist"))));
1893+
errmsg("local user with ID %ld does not exist", (long) uid));
18891894
return STATUS_ERROR;
18901895
}
18911896

src/bin/psql/nls.mk

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \
2323
../../common/exec.c \
2424
../../common/fe_memutils.c \
2525
../../common/username.c \
26-
../../common/wait_error.c \
27-
../../port/user.c
26+
../../common/wait_error.c
2827
GETTEXT_TRIGGERS = $(FRONTEND_COMMON_GETTEXT_TRIGGERS) \
2928
HELP0 HELPN N_ simple_prompt simple_prompt_extended
3029
GETTEXT_FLAGS = $(FRONTEND_COMMON_GETTEXT_FLAGS) \

src/include/port.h

-6
Original file line numberDiff line numberDiff line change
@@ -436,12 +436,6 @@ extern size_t strnlen(const char *str, size_t maxlen);
436436
extern char *strsep(char **stringp, const char *delim);
437437
#endif
438438

439-
/* port/user.c */
440-
#ifndef WIN32
441-
extern bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen);
442-
extern bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen);
443-
#endif
444-
445439
/*
446440
* Callers should use the qsort() macro defined below instead of calling
447441
* pg_qsort() directly.

src/interfaces/libpq/fe-auth.c

+18-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <unistd.h>
2929
#include <fcntl.h>
3030
#include <limits.h>
31+
#include <pwd.h>
3132
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
3233
#include <sys/socket.h>
3334
#ifdef HAVE_SYS_UCRED_H
@@ -1203,7 +1204,10 @@ pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
12031204
char username[256 + 1];
12041205
DWORD namesize = sizeof(username);
12051206
#else
1206-
char pwdbuf[BUFSIZ];
1207+
struct passwd pwbuf;
1208+
struct passwd *pw;
1209+
char buf[1024];
1210+
int rc;
12071211
#endif
12081212

12091213
#ifdef WIN32
@@ -1214,10 +1218,19 @@ pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
12141218
"user name lookup failure: error code %lu",
12151219
GetLastError());
12161220
#else
1217-
if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf)))
1218-
name = pwdbuf;
1219-
else if (errorMessage)
1220-
appendPQExpBuffer(errorMessage, "%s\n", pwdbuf);
1221+
rc = getpwuid_r(user_id, &pwbuf, buf, sizeof buf, &pw);
1222+
if (rc != 0)
1223+
{
1224+
errno = rc;
1225+
if (errorMessage)
1226+
libpq_append_error(errorMessage, "could not look up local user ID %ld: %m", (long) user_id);
1227+
}
1228+
else if (!pw)
1229+
{
1230+
if (errorMessage)
1231+
libpq_append_error(errorMessage, "local user with ID %ld does not exist", (long) user_id);
1232+
}
1233+
name = pw->pw_name;
12211234
#endif
12221235

12231236
if (name)

src/interfaces/libpq/fe-connect.c

+19-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <netdb.h>
5151
#include <netinet/in.h>
5252
#include <netinet/tcp.h>
53+
#include <pwd.h>
5354
#endif
5455

5556
#ifdef WIN32
@@ -7702,10 +7703,24 @@ pqGetHomeDirectory(char *buf, int bufsize)
77027703
const char *home;
77037704

77047705
home = getenv("HOME");
7705-
if (home == NULL || home[0] == '\0')
7706-
return pg_get_user_home_dir(geteuid(), buf, bufsize);
7707-
strlcpy(buf, home, bufsize);
7708-
return true;
7706+
if (home && home[0])
7707+
{
7708+
strlcpy(buf, home, bufsize);
7709+
return true;
7710+
}
7711+
else
7712+
{
7713+
struct passwd pwbuf;
7714+
struct passwd *pw;
7715+
char tmpbuf[1024];
7716+
int rc;
7717+
7718+
rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
7719+
if (rc != 0 || !pw)
7720+
return false;
7721+
strlcpy(buf, pw->pw_dir, bufsize);
7722+
return true;
7723+
}
77097724
#else
77107725
char tmppath[MAX_PATH];
77117726

src/interfaces/libpq/nls.mk

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ GETTEXT_FILES = fe-auth.c \
1313
fe-secure-common.c \
1414
fe-secure-gssapi.c \
1515
fe-secure-openssl.c \
16-
win32.c \
17-
../../port/user.c
16+
win32.c
1817
GETTEXT_TRIGGERS = libpq_append_conn_error:2 \
1918
libpq_append_error:2 \
2019
libpq_gettext \

src/port/Makefile

+1-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ OBJS = \
5757
quotes.o \
5858
snprintf.o \
5959
strerror.o \
60-
tar.o \
61-
user.o
60+
tar.o
6261

6362
# libpgport.a, libpgport_shlib.a, and libpgport_srv.a contain the same files
6463
# foo.o, foo_shlib.o, and foo_srv.o are all built from foo.c

src/port/meson.build

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ pgport_sources = [
2020
'snprintf.c',
2121
'strerror.c',
2222
'tar.c',
23-
'user.c',
2423
]
2524

2625
if host_system == 'windows'

src/port/path.c

+19-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define near
3333
#include <shlobj.h>
3434
#else
35+
#include <pwd.h>
3536
#include <unistd.h>
3637
#endif
3738

@@ -934,10 +935,24 @@ get_home_path(char *ret_path)
934935
const char *home;
935936

936937
home = getenv("HOME");
937-
if (home == NULL || home[0] == '\0')
938-
return pg_get_user_home_dir(geteuid(), ret_path, MAXPGPATH);
939-
strlcpy(ret_path, home, MAXPGPATH);
940-
return true;
938+
if (home && home[0])
939+
{
940+
strlcpy(ret_path, home, MAXPGPATH);
941+
return true;
942+
}
943+
else
944+
{
945+
struct passwd pwbuf;
946+
struct passwd *pw;
947+
char buf[1024];
948+
int rc;
949+
950+
rc = getpwuid_r(geteuid(), &pwbuf, buf, sizeof buf, &pw);
951+
if (rc != 0 || !pw)
952+
return false;
953+
strlcpy(ret_path, pw->pw_dir, MAXPGPATH);
954+
return true;
955+
}
941956
#else
942957
char *tmppath;
943958

src/port/user.c

-89
This file was deleted.

0 commit comments

Comments
 (0)