Alexandre Julliard : server: Specify the process in which to create a new thread.
Alexandre Julliard
julliard at winehq.org
Thu Sep 20 13:45:33 CDT 2018
Module: wine
Branch: master
Commit: 0fd450af5bad816f7134b5ce6a5b81fb7b962b44
URL: https://source.winehq.org/git/wine.git/?a=commit;h=0fd450af5bad816f7134b5ce6a5b81fb7b962b44
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Sep 20 13:19:49 2018 +0200
server: Specify the process in which to create a new thread.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 7fa087d..8171638 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 d31a1d4..02734bc 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 46669d6..1c2e130 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 ff2da53..d7a4c8d 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 d671377..7162fc3 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 3054a18..a419ddf 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 );
More information about the wine-cvs
mailing list