[6/6] server: implement passing a thread security descriptor to CreateProcess

Joris van der Wel joris at jorisvanderwel.com
Sun Jul 6 13:19:50 CDT 2014


server: implement passing a thread security descriptor to
 CreateProcess

---
 dlls/advapi32/tests/security.c | 45 ++++++++++++++++++++++++++++++++++++++----
 dlls/kernel32/process.c        | 24 +++++++++++++++++++---
 server/process.c               | 28 +++++++++++++++++++++++++-
 3 files changed, 89 insertions(+), 8 deletions(-)
-------------- next part --------------
From 3c99c29522750cd03200011a33b3604ca3791db9 Mon Sep 17 00:00:00 2001
From: Joris van der Wel <joris at jorisvanderwel.com>
Date: Sun, 6 Jul 2014 20:09:14 +0200
Subject: server: implement passing a thread security descriptor to
 CreateProcess

---
 dlls/advapi32/tests/security.c | 45 ++++++++++++++++++++++++++++++++++++++----
 dlls/kernel32/process.c        | 24 +++++++++++++++++++---
 server/process.c               | 28 +++++++++++++++++++++++++-
 3 files changed, 89 insertions(+), 8 deletions(-)

diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 669472d..15a3b83 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -2532,12 +2532,12 @@ static void test_process_security(void)
     PTOKEN_OWNER owner;
     PTOKEN_PRIMARY_GROUP group;
     PSID AdminSid = NULL, UsersSid = NULL;
-    PACL Acl = NULL;
-    SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
+    PACL Acl = NULL, ThreadAcl = NULL;
+    SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL;
     char buffer[MAX_PATH];
     PROCESS_INFORMATION info;
     STARTUPINFOA startup;
-    SECURITY_ATTRIBUTES psa;
+    SECURITY_ATTRIBUTES psa, tsa;
     HANDLE token, event;
     DWORD size;
     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
@@ -2657,12 +2657,38 @@ static void test_process_security(void)
     psa.nLength = sizeof(psa);
     psa.lpSecurityDescriptor = SecurityDescriptor;
     psa.bInheritHandle = TRUE;
+    
+    
+    ThreadSecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
+    res = InitializeSecurityDescriptor(ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+    ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
+    
+    ThreadAcl = HeapAlloc(GetProcessHeap(), 0, 256);
+    res = InitializeAcl(ThreadAcl, 256, ACL_REVISION);
+    ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+    res = AddAccessDeniedAce(ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid);
+    ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
+    res = AddAccessAllowedAce(ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid);
+    ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+    
+    res = SetSecurityDescriptorOwner(ThreadSecurityDescriptor, AdminSid, FALSE);
+    ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+    res = SetSecurityDescriptorGroup(ThreadSecurityDescriptor, UsersSid, FALSE);
+    ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+    res = SetSecurityDescriptorDacl(ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE);
+    ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+    
+    tsa.nLength = sizeof(tsa);
+    tsa.lpSecurityDescriptor = ThreadSecurityDescriptor;
+    tsa.bInheritHandle = TRUE;
 
     /* Doesn't matter what ACL say we should get full access for ourselves */
-    res = CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info );
+    res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info );
     ok(res, "CreateProcess with err:%d\n", GetLastError());
     TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4,
                           STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
+    TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4,
+                          STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
     winetest_wait_child_process( info.hProcess );
 
     CloseHandle( info.hProcess );
@@ -2672,6 +2698,8 @@ static void test_process_security(void)
     HeapFree(GetProcessHeap(), 0, owner);
     HeapFree(GetProcessHeap(), 0, Acl);
     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
+    HeapFree(GetProcessHeap(), 0, ThreadAcl);
+    HeapFree(GetProcessHeap(), 0, ThreadSecurityDescriptor);
 }
 
 static void test_process_security_child(void)
@@ -2727,6 +2755,15 @@ static void test_process_security_child(void)
     TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
     CloseHandle( handle1 );
     CloseHandle( handle );
+    
+    
+    handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() );
+    ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%d\n", GetLastError());
+    TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
+    CloseHandle( handle );
+    
+    handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() );
+    ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");
 }
 
 static void test_impersonation_level(void)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index e4db5be..c0858b4 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -1939,8 +1939,8 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
     int socketfd[2], stdin_fd = -1, stdout_fd = -1;
     pid_t pid;
     int err, cpu;
