Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4af446e

Browse files
committed
Produce a more useful error message for over-length Unix socket paths.
The length of a socket path name is constrained by the size of struct sockaddr_un, and there's not a lot we can do about it since that is a kernel API. However, it would be a good thing if we produced an intelligible error message when the user specifies a socket path that's too long --- and getaddrinfo's standard API is too impoverished to do this in the natural way. So insert explicit tests at the places where we construct a socket path name. Now you'll get an error that makes sense and even tells you what the limit is, rather than something generic like "Non-recoverable failure in name resolution". Per trouble report from Jeremy Drake and a fix idea from Andrew Dunstan.
1 parent d3fe599 commit 4af446e

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

src/backend/libpq/pqcomm.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
308308
* that file path
309309
*/
310310
UNIXSOCK_PATH(unixSocketPath, portNumber, unixSocketDir);
311+
if (strlen(unixSocketPath) >= UNIXSOCK_PATH_BUFLEN)
312+
{
313+
ereport(LOG,
314+
(errmsg("Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
315+
unixSocketPath,
316+
(int) (UNIXSOCK_PATH_BUFLEN - 1))));
317+
return STATUS_ERROR;
318+
}
311319
if (Lock_AF_UNIX(unixSocketDir, unixSocketPath) != STATUS_OK)
312320
return STATUS_ERROR;
313321
service = unixSocketPath;

src/include/libpq/pqcomm.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ typedef struct
7373
DEFAULT_PGSOCKET_DIR, \
7474
(port))
7575

76+
/*
77+
* The maximum workable length of a socket path is what will fit into
78+
* struct sockaddr_un. This is usually only 100 or so bytes :-(.
79+
*
80+
* For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(),
81+
* then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes.
82+
* (Because the standard API for getaddrinfo doesn't allow it to complain in
83+
* a useful way when the socket pathname is too long, we have to test for
84+
* this explicitly, instead of just letting the subroutine return an error.)
85+
*/
86+
#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
87+
88+
7689
/*
7790
* These manipulate the frontend/backend protocol version number.
7891
*

src/interfaces/libpq/fe-connect.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ static int
13221322
connectDBStart(PGconn *conn)
13231323
{
13241324
int portnum;
1325-
char portstr[128];
1325+
char portstr[MAXPGPATH];
13261326
struct addrinfo *addrs = NULL;
13271327
struct addrinfo hint;
13281328
const char *node;
@@ -1384,6 +1384,15 @@ connectDBStart(PGconn *conn)
13841384
node = NULL;
13851385
hint.ai_family = AF_UNIX;
13861386
UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
1387+
if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
1388+
{
1389+
appendPQExpBuffer(&conn->errorMessage,
1390+
libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
1391+
portstr,
1392+
(int) (UNIXSOCK_PATH_BUFLEN - 1));
1393+
conn->options_valid = false;
1394+
goto connect_errReturn;
1395+
}
13871396
#else
13881397
/* Without Unix sockets, default to localhost instead */
13891398
node = DefaultHost;

0 commit comments

Comments
 (0)