Skip to content

Commit ce608dc

Browse files
committedNov 12, 2024·
Windows: Avoid child processes inheriting all file handles
1 parent 33c02a5 commit ce608dc

File tree

2 files changed

+67
-24
lines changed

2 files changed

+67
-24
lines changed
 

‎platform/windows/os_windows.cpp

+66-23
Original file line numberDiff line numberDiff line change
@@ -840,18 +840,10 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String
840840
sa.lpSecurityDescriptor = nullptr;
841841

842842
ERR_FAIL_COND_V(!CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0), ret);
843-
if (!SetHandleInformation(pipe_in[1], HANDLE_FLAG_INHERIT, 0)) {
844-
CLEAN_PIPES
845-
ERR_FAIL_V(ret);
846-
}
847843
if (!CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0)) {
848844
CLEAN_PIPES
849845
ERR_FAIL_V(ret);
850846
}
851-
if (!SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0)) {
852-
CLEAN_PIPES
853-
ERR_FAIL_V(ret);
854-
}
855847
if (!CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0)) {
856848
CLEAN_PIPES
857849
ERR_FAIL_V(ret);
@@ -861,24 +853,47 @@ Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String
861853
// Create process.
862854
ProcessInfo pi;
863855
ZeroMemory(&pi.si, sizeof(pi.si));
864-
pi.si.cb = sizeof(pi.si);
856+
pi.si.StartupInfo.cb = sizeof(pi.si);
865857
ZeroMemory(&pi.pi, sizeof(pi.pi));
866-
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
858+
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo;
867859

868-
pi.si.dwFlags |= STARTF_USESTDHANDLES;
869-
pi.si.hStdInput = pipe_in[0];
870-
pi.si.hStdOutput = pipe_out[1];
871-
pi.si.hStdError = pipe_err[1];
860+
pi.si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
861+
pi.si.StartupInfo.hStdInput = pipe_in[0];
862+
pi.si.StartupInfo.hStdOutput = pipe_out[1];
863+
pi.si.StartupInfo.hStdError = pipe_err[1];
872864

873-
DWORD creation_flags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW;
865+
size_t attr_list_size = 0;
866+
InitializeProcThreadAttributeList(nullptr, 1, 0, &attr_list_size);
867+
pi.si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(attr_list_size);
868+
if (!InitializeProcThreadAttributeList(pi.si.lpAttributeList, 1, 0, &attr_list_size)) {
869+
CLEAN_PIPES
870+
ERR_FAIL_V(ret);
871+
}
872+
HANDLE handles_to_inherit[] = { pipe_in[0], pipe_out[1], pipe_err[1] };
873+
if (!UpdateProcThreadAttribute(
874+
pi.si.lpAttributeList,
875+
0,
876+
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
877+
handles_to_inherit,
878+
sizeof(handles_to_inherit),
879+
nullptr,
880+
nullptr)) {
881+
CLEAN_PIPES
882+
DeleteProcThreadAttributeList(pi.si.lpAttributeList);
883+
ERR_FAIL_V(ret);
884+
}
885+
886+
DWORD creation_flags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT;
874887

875888
if (!CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, true, creation_flags, nullptr, nullptr, si_w, &pi.pi)) {
876889
CLEAN_PIPES
890+
DeleteProcThreadAttributeList(pi.si.lpAttributeList);
877891
ERR_FAIL_V_MSG(ret, "Could not create child process: " + command);
878892
}
879893
CloseHandle(pipe_in[0]);
880894
CloseHandle(pipe_out[1]);
881895
CloseHandle(pipe_err[1]);
896+
DeleteProcThreadAttributeList(pi.si.lpAttributeList);
882897

883898
ProcessID pid = pi.pi.dwProcessId;
884899
process_map_mutex.lock();
@@ -910,9 +925,9 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
910925

911926
ProcessInfo pi;
912927
ZeroMemory(&pi.si, sizeof(pi.si));
913-
pi.si.cb = sizeof(pi.si);
928+
pi.si.StartupInfo.cb = sizeof(pi.si);
914929
ZeroMemory(&pi.pi, sizeof(pi.pi));
915-
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
930+
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo;
916931