-    struct security_descriptor *psd = NULL;
-    data_size_t psd_len = 0;
+    struct security_descriptor *psd = NULL, *tsd = NULL;
+    data_size_t psd_len = 0, tsd_len = 0;
 
 
     if ((cpu = get_process_cpu( filename, binary_info )) == -1)
@@ -1959,12 +1959,26 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
             return FALSE;
         }
     }
+    
+    if (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->lpSecurityDescriptor)
+    {
+        status = wine_server_create_struct_sd( tsa->lpSecurityDescriptor, &tsd, &tsd_len );
+        
+        if (status != STATUS_SUCCESS)
+        {
+            wine_server_free_struct_sd( psd );
+            WARN("Invalid thread security descriptor with status %x\n", status);
+            SetLastError( RtlNtStatusToDosError(status) );
+            return FALSE;
+        }
+    }
 
     /* create the socket for the new process */
 
     if (socketpair( PF_UNIX, SOCK_STREAM, 0, socketfd ) == -1)
     {
         wine_server_free_struct_sd( psd );
+        wine_server_free_struct_sd( tsd );
         SetLastError( ERROR_TOO_MANY_OPEN_FILES );
         return FALSE;
     }
@@ -2005,6 +2019,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
         }
         close( socketfd[0] );
         wine_server_free_struct_sd( psd );
+        wine_server_free_struct_sd( tsd );
         SetLastError( RtlNtStatusToDosError( status ));
         return FALSE;
     }
@@ -2018,6 +2033,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
         close( socketfd[0] );
         close( socketfd[1] );
         wine_server_free_struct_sd( psd );
+        wine_server_free_struct_sd( tsd );
         return FALSE;
     }
     if (!env) env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
@@ -2052,11 +2068,12 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
         req->thread_attr     = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
         req->cpu             = cpu;
         req->process_sd_size = psd_len;
-        req->thread_sd_size  = 0;
+        req->thread_sd_size  = tsd_len;
         req->info_size       = startup_info_size;
         req->env_size        = (env_end - env) * sizeof(WCHAR);
         
         wine_server_add_data( req, psd         , req->process_sd_size );
+        wine_server_add_data( req, tsd         , req->thread_sd_size  );
         wine_server_add_data( req, startup_info, req->info_size       );
         wine_server_add_data( req, env         , req->env_size        );
         
@@ -2072,6 +2089,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
     SERVER_END_REQ;
 
     wine_server_free_struct_sd( psd );
+    wine_server_free_struct_sd( tsd );
 
     RtlReleasePebLock();
     if (status)
diff --git a/server/process.c b/server/process.c
index d1db87a..799ac17 100644
--- a/server/process.c
+++ b/server/process.c
@@ -883,7 +883,7 @@ DECL_HANDLER(new_process)
     const startup_info_t *req_info;
     data_size_t req_info_size;
     const WCHAR *req_env;
-    const struct security_descriptor *req_psd = NULL;
+    const struct security_descriptor *req_psd = NULL, *req_tsd = NULL;
 
     if (socket_fd == -1)
     {
@@ -919,6 +919,18 @@ DECL_HANDLER(new_process)
         }
     }
     
+    if (req->thread_sd_size)
+    {
+        req_tsd = (const struct security_descriptor *) 
+              ((char*)get_req_data() + req->process_sd_size);
+        
+        if (!sd_is_valid( req_tsd, req->thread_sd_size ))
+        {
+            set_error( STATUS_INVALID_SECURITY_DESCR );
+            return;
+        }
+    }
+    
     req_info = (const startup_info_t *)
                ((char*)get_req_data() + req->process_sd_size + req->thread_sd_size);
     
@@ -1037,6 +1049,20 @@ DECL_HANDLER(new_process)
                         DACL_SECURITY_INFORMATION|
                         SACL_SECURITY_INFORMATION );
     }
+    
+    if (req_tsd)
+    {
+        /* In CreateProcess the thread defaults come from the process token,
+         * (this is not the case during CreateThread however) */
+        set_sd_defaults_from_token( &thread->obj,
+                                    req_tsd, 
+                                    OWNER_SECURITY_INFORMATION|
+                                    GROUP_SECURITY_INFORMATION|
+                                    DACL_SECURITY_INFORMATION|
+                                    SACL_SECURITY_INFORMATION,
+                                    process->token );
+    }
+
  done:
     release_object( info );
 }
-- 
1.8.1.msysgit.1



More information about the wine-patches mailing list