From: Zebediah Figura Subject: [PATCH 4/5] server: Implement support for creating a process with a specified token. Message-Id: <20200924044456.3451130-4-z.figura12@gmail.com> Date: Wed, 23 Sep 2020 23:44:55 -0500 In-Reply-To: <20200924044456.3451130-1-z.figura12@gmail.com> References: <20200924044456.3451130-1-z.figura12@gmail.com> From: Michael Müller Signed-off-by: Zebediah Figura --- dlls/advapi32/tests/security.c | 24 +++++++++++------------- dlls/ntdll/unix/process.c | 2 +- server/process.c | 17 +++++++++++++---- server/process.h | 2 +- server/protocol.def | 1 + server/request.c | 2 +- server/security.h | 1 + server/token.c | 5 +++++ 8 files changed, 34 insertions(+), 20 deletions(-) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index bd8cc5f061b..c9318bef928 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -7732,16 +7732,16 @@ static void test_duplicate_handle_access_child(void) SetLastError(0xdeadbeef); event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup"); - todo_wine ok(!event2, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); + ok(!event2, "expected failure\n"); + ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0); - ok(ret, "got error %u\n", GetLastError()); + todo_wine ok(ret, "got error %u\n", GetLastError()); SetLastError(0xdeadbeef); ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ret = DuplicateHandle(process, (HANDLE)(ULONG_PTR)_atoi64(myARGV[5]), GetCurrentProcess(), &token, 0, FALSE, DUPLICATE_SAME_ACCESS); @@ -7823,17 +7823,15 @@ static void test_create_process_token(void) ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); ok(ret, "got error %u\n", GetLastError()); ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); - if (ret) join_process(&pi); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); CloseHandle(token); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY, &token); ok(ret, "got error %u\n", GetLastError()); ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); - if (ret) join_process(&pi); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); CloseHandle(token); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &token); @@ -7875,8 +7873,8 @@ static void test_create_process_token_child(void) } else { - todo_wine ok(!event, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); + ok(!event, "expected failure\n"); + ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); } } diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index a6be00646a8..5ccf435e9ff 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -894,7 +894,6 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ TRACE( "%s image %s cmdline %s parent %p\n", debugstr_us( &path ), debugstr_us( ¶ms->ImagePathName ), debugstr_us( ¶ms->CommandLine ), parent ); if (debug) FIXME( "debug port %p not supported yet\n", debug ); - if (token) FIXME( "token %p not supported yet\n", token ); unixdir = get_unix_curdir( params ); @@ -942,6 +941,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ SERVER_START_REQ( new_process ) { + req->token = wine_server_obj_handle( token ); req->parent_process = wine_server_obj_handle( parent ); req->inherit_all = !!(process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES); req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */ diff --git a/server/process.c b/server/process.c index 1650bd8f354..26958308ca7 100644 --- a/server/process.c +++ b/server/process.c @@ -504,7 +504,7 @@ static void start_sigkill_timer( struct process *process ) /* if the function fails the fd is closed */ struct process *create_process( int fd, struct process *parent, int inherit_all, const struct security_descriptor *sd, const obj_handle_t *handles, - unsigned int handle_count ) + unsigned int handle_count, struct token *token ) { struct process *process; @@ -581,7 +581,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, : 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 */ - process->token = token_duplicate( parent->token, TRUE, 0, NULL, NULL, 0, NULL, 0 ); + process->token = token_duplicate( token ? token : parent->token, TRUE, 0, NULL, NULL, 0, NULL, 0 ); process->affinity = parent->affinity; } if (!process->handles || !process->token) goto error; @@ -1102,6 +1102,7 @@ DECL_HANDLER(new_process) const struct security_descriptor *sd; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); struct process *process = NULL; + struct token *token = NULL; struct process *parent; struct thread *parent_thread = current; int socket_fd = thread_get_inflight_fd( current, req->socket_fd ); @@ -1220,7 +1221,14 @@ DECL_HANDLER(new_process) #undef FIXUP_LEN } - if (!(process = create_process( socket_fd, parent, req->inherit_all, sd, handles, req->handles_size / sizeof(*handles) ))) + if (req->token && !(token = get_token_obj( current->process, req->token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY ))) + { + close( socket_fd ); + goto done; + } + + if (!(process = create_process( socket_fd, parent, req->inherit_all, sd, + handles, req->handles_size / sizeof(*handles), token ))) goto done; process->startup_info = (struct startup_info *)grab_object( info ); @@ -1284,6 +1292,7 @@ DECL_HANDLER(new_process) done: if (process) release_object( process ); + if (token) release_object( token ); release_object( parent ); release_object( info ); } @@ -1316,7 +1325,7 @@ DECL_HANDLER(exec_process) close( socket_fd ); return; } - if (!(process = create_process( socket_fd, NULL, 0, NULL, NULL, 0 ))) return; + if (!(process = create_process( socket_fd, NULL, 0, NULL, NULL, 0, NULL ))) return; create_thread( -1, process, NULL ); release_object( process ); } diff --git a/server/process.h b/server/process.h index 7facc4f6dfa..bc81d563b47 100644 --- a/server/process.h +++ b/server/process.h @@ -110,7 +110,7 @@ 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, const struct security_descriptor *sd, const obj_handle_t *handles, - unsigned int handle_count ); + unsigned int handle_count, struct token *token ); extern data_size_t init_process( struct thread *thread ); extern struct thread *get_process_first_thread( struct process *process ); extern struct process *get_process_from_id( process_id_t id ); diff --git a/server/protocol.def b/server/protocol.def index 9437a303501..6534092f2cc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -787,6 +787,7 @@ struct rawinput_device /* Create a new process from the context of the parent */ @REQ(new_process) + obj_handle_t token; /* process token */ obj_handle_t parent_process; /* parent process */ int inherit_all; /* inherit all handles from parent */ unsigned int create_flags; /* creation flags */ diff --git a/server/request.c b/server/request.c index 3ef4a244b84..40e9478e09e 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 ))) + if ((process = create_process( client, NULL, 0, NULL, NULL, 0, NULL ))) { create_thread( -1, process, NULL ); release_object( process ); diff --git a/server/security.h b/server/security.h index 7c35300afe4..bece7f54048 100644 --- a/server/security.h +++ b/server/security.h @@ -53,6 +53,7 @@ extern const PSID security_high_label_sid; /* token functions */ +extern struct token *get_token_obj( struct process *process, obj_handle_t handle, unsigned int access ); extern struct token *token_create_admin(void); extern int token_assign_label( struct token *token, PSID label ); extern struct token *token_duplicate( struct token *src_token, unsigned primary, diff --git a/server/token.c b/server/token.c index 8404e651196..8a106b7d34f 100644 --- a/server/token.c +++ b/server/token.c @@ -835,6 +835,11 @@ int token_assign_label( struct token *token, PSID label ) return ret; } +struct token *get_token_obj( struct process *process, obj_handle_t handle, unsigned int access ) +{ + return (struct token *)get_handle_obj( process, handle, access, &token_ops ); +} + struct token *token_create_admin( void ) { struct token *token = NULL; -- 2.28.0