Commit d0bea3d7 authored by Michael Müller's avatar Michael Müller Committed by Alexandre Julliard

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

parent 2379e3c1
...@@ -7732,16 +7732,16 @@ static void test_duplicate_handle_access_child(void) ...@@ -7732,16 +7732,16 @@ static void test_duplicate_handle_access_child(void)
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup"); event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
todo_wine ok(!event2, "expected failure\n"); ok(!event2, "expected failure\n");
todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0); 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); SetLastError(0xdeadbeef);
ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0); ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
todo_wine ok(!ret, "expected failure\n"); ok(!ret, "expected failure\n");
todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
ret = DuplicateHandle(process, (HANDLE)(ULONG_PTR)_atoi64(myARGV[5]), ret = DuplicateHandle(process, (HANDLE)(ULONG_PTR)_atoi64(myARGV[5]),
GetCurrentProcess(), &token, 0, FALSE, DUPLICATE_SAME_ACCESS); GetCurrentProcess(), &token, 0, FALSE, DUPLICATE_SAME_ACCESS);
...@@ -7823,17 +7823,15 @@ static void test_create_process_token(void) ...@@ -7823,17 +7823,15 @@ static void test_create_process_token(void)
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
ok(ret, "got error %u\n", GetLastError()); ok(ret, "got error %u\n", GetLastError());
ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
todo_wine ok(!ret, "expected failure\n"); ok(!ret, "expected failure\n");
todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
if (ret) join_process(&pi);
CloseHandle(token); CloseHandle(token);
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY, &token); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY, &token);
ok(ret, "got error %u\n", GetLastError()); ok(ret, "got error %u\n", GetLastError());
ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
todo_wine ok(!ret, "expected failure\n"); ok(!ret, "expected failure\n");
todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
if (ret) join_process(&pi);
CloseHandle(token); CloseHandle(token);
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &token); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &token);
...@@ -7875,8 +7873,8 @@ static void test_create_process_token_child(void) ...@@ -7875,8 +7873,8 @@ static void test_create_process_token_child(void)
} }
else else
{ {
todo_wine ok(!event, "expected failure\n"); ok(!event, "expected failure\n");
todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
} }
} }
......
...@@ -894,7 +894,6 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ ...@@ -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 ), TRACE( "%s image %s cmdline %s parent %p\n", debugstr_us( &path ),
debugstr_us( &params->ImagePathName ), debugstr_us( &params->CommandLine ), parent ); debugstr_us( &params->ImagePathName ), debugstr_us( &params->CommandLine ), parent );
if (debug) FIXME( "debug port %p not supported yet\n", debug ); 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 ); unixdir = get_unix_curdir( params );
...@@ -942,6 +941,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_ ...@@ -942,6 +941,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
SERVER_START_REQ( new_process ) SERVER_START_REQ( new_process )
{ {
req->token = wine_server_obj_handle( token );
req->parent_process = wine_server_obj_handle( parent ); req->parent_process = wine_server_obj_handle( parent );
req->inherit_all = !!(process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES); req->inherit_all = !!(process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES);
req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */ req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */
......
...@@ -773,6 +773,7 @@ struct rawinput_device ...@@ -773,6 +773,7 @@ struct rawinput_device
struct new_process_request struct new_process_request
{ {
struct request_header __header; struct request_header __header;
obj_handle_t token;
obj_handle_t parent_process; obj_handle_t parent_process;
int inherit_all; int inherit_all;
unsigned int create_flags; unsigned int create_flags;
...@@ -786,6 +787,7 @@ struct new_process_request ...@@ -786,6 +787,7 @@ struct new_process_request
/* VARARG(handles,uints,handles_size); */ /* VARARG(handles,uints,handles_size); */
/* VARARG(info,startup_info,info_size); */ /* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */ /* VARARG(env,unicode_str); */
char __pad_52[4];
}; };
struct new_process_reply struct new_process_reply
{ {
...@@ -6300,7 +6302,7 @@ union generic_reply ...@@ -6300,7 +6302,7 @@ union generic_reply
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 646 #define SERVER_PROTOCOL_VERSION 647
/* ### protocol_version end ### */ /* ### protocol_version end ### */
......
...@@ -504,7 +504,7 @@ static void start_sigkill_timer( struct process *process ) ...@@ -504,7 +504,7 @@ static void start_sigkill_timer( struct process *process )
/* if the function fails the fd is closed */ /* 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 struct security_descriptor *sd, const obj_handle_t *handles, const struct security_descriptor *sd, const obj_handle_t *handles,
unsigned int handle_count ) unsigned int handle_count, struct token *token )
{ {
struct process *process; struct process *process;
...@@ -581,7 +581,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, ...@@ -581,7 +581,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
: alloc_handle_table( process, 0 ); : alloc_handle_table( process, 0 );
/* Note: for security reasons, starting a new process does not attempt /* Note: for security reasons, starting a new process does not attempt
* to use the current impersonation token for the new process */ * 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; process->affinity = parent->affinity;
} }
if (!process->handles || !process->token) goto error; if (!process->handles || !process->token) goto error;
...@@ -1102,6 +1102,7 @@ DECL_HANDLER(new_process) ...@@ -1102,6 +1102,7 @@ DECL_HANDLER(new_process)
const struct security_descriptor *sd; const struct security_descriptor *sd;
const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL );
struct process *process = NULL; struct process *process = NULL;
struct token *token = NULL;
struct process *parent; struct process *parent;
struct thread *parent_thread = current; struct thread *parent_thread = current;
int socket_fd = thread_get_inflight_fd( current, req->socket_fd ); int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
...@@ -1220,7 +1221,14 @@ DECL_HANDLER(new_process) ...@@ -1220,7 +1221,14 @@ DECL_HANDLER(new_process)
#undef FIXUP_LEN #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; goto done;
process->startup_info = (struct startup_info *)grab_object( info ); process->startup_info = (struct startup_info *)grab_object( info );
...@@ -1284,6 +1292,7 @@ DECL_HANDLER(new_process) ...@@ -1284,6 +1292,7 @@ DECL_HANDLER(new_process)
done: done:
if (process) release_object( process ); if (process) release_object( process );
if (token) release_object( token );
release_object( parent ); release_object( parent );
release_object( info ); release_object( info );
} }
...@@ -1316,7 +1325,7 @@ DECL_HANDLER(exec_process) ...@@ -1316,7 +1325,7 @@ DECL_HANDLER(exec_process)
close( socket_fd ); close( socket_fd );
return; 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 ); create_thread( -1, process, NULL );
release_object( process ); release_object( process );
} }
......
...@@ -110,7 +110,7 @@ extern void free_ptid( unsigned int id ); ...@@ -110,7 +110,7 @@ extern void free_ptid( unsigned int id );
extern void *get_ptid_entry( 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 struct security_descriptor *sd, const obj_handle_t *handles, 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 data_size_t init_process( struct thread *thread );
extern struct thread *get_process_first_thread( struct process *process ); extern struct thread *get_process_first_thread( struct process *process );
extern struct process *get_process_from_id( process_id_t id ); extern struct process *get_process_from_id( process_id_t id );
......
...@@ -787,6 +787,7 @@ struct rawinput_device ...@@ -787,6 +787,7 @@ struct rawinput_device
/* Create a new process from the context of the parent */ /* Create a new process from the context of the parent */
@REQ(new_process) @REQ(new_process)
obj_handle_t token; /* process token */
obj_handle_t parent_process; /* parent process */ obj_handle_t parent_process; /* parent process */
int inherit_all; /* inherit all handles from parent */ int inherit_all; /* inherit all handles from parent */
unsigned int create_flags; /* creation flags */ unsigned int create_flags; /* creation flags */
......
...@@ -583,7 +583,7 @@ static void master_socket_poll_event( struct fd *fd, int event ) ...@@ -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 ); int client = accept( get_unix_fd( master_socket->fd ), (struct sockaddr *) &dummy, &len );
if (client == -1) return; if (client == -1) return;
fcntl( client, F_SETFL, O_NONBLOCK ); 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 ); create_thread( -1, process, NULL );
release_object( process ); release_object( process );
......
...@@ -719,16 +719,17 @@ C_ASSERT( sizeof(unsigned char) == 1 ); ...@@ -719,16 +719,17 @@ C_ASSERT( sizeof(unsigned char) == 1 );
C_ASSERT( sizeof(unsigned int) == 4 ); C_ASSERT( sizeof(unsigned int) == 4 );
C_ASSERT( sizeof(unsigned short) == 2 ); C_ASSERT( sizeof(unsigned short) == 2 );
C_ASSERT( sizeof(user_handle_t) == 4 ); 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, token) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 16 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 16 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 20 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 20 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 24 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 24 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 28 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 40 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 44 ); C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 44 );
C_ASSERT( sizeof(struct new_process_request) == 48 ); 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, info) == 8 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 );
......
...@@ -53,6 +53,7 @@ extern const PSID security_high_label_sid; ...@@ -53,6 +53,7 @@ extern const PSID security_high_label_sid;
/* token functions */ /* 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 struct token *token_create_admin(void);
extern int token_assign_label( struct token *token, PSID label ); extern int token_assign_label( struct token *token, PSID label );
extern struct token *token_duplicate( struct token *src_token, unsigned primary, extern struct token *token_duplicate( struct token *src_token, unsigned primary,
......
...@@ -835,6 +835,11 @@ int token_assign_label( struct token *token, PSID label ) ...@@ -835,6 +835,11 @@ int token_assign_label( struct token *token, PSID label )
return ret; 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_create_admin( void )
{ {
struct token *token = NULL; struct token *token = NULL;
......
...@@ -1284,7 +1284,8 @@ typedef void (*dump_func)( const void *req ); ...@@ -1284,7 +1284,8 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *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, ", inherit_all=%d", req->inherit_all );
fprintf( stderr, ", create_flags=%08x", req->create_flags ); fprintf( stderr, ", create_flags=%08x", req->create_flags );
fprintf( stderr, ", socket_fd=%d", req->socket_fd ); fprintf( stderr, ", socket_fd=%d", req->socket_fd );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment