1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-18 14:17:03 +01:00

try to control inherited HANDLE for new Windows.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2022-11-18 14:29:13 +09:00
parent 4736debd01
commit f5eb3710b4
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
2 changed files with 100 additions and 36 deletions

View File

@ -33,6 +33,8 @@
#if !defined(HAVE_W32_SYSTEM) #if !defined(HAVE_W32_SYSTEM)
#error This code is only used on W32. #error This code is only used on W32.
#else
#define _WIN32_WINNT 0x602
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -63,9 +65,11 @@
#include "util.h" #include "util.h"
#include "i18n.h" #include "i18n.h"
#include "sysutils.h" #include "sysutils.h"
#define NEED_STRUCT_SPAWN_CB_ARG
#include "exechelp.h" #include "exechelp.h"
#include <windows.h> #include <windows.h>
#include <processthreadsapi.h>
/* Define to 1 do enable debugging. */ /* Define to 1 do enable debugging. */
#define DEBUG_W32_SPAWN 0 #define DEBUG_W32_SPAWN 0
@ -1098,13 +1102,14 @@ spawn_detached (gnupg_process_t process,
{ {
SECURITY_ATTRIBUTES sec_attr; SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
STARTUPINFOW si; STARTUPINFOEXW si;
int cr_flags; int cr_flags;
wchar_t *wcmdline = NULL; wchar_t *wcmdline = NULL;
wchar_t *wpgmname = NULL; wchar_t *wpgmname = NULL;
int ask_inherit = 0; BOOL ask_inherit = FALSE;
gpg_err_code_t ec; gpg_err_code_t ec;
int ret; int ret;
struct spawn_cb_arg sca;
ec = gnupg_access (pgmname, X_OK); ec = gnupg_access (pgmname, X_OK);
if (ec) if (ec)
@ -1114,23 +1119,23 @@ spawn_detached (gnupg_process_t process,
return ec; return ec;
} }
if (spawn_cb) memset (&si, 0, sizeof si);
ask_inherit = (*spawn_cb) (spawn_cb_arg);
sca.plpAttributeList = &si.lpAttributeList;
sca.arg = spawn_cb_arg;
sca.hd[0] = INVALID_HANDLE_VALUE;
if (spawn_cb && (*spawn_cb) (&sca))
ask_inherit = TRUE;
/* Prepare security attributes. */ /* Prepare security attributes. */
memset (&sec_attr, 0, sizeof sec_attr ); memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr; sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE;
if (ask_inherit)
sec_attr.bInheritHandle = TRUE;
else
sec_attr.bInheritHandle = FALSE;
/* Start the process. */ /* Start the process. */
memset (&si, 0, sizeof si); si.StartupInfo.cb = sizeof (si);
si.cb = sizeof (si); si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
si.dwFlags = STARTF_USESHOWWINDOW; si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
cr_flags = (CREATE_DEFAULT_ERROR_MODE cr_flags = (CREATE_DEFAULT_ERROR_MODE
| GetPriorityClass (GetCurrentProcess ()) | GetPriorityClass (GetCurrentProcess ())
@ -1149,11 +1154,11 @@ spawn_detached (gnupg_process_t process,
wcmdline, /* Command line arguments. */ wcmdline, /* Command line arguments. */
&sec_attr, /* Process security attributes. */ &sec_attr, /* Process security attributes. */
&sec_attr, /* Thread security attributes. */ &sec_attr, /* Thread security attributes. */
FALSE, /* Inherit handles. */ ask_inherit, /* Inherit handles. */
cr_flags, /* Creation flags. */ cr_flags, /* Creation flags. */
NULL, /* Environment. */ NULL, /* Environment. */
NULL, /* Use current drive/directory. */ NULL, /* Use current drive/directory. */
&si, /* Startup information. */ (STARTUPINFOW *)&si, /* Startup information. */
&pi /* Returns process information. */ &pi /* Returns process information. */
); );
if (!ret) if (!ret)
@ -1169,6 +1174,8 @@ spawn_detached (gnupg_process_t process,
xfree (cmdline); xfree (cmdline);
return GPG_ERR_GENERAL; return GPG_ERR_GENERAL;
} }
if (si.lpAttributeList)
DeleteProcThreadAttributeList (si.lpAttributeList);
xfree (wpgmname); xfree (wpgmname);
xfree (wcmdline); xfree (wcmdline);
xfree (cmdline); xfree (cmdline);
@ -1202,16 +1209,18 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
gnupg_process_t process; gnupg_process_t process;
SECURITY_ATTRIBUTES sec_attr; SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
STARTUPINFOW si; STARTUPINFOEXW si;
int cr_flags; int cr_flags;
char *cmdline; char *cmdline;
wchar_t *wcmdline = NULL; wchar_t *wcmdline = NULL;
wchar_t *wpgmname = NULL; wchar_t *wpgmname = NULL;
int ret; int ret;
int ask_inherit = 0; BOOL ask_inherit = FALSE;
HANDLE hd_in[2]; HANDLE hd_in[2];
HANDLE hd_out[2]; HANDLE hd_out[2];
HANDLE hd_err[2]; HANDLE hd_err[2];
struct spawn_cb_arg sca;
int i;
check_syscall_func (); check_syscall_func ();
@ -1224,7 +1233,10 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
process = xtrymalloc (sizeof (struct gnupg_process)); process = xtrymalloc (sizeof (struct gnupg_process));
if (process == NULL) if (process == NULL)
return gpg_err_code_from_syserror (); {
xfree (cmdline);
return gpg_err_code_from_syserror ();
}
process->pgmname = pgmname; process->pgmname = pgmname;
process->flags = flags; process->flags = flags;
@ -1324,26 +1336,67 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
hd_err[1] = GetStdHandle (STD_ERROR_HANDLE); hd_err[1] = GetStdHandle (STD_ERROR_HANDLE);
} }
if (spawn_cb) memset (&si, 0, sizeof si);
ask_inherit = (*spawn_cb) (spawn_cb_arg);
sca.plpAttributeList = &si.lpAttributeList;
sca.arg = spawn_cb_arg;
i = 0;
if (hd_in[0] != INVALID_HANDLE_VALUE)
sca.hd[i++] = hd_in[0];
if (hd_out[1] != INVALID_HANDLE_VALUE)
sca.hd[i++] = hd_out[1];
if (hd_err[1] != INVALID_HANDLE_VALUE)
sca.hd[i++] = hd_err[1];
sca.hd[i] = INVALID_HANDLE_VALUE;
if (spawn_cb && (*spawn_cb) (&sca))
ask_inherit = TRUE;
else if (i != 0)
{
SIZE_T attr_list_size = 0;
InitializeProcThreadAttributeList (NULL, 1, 0, &attr_list_size);
si.lpAttributeList = xtrymalloc (attr_list_size);
if (si.lpAttributeList == NULL)
{
if (hd_in[0] != INVALID_HANDLE_VALUE)
CloseHandle (hd_in[0]);
if (hd_in[1] != INVALID_HANDLE_VALUE)
CloseHandle (hd_in[1]);
if (hd_out[0] != INVALID_HANDLE_VALUE)
CloseHandle (hd_out[0]);
if (hd_out[1] != INVALID_HANDLE_VALUE)
CloseHandle (hd_out[1]);
if (hd_err[0] != INVALID_HANDLE_VALUE)
CloseHandle (hd_err[0]);
if (hd_err[1] != INVALID_HANDLE_VALUE)
CloseHandle (hd_err[1]);
xfree (wpgmname);
xfree (wcmdline);
xfree (process);
xfree (cmdline);
return gpg_err_code_from_syserror ();
}
InitializeProcThreadAttributeList (si.lpAttributeList, 1, 0,
&attr_list_size);
UpdateProcThreadAttribute (si.lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
sca.hd, sizeof (HANDLE) * i, NULL, NULL);
ask_inherit = TRUE;
}
/* Prepare security attributes. */ /* Prepare security attributes. */
memset (&sec_attr, 0, sizeof sec_attr ); memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr; sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE;
if (ask_inherit)
sec_attr.bInheritHandle = TRUE;
else
sec_attr.bInheritHandle = FALSE;
/* Start the process. */ /* Start the process. */
memset (&si, 0, sizeof si); si.StartupInfo.cb = sizeof (si);
si.cb = sizeof (si); si.StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE;
si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE; si.StartupInfo.hStdInput = hd_in[0];
si.hStdInput = hd_in[0]; si.StartupInfo.hStdOutput = hd_out[1];
si.hStdOutput = hd_out[1]; si.StartupInfo.hStdError = hd_err[1];
si.hStdError = hd_err[1];
log_debug ("CreateProcess, path='%s' cmdline='%s'\n", log_debug ("CreateProcess, path='%s' cmdline='%s'\n",
pgmname, cmdline); pgmname, cmdline);
@ -1355,15 +1408,15 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
else if (!(wcmdline = utf8_to_wchar (cmdline))) else if (!(wcmdline = utf8_to_wchar (cmdline)))
ret = 0; ret = 0;
else else
ret = CreateProcessW (wpgmname, /* Program to start. */ ret = CreateProcessW (wpgmname, /* Program to start. */
wcmdline, /* Command line arguments. */ wcmdline, /* Command line arguments. */
&sec_attr, /* Process security attributes. */ &sec_attr, /* Process security attributes. */
&sec_attr, /* Thread security attributes. */ &sec_attr, /* Thread security attributes. */
TRUE, /* Inherit handles. */ ask_inherit, /* Inherit handles. */
cr_flags, /* Creation flags. */ cr_flags, /* Creation flags. */
NULL, /* Environment. */ NULL, /* Environment. */
NULL, /* Use current drive/directory. */ NULL, /* Use current drive/directory. */
&si, /* Startup information. */ (STARTUPINFOW *)&si, /* Startup information. */
&pi /* Returns process information. */ &pi /* Returns process information. */
); );
if (!ret) if (!ret)
@ -1393,6 +1446,8 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
return GPG_ERR_GENERAL; return GPG_ERR_GENERAL;
} }
if (si.lpAttributeList)
DeleteProcThreadAttributeList (si.lpAttributeList);
xfree (wpgmname); xfree (wpgmname);
xfree (wcmdline); xfree (wcmdline);
xfree (cmdline); xfree (cmdline);

View File

@ -210,6 +210,15 @@ gpg_error_t gnupg_spawn_process_detached (const char *pgmname,
/* The opaque type for a subprocess. */ /* The opaque type for a subprocess. */
typedef struct gnupg_process *gnupg_process_t; typedef struct gnupg_process *gnupg_process_t;
#ifdef HAVE_W32_SYSTEM
#ifdef NEED_STRUCT_SPAWN_CB_ARG
struct spawn_cb_arg {
void *plpAttributeList;
HANDLE hd[16];
void *arg;
};
#endif
#endif
/* Internal flag to ihnerit file descriptor/handle */ /* Internal flag to ihnerit file descriptor/handle */
#define GNUPG_PROCESS_INHERIT_FILE (1 << 0) #define GNUPG_PROCESS_INHERIT_FILE (1 << 0)