[PATCH 4/5] server: Implement support for creating a process with a specified token.
Zebediah Figura
z.figura12 at gmail.com
Wed Sep 23 23:44:55 CDT 2020
From: Michael Müller <michael at fds-team.de>
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
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
More information about the wine-devel
mailing list