From ce608dcbf7a8e49a9f6b7f1c6d6d3be9f587275a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Mon, 11 Nov 2024 18:39:08 +0100 Subject: [PATCH] Windows: Avoid child processes inheriting all file handles --- platform/windows/os_windows.cpp | 89 ++++++++++++++++++++++++--------- platform/windows/os_windows.h | 2 +- 2 files changed, 67 insertions(+), 24 deletions(-) diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 7572912cf6f..27a7e4573db 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -840,18 +840,10 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List &p_arguments, ProcessInfo pi; ZeroMemory(&pi.si, sizeof(pi.si)); - pi.si.cb = sizeof(pi.si); + pi.si.StartupInfo.cb = sizeof(pi.si); ZeroMemory(&pi.pi, sizeof(pi.pi)); - LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; + LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo; bool inherit_handles = false; HANDLE pipe[2] = { nullptr, nullptr }; @@ -924,16 +939,40 @@ Error OS_Windows::execute(const String &p_path, const List &p_arguments, sa.lpSecurityDescriptor = nullptr; ERR_FAIL_COND_V(!CreatePipe(&pipe[0], &pipe[1], &sa, 0), ERR_CANT_FORK); - ERR_FAIL_COND_V(!SetHandleInformation(pipe[0], HANDLE_FLAG_INHERIT, 0), ERR_CANT_FORK); // Read handle is for host process only and should not be inherited. - pi.si.dwFlags |= STARTF_USESTDHANDLES; - pi.si.hStdOutput = pipe[1]; + pi.si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + pi.si.StartupInfo.hStdOutput = pipe[1]; if (read_stderr) { - pi.si.hStdError = pipe[1]; + pi.si.StartupInfo.hStdError = pipe[1]; + } + + size_t attr_list_size = 0; + InitializeProcThreadAttributeList(nullptr, 1, 0, &attr_list_size); + pi.si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(attr_list_size); + if (!InitializeProcThreadAttributeList(pi.si.lpAttributeList, 1, 0, &attr_list_size)) { + CloseHandle(pipe[0]); // Cleanup pipe handles. + CloseHandle(pipe[1]); + ERR_FAIL_V(ERR_CANT_FORK); + } + if (!UpdateProcThreadAttribute( + pi.si.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + &pipe[1], + sizeof(HANDLE), + nullptr, + nullptr)) { + CloseHandle(pipe[0]); // Cleanup pipe handles. + CloseHandle(pipe[1]); + DeleteProcThreadAttributeList(pi.si.lpAttributeList); + ERR_FAIL_V(ERR_CANT_FORK); } inherit_handles = true; } DWORD creation_flags = NORMAL_PRIORITY_CLASS; + if (inherit_handles) { + creation_flags |= EXTENDED_STARTUPINFO_PRESENT; + } if (p_open_console) { creation_flags |= CREATE_NEW_CONSOLE; } else { @@ -944,6 +983,7 @@ Error OS_Windows::execute(const String &p_path, const List &p_arguments, if (!ret && r_pipe) { CloseHandle(pipe[0]); // Cleanup pipe handles. CloseHandle(pipe[1]); + DeleteProcThreadAttributeList(pi.si.lpAttributeList); } ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); @@ -999,6 +1039,9 @@ Error OS_Windows::execute(const String &p_path, const List &p_arguments, CloseHandle(pi.pi.hProcess); CloseHandle(pi.pi.hThread); + if (r_pipe) { + DeleteProcThreadAttributeList(pi.si.lpAttributeList); + } return OK; } @@ -1012,9 +1055,9 @@ Error OS_Windows::create_process(const String &p_path, const List &p_arg ProcessInfo pi; ZeroMemory(&pi.si, sizeof(pi.si)); - pi.si.cb = sizeof(pi.si); + pi.si.StartupInfo.cb = sizeof(pi.si.StartupInfo); ZeroMemory(&pi.pi, sizeof(pi.pi)); - LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; + LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo; DWORD creation_flags = NORMAL_PRIORITY_CLASS; if (p_open_console) { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index b6a21ed42dd..a2d1e2fa6af 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -148,7 +148,7 @@ protected: String _quote_command_line_argument(const String &p_text) const; struct ProcessInfo { - STARTUPINFO si; + STARTUPINFOEX si; PROCESS_INFORMATION pi; mutable bool is_running = true; mutable int exit_code = -1;