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: