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:

Previous
From: Tom Lane
Date:
Subject: Re: Overlength socket paths (was Re: [COMMITTERS] pgsql: Refactor flex and bison make rules)
Next
From: Andrew Dunstan
Date:
Subject: Re: Overlength socket paths (was Re: [COMMITTERS] pgsql: Refactor flex and bison make rules)