diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index a86ad3443a4..e6b99aed62c 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -97,7 +97,7 @@ HANDLE WINAPI CreateRemoteThreadEx( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SI if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack; else stack_commit = stack; - status = RtlCreateUserThread( hProcess, NULL, TRUE, + status = RtlCreateUserThread( hProcess, sa ? sa->lpSecurityDescriptor : NULL, TRUE, NULL, stack_reserve, stack_commit, (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id ); if (status == STATUS_SUCCESS) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index f8b9ce1bdb8..7fa087defe5 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -544,7 +544,7 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle_ptr, ACCESS_MASK access, OBJECT /*********************************************************************** * RtlCreateUserThread (NTDLL.@) */ -NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *descr, +NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, BOOLEAN suspended, PVOID stack_addr, SIZE_T stack_reserve, SIZE_T stack_commit, PRTL_THREAD_START_ROUTINE start, void *param, @@ -561,6 +561,8 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * int request_pipe[2]; NTSTATUS status; SIZE_T extra_stack = PTHREAD_STACK_MIN; + data_size_t len = 0; + struct object_attributes *objattr = NULL; if (process != NtCurrentProcess()) { @@ -587,15 +589,26 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * return result.create_thread.status; } - if (server_pipe( request_pipe ) == -1) return STATUS_TOO_MANY_OPENED_FILES; + if (descr) + { + OBJECT_ATTRIBUTES thread_attr; + InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, descr ); + if ((status = alloc_object_attributes( &thread_attr, &objattr, &len ))) return status; + } + + if (server_pipe( request_pipe ) == -1) + { + RtlFreeHeap( GetProcessHeap(), 0, objattr ); + return STATUS_TOO_MANY_OPENED_FILES; + } wine_server_send_fd( request_pipe[0] ); SERVER_START_REQ( new_thread ) { req->access = THREAD_ALL_ACCESS; - req->attributes = 0; /* FIXME */ req->suspend = suspended; req->request_fd = request_pipe[0]; + wine_server_add_data( req, objattr, len ); if (!(status = wine_server_call( req ))) { handle = wine_server_ptr_handle( reply->handle ); @@ -605,6 +618,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * } SERVER_END_REQ; + RtlFreeHeap( GetProcessHeap(), 0, objattr ); if (status) { close( request_pipe[1] ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 24eb95be26d..d31a1d48419 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -767,10 +767,9 @@ struct new_thread_request { struct request_header __header; unsigned int access; - unsigned int attributes; int suspend; int request_fd; - char __pad_28[4]; + /* VARARG(objattr,object_attributes); */ }; struct new_thread_reply { @@ -6535,6 +6534,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 560 +#define SERVER_PROTOCOL_VERSION 561 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winternl.h b/include/winternl.h index dca8ff32dc2..c718d4c64a3 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2608,7 +2608,7 @@ NTSYSAPI NTSTATUS WINAPI RtlCreateTimer(PHANDLE, HANDLE, RTL_WAITORTIMERCALLBAC NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR); NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR); NTSYSAPI NTSTATUS WINAPI RtlCreateUserProcess(UNICODE_STRING*,ULONG,RTL_USER_PROCESS_PARAMETERS*,SECURITY_DESCRIPTOR*,SECURITY_DESCRIPTOR*,HANDLE,BOOLEAN,HANDLE,HANDLE,RTL_USER_PROCESS_INFORMATION*); -NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,const SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*); +NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*); NTSYSAPI void WINAPI RtlDeactivateActivationContext(DWORD,ULONG_PTR); NTSYSAPI PVOID WINAPI RtlDecodePointer(PVOID); NTSYSAPI NTSTATUS WINAPI RtlDecompressBuffer(USHORT,PUCHAR,ULONG,PUCHAR,ULONG,PULONG); diff --git a/server/process.c b/server/process.c index f8739d00b64..8b808de388f 100644 --- a/server/process.c +++ b/server/process.c @@ -590,7 +590,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit goto error; } close( request_pipe[1] ); - if (!(thread = create_thread( request_pipe[0], process ))) goto error; + if (!(thread = create_thread( request_pipe[0], process, NULL ))) goto error; set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ release_object( process ); diff --git a/server/protocol.def b/server/protocol.def index 8bff5d8d482..46669d6c8fe 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -769,9 +769,9 @@ struct rawinput_device /* Create a new thread from the context of the parent */ @REQ(new_thread) unsigned int access; /* wanted access rights */ - unsigned int attributes; /* object attributes */ int suspend; /* new thread should be suspended on creation */ int request_fd; /* fd for request pipe */ + VARARG(objattr,object_attributes); /* object attributes */ @REPLY thread_id_t tid; /* thread id */ obj_handle_t handle; /* thread handle (in the current process) */ diff --git a/server/request.h b/server/request.h index 6005d1f8f54..ff2da53e4ee 100644 --- a/server/request.h +++ b/server/request.h @@ -753,10 +753,9 @@ 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, attributes) == 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_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_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 2cf5054738a..9ee846df937 100644 --- a/server/thread.c +++ b/server/thread.c @@ -218,7 +218,7 @@ static inline int is_valid_address( client_ptr_t addr ) } /* create a new thread */ -struct thread *create_thread( int fd, struct process *process ) +struct thread *create_thread( int fd, struct process *process, const struct security_descriptor *sd ) { struct thread *thread; @@ -244,6 +244,15 @@ struct thread *create_thread( int fd, struct process *process ) list_add_head( &thread_list, &thread->entry ); + if (sd && !set_sd_defaults_from_token( &thread->obj, sd, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, + process->token )) + { + close( fd ); + release_object( thread ); + return NULL; + } if (!(thread->id = alloc_ptid( thread ))) { close( fd ); @@ -1244,6 +1253,9 @@ unsigned int get_supported_cpu_mask(void) DECL_HANDLER(new_thread) { struct thread *thread; + 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) @@ -1253,12 +1265,13 @@ DECL_HANDLER(new_thread) return; } - if ((thread = create_thread( request_fd, current->process ))) + if ((thread = create_thread( request_fd, current->process, sd ))) { thread->system_regs = current->system_regs; if (req->suspend) thread->suspend++; reply->tid = get_thread_id( thread ); - if ((reply->handle = alloc_handle( current->process, thread, req->access, req->attributes ))) + if ((reply->handle = alloc_handle_no_access_check( current->process, thread, + req->access, objattr->attributes ))) { /* thread object will be released when the thread gets killed */ return; diff --git a/server/thread.h b/server/thread.h index 3cb7cb6cf15..e4332df4abd 100644 --- a/server/thread.h +++ b/server/thread.h @@ -102,7 +102,8 @@ extern struct thread *current; /* thread functions */ -extern struct thread *create_thread( int fd, struct process *process ); +extern struct thread *create_thread( int fd, struct process *process, + const struct security_descriptor *sd ); extern struct thread *get_thread_from_id( thread_id_t id ); extern struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access ); extern struct thread *get_thread_from_tid( int tid ); diff --git a/server/trace.c b/server/trace.c index 1a28cac13e5..3054a18d6a4 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1262,9 +1262,9 @@ 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, ", attributes=%08x", req->attributes ); fprintf( stderr, ", suspend=%d", req->suspend ); fprintf( stderr, ", request_fd=%d", req->request_fd ); + dump_varargs_object_attributes( ", objattr=", cur_size ); } static void dump_new_thread_reply( const struct new_thread_reply *req )