An application was spawning a Unix process with CreateProcess (which returned success only when the stack was favorable; see the first patch) and then closing the handles from the PROCESS_INFORMATION, which were garbage. That obviously caused havoc elsewhere if those garbage values happened to be valid handles.
It's not quite clear to me what the "right" thing to do is when a Unix process is created this way, since it's kind of a hack. But we already zero out the PS_CREATE_INFO in NtCreateUserProcess, so zeroing the handles seems in keeping with that.
From: Tim Clem tclem@codeweavers.com
Otherwise, if the exec succeeds, the later read() will not actually read anything (EOF since the other end of the pipe is closed), and we'll returned the uninitialized value of `status`.
This was preventing NtCreateUserProcess for a Unix process from returning successfully, depending on the state of the stack, even if the fork/exec suceeded. --- dlls/ntdll/unix/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index c6bba1e17a0..5d899338a20 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -555,7 +555,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, const char *unix_name, i pid_t pid; int fd[2], stdin_fd = -1, stdout_fd = -1; char **argv, **envp; - NTSTATUS status; + NTSTATUS status = STATUS_SUCCESS;
#ifdef HAVE_PIPE2 if (pipe2( fd, O_CLOEXEC ) == -1)
From: Tim Clem tclem@codeweavers.com
Otherwise we will return success while potentially leaving them with garbage values, which the caller is likely to close. --- dlls/ntdll/unix/process.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 5d899338a20..3321640ba97 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -752,6 +752,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ { if (status == STATUS_INVALID_IMAGE_NOT_MZ && !fork_and_exec( &attr, unix_name, unixdir, params )) { + *process_handle_ptr = *thread_handle_ptr = 0; memset( info, 0, sizeof(*info) ); free( unix_name ); free( nt_name.Buffer );
From: Tim Clem tclem@codeweavers.com
If we end up creating a Unix process, not all of the values in this structure will (/can) be populated, and thus may be garbage. --- dlls/kernelbase/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 0b803792790..e1c28fc67ed 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -516,7 +516,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR WCHAR name[MAX_PATH]; WCHAR *p, *tidy_cmdline = cmd_line; RTL_USER_PROCESS_PARAMETERS *params = NULL; - RTL_USER_PROCESS_INFORMATION rtl_info; + RTL_USER_PROCESS_INFORMATION rtl_info = { 0 }; HANDLE parent = 0, debug = 0; ULONG nt_flags = 0; USHORT machine = 0;