From 0fd450af5bad816f7134b5ce6a5b81fb7b962b44 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 20 Sep 2018 13:19:49 +0200 Subject: [PATCH] server: Specify the process in which to create a new thread. Signed-off-by: Alexandre Julliard --- dlls/ntdll/thread.c | 1 + include/wine/server_protocol.h | 4 +++- server/protocol.def | 3 ++- server/request.h | 9 +++++---- server/thread.c | 31 +++++++++++++++++++++++++++---- server/trace.c | 3 ++- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 7fa087defe5..8171638c4af 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -605,6 +605,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, SERVER_START_REQ( new_thread ) { + req->process = wine_server_obj_handle( process ); req->access = THREAD_ALL_ACCESS; req->suspend = suspended; req->request_fd = request_pipe[0]; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index d31a1d48419..02734bcd8cc 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -766,10 +766,12 @@ struct get_new_process_info_reply struct new_thread_request { struct request_header __header; + obj_handle_t process; unsigned int access; int suspend; int request_fd; /* VARARG(objattr,object_attributes); */ + char __pad_28[4]; }; struct new_thread_reply { @@ -6534,6 +6536,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 561 +#define SERVER_PROTOCOL_VERSION 562 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 46669d6c8fe..1c2e1308c4b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -766,8 +766,9 @@ struct rawinput_device @END -/* Create a new thread from the context of the parent */ +/* Create a new thread */ @REQ(new_thread) + obj_handle_t process; /* process in which to create thread */ unsigned int access; /* wanted access rights */ int suspend; /* new thread should be suspended on creation */ int request_fd; /* fd for request pipe */ diff --git a/server/request.h b/server/request.h index ff2da53e4ee..d7a4c8d7c13 100644 --- a/server/request.h +++ b/server/request.h @@ -752,10 +752,11 @@ C_ASSERT( sizeof(struct get_new_process_info_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_new_process_info_reply, success) == 8 ); C_ASSERT( FIELD_OFFSET(struct get_new_process_info_reply, exit_code) == 12 ); C_ASSERT( sizeof(struct get_new_process_info_reply) == 16 ); -C_ASSERT( FIELD_OFFSET(struct new_thread_request, access) == 12 ); -C_ASSERT( FIELD_OFFSET(struct new_thread_request, suspend) == 16 ); -C_ASSERT( FIELD_OFFSET(struct new_thread_request, request_fd) == 20 ); -C_ASSERT( sizeof(struct new_thread_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct new_thread_request, process) == 12 ); +C_ASSERT( FIELD_OFFSET(struct new_thread_request, access) == 16 ); +C_ASSERT( FIELD_OFFSET(struct new_thread_request, suspend) == 20 ); +C_ASSERT( FIELD_OFFSET(struct new_thread_request, request_fd) == 24 ); +C_ASSERT( sizeof(struct new_thread_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct new_thread_reply, tid) == 8 ); C_ASSERT( FIELD_OFFSET(struct new_thread_reply, handle) == 12 ); C_ASSERT( sizeof(struct new_thread_reply) == 16 ); diff --git a/server/thread.c b/server/thread.c index d6713771ea7..7162fc33bde 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1271,19 +1271,40 @@ unsigned int get_supported_cpu_mask(void) DECL_HANDLER(new_thread) { struct thread *thread; + struct process *process; struct unicode_str name; const struct security_descriptor *sd; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); int request_fd = thread_get_inflight_fd( current, req->request_fd ); - if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1) + if (!(process = get_process_from_handle( req->process, PROCESS_CREATE_THREAD ))) { if (request_fd != -1) close( request_fd ); - set_error( STATUS_INVALID_HANDLE ); return; } - if ((thread = create_thread( request_fd, current->process, sd ))) + if (process != current->process) + { + if (request_fd != -1) /* can't create a request fd in a different process */ + { + close( request_fd ); + set_error( STATUS_INVALID_PARAMETER ); + goto done; + } + if (process->running_threads) /* only the initial thread can be created in another process */ + { + set_error( STATUS_ACCESS_DENIED ); + goto done; + } + } + else if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1) + { + if (request_fd != -1) close( request_fd ); + set_error( STATUS_INVALID_HANDLE ); + goto done; + } + + if ((thread = create_thread( request_fd, process, sd ))) { thread->system_regs = current->system_regs; if (req->suspend) thread->suspend++; @@ -1292,10 +1313,12 @@ DECL_HANDLER(new_thread) req->access, objattr->attributes ))) { /* thread object will be released when the thread gets killed */ - return; + goto done; } kill_thread( thread, 1 ); } +done: + release_object( process ); } /* initialize a new thread */ diff --git a/server/trace.c b/server/trace.c index 3054a18d6a4..a419ddf2573 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1261,7 +1261,8 @@ static void dump_get_new_process_info_reply( const struct get_new_process_info_r static void dump_new_thread_request( const struct new_thread_request *req ) { - fprintf( stderr, " access=%08x", req->access ); + fprintf( stderr, " process=%04x", req->process ); + fprintf( stderr, ", access=%08x", req->access ); fprintf( stderr, ", suspend=%d", req->suspend ); fprintf( stderr, ", request_fd=%d", req->request_fd ); dump_varargs_object_attributes( ", objattr=", cur_size );