-- v3: ntdll: Do not fail NtCreateUserProcess() if requested access doesn't have PROCESS_CREATE_THREAD.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/thread.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/dlls/ntdll/tests/thread.c b/dlls/ntdll/tests/thread.c index a7ccf51e5e2..567a94a583d 100644 --- a/dlls/ntdll/tests/thread.c +++ b/dlls/ntdll/tests/thread.c @@ -204,6 +204,44 @@ static void test_errno(void) ok( val == 0xbeef, "wrong value %x\n", val ); }
+static void test_NtCreateUserProcess(void) +{ + RTL_USER_PROCESS_PARAMETERS *params; + PS_CREATE_INFO create_info; + PS_ATTRIBUTE_LIST ps_attr; + WCHAR path[MAX_PATH + 4]; + HANDLE process, thread; + UNICODE_STRING imageW; + NTSTATUS status; + + lstrcpyW( path, L"\??\" ); + GetModuleFileNameW( NULL, path + 4, MAX_PATH ); + + RtlInitUnicodeString( &imageW, path ); + + memset( &ps_attr, 0, sizeof(ps_attr) ); + ps_attr.Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME; + ps_attr.Attributes[0].Size = lstrlenW(path) * sizeof(WCHAR); + ps_attr.Attributes[0].ValuePtr = path; + ps_attr.TotalLength = sizeof(ps_attr); + + status = RtlCreateProcessParametersEx( ¶ms, &imageW, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, PROCESS_PARAMS_FLAG_NORMALIZED ); + ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + + memset( &create_info, 0, sizeof(create_info) ); + create_info.Size = sizeof(create_info); + status = NtCreateUserProcess( &process, &thread, PROCESS_TERMINATE, SYNCHRONIZE, + NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params, + &create_info, &ps_attr ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + status = NtTerminateProcess( process, 0 ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + CloseHandle( process ); + CloseHandle( thread ); +} + START_TEST(thread) { init_function_pointers(); @@ -211,4 +249,5 @@ START_TEST(thread) test_dbg_hidden_thread_creation(); test_unique_teb(); test_errno(); + test_NtCreateUserProcess(); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/thread.c | 4 ++-- server/thread.c | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/thread.c b/dlls/ntdll/tests/thread.c index 567a94a583d..f7806e0fe62 100644 --- a/dlls/ntdll/tests/thread.c +++ b/dlls/ntdll/tests/thread.c @@ -235,9 +235,9 @@ static void test_NtCreateUserProcess(void) status = NtCreateUserProcess( &process, &thread, PROCESS_TERMINATE, SYNCHRONIZE, NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params, &create_info, &ps_attr ); - todo_wine ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); status = NtTerminateProcess( process, 0 ); - todo_wine ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); CloseHandle( process ); CloseHandle( thread ); } diff --git a/server/thread.c b/server/thread.c index 5ad060108e3..8ffe7ffdb33 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1520,12 +1520,19 @@ DECL_HANDLER(new_thread) const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); int request_fd = thread_get_inflight_fd( current, req->request_fd );
- if (!(process = get_process_from_handle( req->process, PROCESS_CREATE_THREAD ))) + if (!(process = get_process_from_handle( req->process, 0 ))) { if (request_fd != -1) close( request_fd ); return; }
+ if (process->running_threads && !(get_handle_access( current->process, req->process ) & PROCESS_CREATE_THREAD)) + { + if (request_fd != -1) close( request_fd ); + set_error( STATUS_ACCESS_DENIED ); + goto done; + } + if (process != current->process) { if (request_fd != -1) /* can't create a request fd in a different process */
v3: - reuse process->running_threads instead of adding a new flag.