Fix to not allow Unix-domain socket path with invalid length.
authorMasaya Kawamoto <kawamoto@sraoss.co.jp>
Mon, 12 Sep 2022 09:18:21 +0000 (09:18 +0000)
committerMasaya Kawamoto <kawamoto@sraoss.co.jp>
Mon, 12 Sep 2022 09:21:12 +0000 (09:21 +0000)
src/main/pgpool_main.c

index ddaea718ca4968272f97a346a6878732b8ebc395..57750496f2b2d7e30b0477bb615af490e7d48d52 100644 (file)
@@ -120,6 +120,8 @@ typedef struct User1SignalSlot
 
 #define PGPOOLMAXLITSENQUEUELENGTH 10000
 
+#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
+
 static void signal_user1_to_parent_with_reason(User1SignalReason reason);
 
 static void FileUnlink(int code, Datum path);
@@ -233,6 +235,7 @@ int
 PgpoolMain(bool discard_status, bool clear_memcache_oidmaps)
 {
        int                     i;
+       char            unix_domain_socket_path[UNIXSOCK_PATH_BUFLEN + 1024];
 
        sigjmp_buf      local_sigjmp_buf;
 
@@ -260,13 +263,34 @@ PgpoolMain(bool discard_status, bool clear_memcache_oidmaps)
        on_system_exit(system_will_go_down, (Datum) NULL);
 
        /* set unix domain socket path for connections to pgpool */
-       snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/.s.PGSQL.%d",
+       memset(unix_domain_socket_path, 0, sizeof(unix_domain_socket_path));
+       snprintf(unix_domain_socket_path, sizeof(unix_domain_socket_path), "%s/.s.PGSQL.%d",
                         pool_config->socket_dir,
                         pool_config->port);
+       if (strlen(unix_domain_socket_path) >= UNIXSOCK_PATH_BUFLEN)
+       {
+               ereport(FATAL,
+                          (errmsg("could not create Unix-domain sockets"),
+                               errdetail("Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
+                               unix_domain_socket_path,
+                               (int) (UNIXSOCK_PATH_BUFLEN - 1))));
+       }
+       snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s",unix_domain_socket_path);
+
        /* set unix domain socket path for pgpool PCP communication */
-       snprintf(pcp_un_addr.sun_path, sizeof(pcp_un_addr.sun_path), "%s/.s.PGSQL.%d",
+       memset(unix_domain_socket_path, 0, sizeof(unix_domain_socket_path));
+       snprintf(unix_domain_socket_path, sizeof(unix_domain_socket_path), "%s/.s.PGSQL.%d",
                         pool_config->pcp_socket_dir,
                         pool_config->pcp_port);
+       if (strlen(unix_domain_socket_path) >= UNIXSOCK_PATH_BUFLEN)
+       {
+               ereport(FATAL,
+                          (errmsg("could not create PCP Unix-domain sockets"),
+                               errdetail("PCP Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
+                               unix_domain_socket_path,
+                               (int) (UNIXSOCK_PATH_BUFLEN - 1))));
+       }
+       snprintf(pcp_un_addr.sun_path, sizeof(pcp_un_addr.sun_path), "%s",unix_domain_socket_path);
 
        /* set up signal handlers */
        pool_signal(SIGPIPE, SIG_IGN);