From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/ntdll/unix/process.c | 12 ++++++++++-- server/process.c | 24 +++++++++++++++++++++++- server/process.h | 1 + server/protocol.def | 2 ++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 758a5bf9d35..005b90eb05e 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -690,8 +690,8 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ unsigned int status; BOOL success = FALSE; HANDLE file_handle, process_info = 0, process_handle = 0, thread_handle = 0; - struct object_attributes *objattr; - data_size_t attr_len; + struct object_attributes *objattr, *thread_objattr; + data_size_t attr_len, thread_attr_len; char *winedebug = NULL; char *unix_name = NULL; struct startup_info_data *startup_info = NULL; @@ -782,6 +782,11 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ env_size = get_env_size( params, &winedebug ); if ((status = alloc_object_attributes( process_attr, &objattr, &attr_len ))) goto done; + if ((status = alloc_object_attributes( thread_attr, &thread_objattr, &thread_attr_len ))) + { + free( thread_objattr ); + goto done; + } if ((status = alloc_handle_list( handles_attr, &handles, &handles_size ))) { @@ -831,9 +836,11 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ req->info_size = startup_info_size; req->handles_size = handles_size; req->jobs_size = jobs_size; + req->sd_len = thread_objattr ? thread_objattr->sd_len : 0; wine_server_add_data( req, objattr, attr_len ); wine_server_add_data( req, handles, handles_size ); wine_server_add_data( req, jobs, jobs_size ); + wine_server_add_data( req, thread_objattr + 1, req->sd_len ); wine_server_add_data( req, startup_info, startup_info_size ); wine_server_add_data( req, params->Environment, env_size ); if (!(status = wine_server_call( req ))) @@ -845,6 +852,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ } SERVER_END_REQ; close( socketfd[1] ); + free( thread_objattr ); free( objattr ); free( handles ); free( jobs ); diff --git a/server/process.c b/server/process.c index 50cd140c8c6..5e44e6faaa6 100644 --- a/server/process.c +++ b/server/process.c @@ -675,6 +675,8 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla process->unix_pid = -1; process->exit_code = STILL_ACTIVE; process->running_threads = 0; + process->thread_flags = 0; + process->thread_sd = NULL; process->priority = PROCESS_PRIOCLASS_NORMAL; process->base_priority = 8; process->disable_boost = 0; @@ -801,6 +803,7 @@ static void process_destroy( struct object *obj ) free( process->rawinput_devices ); free( process->dir_cache ); free( process->image ); + free( process->thread_sd ); } /* dump a process on stdout for debugging purposes */ @@ -1152,7 +1155,7 @@ DECL_HANDLER(new_process) struct startup_info *info; const void *info_ptr; struct unicode_str name, desktop_path = {0}; - const struct security_descriptor *sd; + const struct security_descriptor *sd, *thread_sd = NULL; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); struct process *process = NULL; struct token *token = NULL; @@ -1255,6 +1258,24 @@ DECL_HANDLER(new_process) info_ptr = (const char *)info_ptr + req->jobs_size; info->data_size -= req->jobs_size; } + if (req->sd_len > info->data_size) + { + set_error( STATUS_INVALID_PARAMETER ); + close( socket_fd ); + goto done; + } + if (req->sd_len) + { + thread_sd = info_ptr; + info_ptr = (const char *)thread_sd + req->sd_len; + info->data_size -= req->sd_len; + } + if (thread_sd && !sd_is_valid( thread_sd, req->sd_len )) + { + set_error( STATUS_INVALID_PARAMETER ); + close( socket_fd ); + goto done; + } job_handle_count = req->jobs_size / sizeof(*handles); for (i = 0; i < job_handle_count; ++i) @@ -1327,6 +1348,7 @@ DECL_HANDLER(new_process) process->machine = req->machine; process->startup_info = (struct startup_info *)grab_object( info ); process->thread_flags = req->thread_flags; + if (thread_sd && !(process->thread_sd = memdup( thread_sd, req->sd_len ))) goto done; job = parent->job; while (job) diff --git a/server/process.h b/server/process.h index 5c49daab3f0..b2292440c8b 100644 --- a/server/process.h +++ b/server/process.h @@ -54,6 +54,7 @@ struct process int exit_code; /* process exit code */ int running_threads; /* number of threads running in this process */ unsigned int thread_flags; /* first thread flags */ + struct security_descriptor *thread_sd; /* first thread security descriptor */ timeout_t start_time; /* absolute time at process start */ timeout_t end_time; /* absolute time at process end */ affinity_t affinity; /* process affinity mask */ diff --git a/server/protocol.def b/server/protocol.def index 36e6230ebf6..64e91bccc87 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1095,9 +1095,11 @@ typedef volatile struct data_size_t info_size; /* size of startup info */ data_size_t handles_size; /* length of explicit handles list */ data_size_t jobs_size; /* length of jobs list */ + data_size_t sd_len; /* size of security descriptor */ VARARG(objattr,object_attributes); /* object attributes */ VARARG(handles,uints,handles_size); /* handles list */ VARARG(jobs,uints,jobs_size); /* jobs list */ + VARARG(sd,security_descriptor,sd_len); /* thread security descriptor */ VARARG(info,startup_info,info_size); /* startup information */ VARARG(env,unicode_str); /* environment for new process */ @REPLY -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10058