server: Implement support for creating a process with a specified token.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Michael Müller 2020-09-23 23:44:55 -05:00 committed by Alexandre Julliard
parent 2379e3c181
commit d0bea3d702
11 changed files with 50 additions and 32 deletions

View File

@ -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());
}
}

View File

@ -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( &params->ImagePathName ), debugstr_us( &params->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 */

View File

@ -773,6 +773,7 @@ struct rawinput_device
struct new_process_request
{
struct request_header __header;
obj_handle_t token;
obj_handle_t parent_process;
int inherit_all;
unsigned int create_flags;
@ -786,6 +787,7 @@ struct new_process_request
/* VARARG(handles,uints,handles_size); */
/* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */
char __pad_52[4];
};
struct new_process_reply
{
@ -6300,7 +6302,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 646
#define SERVER_PROTOCOL_VERSION 647
/* ### protocol_version end ### */

View File

@ -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 );
}

View File

@ -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 );

View File

@ -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 */

View File

@ -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 );

View File

@ -719,16 +719,17 @@ C_ASSERT( sizeof(unsigned char) == 1 );
C_ASSERT( sizeof(unsigned int) == 4 );
C_ASSERT( sizeof(unsigned short) == 2 );
C_ASSERT( sizeof(user_handle_t) == 4 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 16 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 20 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 24 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 44 );
C_ASSERT( sizeof(struct new_process_request) == 48 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, token) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 16 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 20 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 24 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 40 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 44 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 48 );
C_ASSERT( sizeof(struct new_process_request) == 56 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, info) == 8 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 );

View File

@ -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,

View File

@ -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;

View File

@ -1284,7 +1284,8 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *req )
{
fprintf( stderr, " parent_process=%04x", req->parent_process );
fprintf( stderr, " token=%04x", req->token );
fprintf( stderr, ", parent_process=%04x", req->parent_process );
fprintf( stderr, ", inherit_all=%d", req->inherit_all );
fprintf( stderr, ", create_flags=%08x", req->create_flags );
fprintf( stderr, ", socket_fd=%d", req->socket_fd );