[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( &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 */
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