From fde5967f725624c5ee4995dcbe22f262979c5c9c Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 29 Sep 2020 12:12:14 +0300 Subject: [PATCH] server: Inherit standard handles together with explicit handle list. Restores standard handles behavior pre-c58a10c16395c30e7793cde1f748febe0432a6ad, always inheriting them when inherit mode is enabled. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49895 Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- server/handle.c | 36 ++++++++++++++++++++++++------------ server/handle.h | 3 ++- server/process.c | 14 ++++++++++---- server/process.h | 2 +- server/request.c | 2 +- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/server/handle.c b/server/handle.c index d4df33f4730..15382256f10 100644 --- a/server/handle.c +++ b/server/handle.c @@ -354,10 +354,26 @@ static void shrink_handle_table( struct handle_table *table ) table->entries = new_entries; } +static void inherit_handle( struct process *parent, const obj_handle_t handle, struct handle_table *table ) +{ + struct handle_entry *dst, *src; + int index; + + dst = table->entries; + + src = get_handle( parent, handle ); + if (!src || !(src->access & RESERVED_INHERIT)) return; + grab_object_for_handle( src->ptr ); + index = handle_to_index( handle ); + dst[index] = *src; + table->last = max( table->last, index ); +} + /* copy the handle table of the parent process */ /* return 1 if OK, 0 on error */ struct handle_table *copy_handle_table( struct process *process, struct process *parent, - const obj_handle_t *handles, unsigned int handle_count ) + const obj_handle_t *handles, unsigned int handle_count, + const obj_handle_t *std_handles ) { struct handle_table *parent_table = parent->handles; struct handle_table *table; @@ -371,20 +387,16 @@ struct handle_table *copy_handle_table( struct process *process, struct process if (handles) { - struct handle_entry *dst, *src; - int index; - - dst = table->entries; - memset( dst, 0, parent_table->count * sizeof(*dst) ); + memset( table->entries, 0, parent_table->count * sizeof(*table->entries) ); for (i = 0; i < handle_count; i++) { - src = get_handle( parent, handles[i] ); - if (!src || !(src->access & RESERVED_INHERIT)) continue; - grab_object_for_handle( src->ptr ); - index = handle_to_index( handles[i] ); - dst[index] = *src; - table->last = max( table->last, index ); + inherit_handle( parent, handles[i], table ); + } + + for (i = 0; i < 3; i++) + { + inherit_handle( parent, std_handles[i], table ); } } else diff --git a/server/handle.h b/server/handle.h index bb541de13b1..ac3104dc003 100644 --- a/server/handle.h +++ b/server/handle.h @@ -51,7 +51,8 @@ extern obj_handle_t find_inherited_handle( struct process *process, const struct extern void close_process_handles( struct process *process ); extern struct handle_table *alloc_handle_table( struct process *process, int count ); extern struct handle_table *copy_handle_table( struct process *process, struct process *parent, - const obj_handle_t *handles, unsigned int handle_count ); + const obj_handle_t *handles, unsigned int handle_count, + const obj_handle_t *std_handles ); extern unsigned int get_handle_table_count( struct process *process); #endif /* __WINE_SERVER_HANDLE_H */ diff --git a/server/process.c b/server/process.c index 26958308ca7..1786493a814 100644 --- a/server/process.c +++ b/server/process.c @@ -502,7 +502,7 @@ static void start_sigkill_timer( struct process *process ) /* create a new process */ /* if the function fails the fd is closed */ -struct process *create_process( int fd, struct process *parent, int inherit_all, +struct process *create_process( int fd, struct process *parent, int inherit_all, const startup_info_t *info, const struct security_descriptor *sd, const obj_handle_t *handles, unsigned int handle_count, struct token *token ) { @@ -576,8 +576,14 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, } else { + obj_handle_t std_handles[3]; + + std_handles[0] = info->hstdin; + std_handles[1] = info->hstdout; + std_handles[2] = info->hstderr; + process->parent_id = parent->id; - process->handles = inherit_all ? copy_handle_table( process, parent, handles, handle_count ) + process->handles = inherit_all ? copy_handle_table( process, parent, handles, handle_count, std_handles ) : alloc_handle_table( process, 0 ); /* Note: for security reasons, starting a new process does not attempt * to use the current impersonation token for the new process */ @@ -1227,7 +1233,7 @@ DECL_HANDLER(new_process) goto done; } - if (!(process = create_process( socket_fd, parent, req->inherit_all, sd, + if (!(process = create_process( socket_fd, parent, req->inherit_all, info->data, sd, handles, req->handles_size / sizeof(*handles), token ))) goto done; @@ -1325,7 +1331,7 @@ DECL_HANDLER(exec_process) close( socket_fd ); return; } - if (!(process = create_process( socket_fd, NULL, 0, NULL, NULL, 0, NULL ))) return; + if (!(process = create_process( socket_fd, NULL, 0, NULL, NULL, NULL, 0, NULL ))) return; create_thread( -1, process, NULL ); release_object( process ); } diff --git a/server/process.h b/server/process.h index bc81d563b47..56092e5b1ac 100644 --- a/server/process.h +++ b/server/process.h @@ -108,7 +108,7 @@ struct process extern unsigned int alloc_ptid( void *ptr ); extern void free_ptid( unsigned int id ); extern void *get_ptid_entry( unsigned int id ); -extern struct process *create_process( int fd, struct process *parent, int inherit_all, +extern struct process *create_process( int fd, struct process *parent, int inherit_all, const startup_info_t *info, const struct security_descriptor *sd, const obj_handle_t *handles, unsigned int handle_count, struct token *token ); extern data_size_t init_process( struct thread *thread ); diff --git a/server/request.c b/server/request.c index 40e9478e09e..97bf1a746d2 100644 --- a/server/request.c +++ b/server/request.c @@ -583,7 +583,7 @@ static void master_socket_poll_event( struct fd *fd, int event ) int client = accept( get_unix_fd( master_socket->fd ), (struct sockaddr *) &dummy, &len ); if (client == -1) return; fcntl( client, F_SETFL, O_NONBLOCK ); - if ((process = create_process( client, NULL, 0, NULL, NULL, 0, NULL ))) + if ((process = create_process( client, NULL, 0, NULL, NULL, NULL, 0, NULL ))) { create_thread( -1, process, NULL ); release_object( process );