Re: Overlength socket paths (was Re: [COMMITTERS] pgsql: Refactor flex and bison make rules) - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Re: Overlength socket paths (was Re: [COMMITTERS] pgsql: Refactor flex and bison make rules) |
Date | |
Msg-id | 22387.1354234853@sss.pgh.pa.us Whole thread Raw |
In response to | Re: Overlength socket paths (was Re: [COMMITTERS] pgsql: Refactor flex and bison make rules) (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-hackers |
Tom Lane <tgl@sss.pgh.pa.us> writes: > Andrew Dunstan <andrew@dunslane.net> writes: >> ... Or maybe the >> postmaster needs to check the length somehow before it calls >> StreamServerPort() so we can give a saner error message. > Hm. That's ugly, but a lot less invasive than trying to get the > official API to pass the information through. Sounds like a plan to me. Here's a patch for that --- I think we should apply and back-patch this. regards, tom lane diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 5e86987f221fee01c5049f925492e0f9c441d372..15a01a8324b8a6ff9727a1b02e7ba8fe385d3a39 100644 *** a/src/backend/libpq/pqcomm.c --- b/src/backend/libpq/pqcomm.c *************** StreamServerPort(int family, char *hostN *** 308,313 **** --- 308,321 ---- * that file path */ UNIXSOCK_PATH(unixSocketPath, portNumber, unixSocketDir); + if (strlen(unixSocketPath) >= UNIXSOCK_PATH_BUFLEN) + { + ereport(LOG, + (errmsg("Unix-domain socket path \"%s\" is too long (maximum %d bytes)", + unixSocketPath, + (int) (UNIXSOCK_PATH_BUFLEN - 1)))); + return STATUS_ERROR; + } if (Lock_AF_UNIX(unixSocketDir, unixSocketPath) != STATUS_OK) return STATUS_ERROR; service = unixSocketPath; diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index 604b5535df6b24885b782688fee9ff7fd284746b..635132dec9317b4045108c75cd8c67a70c360968 100644 *** a/src/include/libpq/pqcomm.h --- b/src/include/libpq/pqcomm.h *************** typedef struct *** 74,79 **** --- 74,92 ---- (port)) /* + * The maximum workable length of a socket path is what will fit into + * struct sockaddr_un. This is usually only 100 or so bytes :-(. + * + * For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(), + * then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes. + * (Because the standard API for getaddrinfo doesn't allow it to complain in + * a useful way when the socket pathname is too long, we have to test for + * this explicitly, instead of just letting the subroutine return an error.) + */ + #define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path) + + + /* * These manipulate the frontend/backend protocol version number. * * The major number should be incremented for incompatible changes. The minor diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 9eaf41025beb652c6c242035490d93319a6bc5d0..1386bb791a96fab087af1ba33546ab89772327fd 100644 *** a/src/interfaces/libpq/fe-connect.c --- b/src/interfaces/libpq/fe-connect.c *************** static int *** 1322,1328 **** connectDBStart(PGconn *conn) { int portnum; ! char portstr[128]; struct addrinfo *addrs = NULL; struct addrinfo hint; const char *node; --- 1322,1328 ---- connectDBStart(PGconn *conn) { int portnum; ! char portstr[MAXPGPATH]; struct addrinfo *addrs = NULL; struct addrinfo hint; const char *node; *************** connectDBStart(PGconn *conn) *** 1384,1389 **** --- 1384,1398 ---- node = NULL; hint.ai_family = AF_UNIX; UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket); + if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"), + portstr, + (int) (UNIXSOCK_PATH_BUFLEN - 1)); + conn->options_valid = false; + goto connect_errReturn; + } #else /* Without Unix sockets, default to localhost instead */ node = DefaultHost;
pgsql-hackers by date: