Re: PostgreSQL Service on Windows does not start. ~ "is not a valid Win32 application"

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: PostgreSQL Service on Windows does not start. ~ "is not a valid Win32 application"
Дата
Msg-id 4415.1385260745@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: PostgreSQL Service on Windows does not start. ~ "is not a valid Win32 application"  (Rajeev rastogi <rajeev.rastogi@huawei.com>)
Ответы Re: PostgreSQL Service on Windows does not start. ~ "is not a valid Win32 application"  (Christian Ullrich <chris@chrullrich.net>)
Re: PostgreSQL Service on Windows does not start. ~ "is not a valid Win32 application"  (Rajeev rastogi <rajeev.rastogi@huawei.com>)
Список pgsql-hackers
Rajeev rastogi <rajeev.rastogi@huawei.com> writes:
> One suggestion:
> Instead of using sizeof(cmdLine),
>     a. Can't we use strlen  (hence small 'for' loop).
>     b. Or use memmove to move one byte.

I looked at this patch a bit.  I agree that we need to fix
pgwin32_CommandLine to double-quote the executable name, but it needs a
great deal more work than that :-(.  Whoever wrote this code was
apparently unacquainted with the concept of buffer overrun.  It's not
going to be hard at all to crash pg_ctl with overlength arguments.  I'm
not sure that that amounts to a security bug, but it's certainly bad.

After some thought it seems like the most future-proof fix is to not
use a fixed-length buffer for the command string at all.  The attached
revised patch switches it over to using a PQExpBuffer instead, which is
pretty much free since we're relying on libpq anyway in this program.
(We still use a fixed-length buffer for the program path, which is OK
because that's what find_my_exec and find_other_exec expect.)

In addition, I fixed it to append .exe in both cases not just the one.

I'm not in a position to actually test this, but it does compile
without warnings.

            regards, tom lane

diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 8399cdd..dd80719 100644
*** a/src/bin/pg_ctl/pg_ctl.c
--- b/src/bin/pg_ctl/pg_ctl.c
***************
*** 18,24 ****
--- 18,26 ----
  #endif

  #include "postgres_fe.h"
+
  #include "libpq-fe.h"
+ #include "pqexpbuffer.h"

  #include <fcntl.h>
  #include <locale.h>
*************** pgwin32_IsInstalled(SC_HANDLE hSCM)
*** 1238,1253 ****
  static char *
  pgwin32_CommandLine(bool registration)
  {
!     static char cmdLine[MAXPGPATH];
      int            ret;

- #ifdef __CYGWIN__
-     char        buf[MAXPGPATH];
- #endif
-
      if (registration)
      {
!         ret = find_my_exec(argv0, cmdLine);
          if (ret != 0)
          {
              write_stderr(_("%s: could not find own program executable\n"), progname);
--- 1240,1252 ----
  static char *
  pgwin32_CommandLine(bool registration)
  {
!     PQExpBuffer cmdLine = createPQExpBuffer();
!     char        cmdPath[MAXPGPATH];
      int            ret;

      if (registration)
      {
!         ret = find_my_exec(argv0, cmdPath);
          if (ret != 0)
          {
              write_stderr(_("%s: could not find own program executable\n"), progname);
*************** pgwin32_CommandLine(bool registration)
*** 1257,1263 ****
      else
      {
          ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
!                               cmdLine);
          if (ret != 0)
          {
              write_stderr(_("%s: could not find postgres program executable\n"), progname);
--- 1256,1262 ----
      else
      {
          ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
!                               cmdPath);
          if (ret != 0)
          {
              write_stderr(_("%s: could not find postgres program executable\n"), progname);
*************** pgwin32_CommandLine(bool registration)
*** 1267,1320 ****

  #ifdef __CYGWIN__
      /* need to convert to windows path */
  #if CYGWIN_VERSION_DLL_MAJOR >= 1007
!     cygwin_conv_path(CCP_POSIX_TO_WIN_A, cmdLine, buf, sizeof(buf));
  #else
!     cygwin_conv_to_full_win32_path(cmdLine, buf);
  #endif
!     strcpy(cmdLine, buf);
  #endif

      if (registration)
!     {
!         if (pg_strcasecmp(cmdLine + strlen(cmdLine) - 4, ".exe") != 0)
!         {
!             /* If commandline does not end in .exe, append it */
!             strcat(cmdLine, ".exe");
!         }
!         strcat(cmdLine, " runservice -N \"");
!         strcat(cmdLine, register_servicename);
!         strcat(cmdLine, "\"");
!     }

      if (pg_config)
!     {
!         strcat(cmdLine, " -D \"");
!         strcat(cmdLine, pg_config);
!         strcat(cmdLine, "\"");
!     }

      if (registration && do_wait)
!         strcat(cmdLine, " -w");

      if (registration && wait_seconds != DEFAULT_WAIT)
!         /* concatenate */
!         sprintf(cmdLine + strlen(cmdLine), " -t %d", wait_seconds);

      if (registration && silent_mode)
!         strcat(cmdLine, " -s");

      if (post_opts)
      {
-         strcat(cmdLine, " ");
-         if (registration)
-             strcat(cmdLine, " -o \"");
-         strcat(cmdLine, post_opts);
          if (registration)
!             strcat(cmdLine, "\"");
      }

!     return cmdLine;
  }

  static void
--- 1266,1319 ----

  #ifdef __CYGWIN__
      /* need to convert to windows path */
+     {
+         char        buf[MAXPGPATH];
+
  #if CYGWIN_VERSION_DLL_MAJOR >= 1007
!         cygwin_conv_path(CCP_POSIX_TO_WIN_A, cmdPath, buf, sizeof(buf));
  #else
!         cygwin_conv_to_full_win32_path(cmdPath, buf);
  #endif
!         strcpy(cmdPath, buf);
!     }
  #endif

+     /* if path does not end in .exe, append it */
+     if (strlen(cmdPath) < 4 ||
+         pg_strcasecmp(cmdPath + strlen(cmdPath) - 4, ".exe") != 0)
+         snprintf(cmdPath + strlen(cmdPath), sizeof(cmdPath) - strlen(cmdPath),
+                  ".exe");
+
+     /* be sure to double-quote the executable's name in the command */
+     appendPQExpBuffer(cmdLine, "\"%s\"", cmdPath);
+
+     /* append assorted switches to the command line, as needed */
+
      if (registration)
!         appendPQExpBuffer(cmdLine, " runservice -N \"%s\"",
!                           register_servicename);

      if (pg_config)
!         appendPQExpBuffer(cmdLine, " -D \"%s\"", pg_config);

      if (registration && do_wait)
!         appendPQExpBuffer(cmdLine, " -w");

      if (registration && wait_seconds != DEFAULT_WAIT)
!         appendPQExpBuffer(cmdLine, " -t %d", wait_seconds);

      if (registration && silent_mode)
!         appendPQExpBuffer(cmdLine, " -s");

      if (post_opts)
      {
          if (registration)
!             appendPQExpBuffer(cmdLine, " -o \"%s\"", post_opts);
!         else
!             appendPQExpBuffer(cmdLine, " %s", post_opts);
      }

!     return cmdLine->data;
  }

  static void
*************** CreateRestrictedProcess(char *cmd, PROCE
*** 1745,1751 ****
       */
      return r;
  }
! #endif

  static void
  do_advice(void)
--- 1744,1750 ----
       */
      return r;
  }
! #endif    /* defined(WIN32) || defined(__CYGWIN__) */

  static void
  do_advice(void)

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Peter Eisentraut
Дата:
Сообщение: Re: Completing PL support for Event Triggers
Следующее
От: Jeff Davis
Дата:
Сообщение: Re: Freezing without write I/O