917932
bool inherit_handles = false;
918933
HANDLE pipe[2] = { nullptr, nullptr };
@@ -924,16 +939,40 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
924939
sa.lpSecurityDescriptor = nullptr;
925940

926941
ERR_FAIL_COND_V(!CreatePipe(&pipe[0], &pipe[1], &sa, 0), ERR_CANT_FORK);
927-
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.
928942

929-
pi.si.dwFlags |= STARTF_USESTDHANDLES;
930-
pi.si.hStdOutput = pipe[1];
943+
pi.si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
944+
pi.si.StartupInfo.hStdOutput = pipe[1];
931945
if (read_stderr) {
932-
pi.si.hStdError = pipe[1];
946+
pi.si.StartupInfo.hStdError = pipe[1];
947+
}
948+
949+
size_t attr_list_size = 0;
950+
InitializeProcThreadAttributeList(nullptr, 1, 0, &attr_list_size);
951+
pi.si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(attr_list_size);
952+
if (!InitializeProcThreadAttributeList(pi.si.lpAttributeList, 1, 0, &attr_list_size)) {
953+
CloseHandle(pipe[0]); // Cleanup pipe handles.
954+
CloseHandle(pipe[1]);
955+
ERR_FAIL_V(ERR_CANT_FORK);
956+
}
957+
if (!UpdateProcThreadAttribute(
958+
pi.si.lpAttributeList,
959+
0,
960+
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
961+
&pipe[1],
962+
sizeof(HANDLE),
963+
nullptr,
964+
nullptr)) {
965+
CloseHandle(pipe[0]); // Cleanup pipe handles.
966+
CloseHandle(pipe[1]);
967+
DeleteProcThreadAttributeList(pi.si.lpAttributeList);
968+
ERR_FAIL_V(ERR_CANT_FORK);
933969
}
934970
inherit_handles = true;
935971
}
936972
DWORD creation_flags = NORMAL_PRIORITY_CLASS;
973+
if (inherit_handles) {
974+
creation_flags |= EXTENDED_STARTUPINFO_PRESENT;
975+
}
937976
if (p_open_console) {
938977
creation_flags |= CREATE_NEW_CONSOLE;
939978
} else {
@@ -944,6 +983,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
944983
if (!ret && r_pipe) {
945984
CloseHandle(pipe[0]); // Cleanup pipe handles.
946985
CloseHandle(pipe[1]);
986+
DeleteProcThreadAttributeList(pi.si.lpAttributeList);
947987
}
948988
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
949989

@@ -999,6 +1039,9 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
9991039

10001040
CloseHandle(pi.pi.hProcess);
10011041
CloseHandle(pi.pi.hThread);
1042+
if (r_pipe) {
1043+
DeleteProcThreadAttributeList(pi.si.lpAttributeList);
1044+
}
10021045

10031046
return OK;
10041047
}
@@ -1012,9 +1055,9 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg
10121055

10131056
ProcessInfo pi;
10141057
ZeroMemory(&pi.si, sizeof(pi.si));
1015-
pi.si.cb = sizeof(pi.si);
1058+
pi.si.StartupInfo.cb = sizeof(pi.si.StartupInfo);
10161059
ZeroMemory(&pi.pi, sizeof(pi.pi));
1017-
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
1060+
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si.StartupInfo;
10181061

10191062
DWORD creation_flags = NORMAL_PRIORITY_CLASS;
10201063
if (p_open_console) {

‎platform/windows/os_windows.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class OS_Windows : public OS {
148148
String _quote_command_line_argument(const String &p_text) const;
149149

150150
struct ProcessInfo {
151-
STARTUPINFO si;
151+
STARTUPINFOEX si;
152152
PROCESS_INFORMATION pi;
153153
mutable bool is_running = true;
154154
mutable int exit_code = -1;

0 commit comments

Comments
 (0)
Please sign in to comment.