From: Sebastian Lackner Subject: [2/3] kernel32: Implement passing security descriptors from CreateProcess to the wineserver. Message-Id: <543E2A13.2070907@fds-team.de> Date: Wed, 15 Oct 2014 10:02:27 +0200 Based on a patch by Joris van der Wel. Unfortunately we have to duplicate create_struct_sd from ntdll, but thats the easiest solution right now. In long term we should probably think about moving process creation logic to ntdll. --- dlls/advapi32/tests/security.c | 3 -- dlls/kernel32/process.c | 102 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 4 deletions(-) From 6722ba8061c0f7af9929d9152ec9b88e9ab5072f Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 23 Aug 2014 06:27:28 +0200 Subject: kernel32: Implement passing security descriptors from CreateProcess to the wineserver. Based on a patch by Joris van der Wel. --- dlls/advapi32/tests/security.c | 3 -- dlls/kernel32/process.c | 102 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index b44496a..b1b35aa 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -2696,7 +2696,6 @@ static void test_process_security_child(void) ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle1, PROCESS_ALL_ACCESS, TRUE, 0 ); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed " "with STATUS_ACCESS_DENIED, instead of err:%d\n", err); @@ -2704,10 +2703,8 @@ static void test_process_security_child(void) /* These two should fail - they are denied by ACL */ handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() ); - todo_wine ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n"); handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() ); - todo_wine ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n"); /* Documented privilege elevation */ diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 5de8b59..d1746a5 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -1916,6 +1916,70 @@ static pid_t exec_loader( LPCWSTR cmd_line, unsigned int flags, int socketfd, return pid; } +/* creates a struct security_descriptor and contained information in one contiguous piece of memory */ +static NTSTATUS create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd, + data_size_t *server_sd_len) +{ + unsigned int len; + PSID owner, group; + ACL *dacl, *sacl; + BOOLEAN owner_present, group_present, dacl_present, sacl_present; + BOOLEAN defaulted; + NTSTATUS status; + unsigned char *ptr; + + if (!nt_sd) + { + *server_sd = NULL; + *server_sd_len = 0; + return STATUS_SUCCESS; + } + + len = sizeof(struct security_descriptor); + + status = RtlGetOwnerSecurityDescriptor(nt_sd, &owner, &owner_present); + if (status != STATUS_SUCCESS) return status; + status = RtlGetGroupSecurityDescriptor(nt_sd, &group, &group_present); + if (status != STATUS_SUCCESS) return status; + status = RtlGetSaclSecurityDescriptor(nt_sd, &sacl_present, &sacl, &defaulted); + if (status != STATUS_SUCCESS) return status; + status = RtlGetDaclSecurityDescriptor(nt_sd, &dacl_present, &dacl, &defaulted); + if (status != STATUS_SUCCESS) return status; + + if (owner_present) + len += RtlLengthSid(owner); + if (group_present) + len += RtlLengthSid(group); + if (sacl_present && sacl) + len += sacl->AclSize; + if (dacl_present && dacl) + len += dacl->AclSize; + + /* fix alignment for the Unicode name that follows the structure */ + len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); + *server_sd = RtlAllocateHeap(GetProcessHeap(), 0, len); + if (!*server_sd) return STATUS_NO_MEMORY; + + (*server_sd)->control = ((SECURITY_DESCRIPTOR *)nt_sd)->Control & ~SE_SELF_RELATIVE; + (*server_sd)->owner_len = owner_present ? RtlLengthSid(owner) : 0; + (*server_sd)->group_len = group_present ? RtlLengthSid(group) : 0; + (*server_sd)->sacl_len = (sacl_present && sacl) ? sacl->AclSize : 0; + (*server_sd)->dacl_len = (dacl_present && dacl) ? dacl->AclSize : 0; + + ptr = (unsigned char *)(*server_sd + 1); + memcpy(ptr, owner, (*server_sd)->owner_len); + ptr += (*server_sd)->owner_len; + memcpy(ptr, group, (*server_sd)->group_len); + ptr += (*server_sd)->group_len; + memcpy(ptr, sacl, (*server_sd)->sacl_len); + ptr += (*server_sd)->sacl_len; + memcpy(ptr, dacl, (*server_sd)->dacl_len); + + *server_sd_len = len; + + return STATUS_SUCCESS; +} + /*********************************************************************** * create_process * @@ -1939,6 +2003,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 *process_sd = NULL, *thread_sd = NULL; + data_size_t process_sd_size = 0, thread_sd_size = 0; if ((cpu = get_process_cpu( filename, binary_info )) == -1) { @@ -1993,12 +2059,41 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW return FALSE; } + if (psa && (psa->nLength >= sizeof(*psa))) + { + status = create_struct_sd( psa->lpSecurityDescriptor, &process_sd, &process_sd_size ); + if (status != STATUS_SUCCESS) + { + close( socketfd[0] ); + close( socketfd[1] ); + WARN( "Invalid process security descriptor: Status %x\n", status ); + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + } + + if (tsa && (tsa->nLength >= sizeof(*tsa))) + { + status = create_struct_sd( tsa->lpSecurityDescriptor, &thread_sd, &thread_sd_size ); + if (status != STATUS_SUCCESS) + { + RtlFreeHeap( GetProcessHeap(), 0, process_sd ); + close( socketfd[0] ); + close( socketfd[1] ); + WARN( "Invalid thread security descriptor: Status %x\n", status ); + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + } + RtlAcquirePebLock(); if (!(startup_info = create_startup_info( filename, cmd_line, cur_dir, env, flags, startup, &startup_info_size ))) { RtlReleasePebLock(); + RtlFreeHeap( GetProcessHeap(), 0, process_sd ); + RtlFreeHeap( GetProcessHeap(), 0, thread_sd ); close( socketfd[0] ); close( socketfd[1] ); return FALSE; @@ -2036,10 +2131,12 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW req->cpu = cpu; req->info_size = startup_info_size; req->env_size = (env_end - env) * sizeof(WCHAR); - req->process_sd_size = 0; + req->process_sd_size = process_sd_size; wine_server_add_data( req, startup_info, startup_info_size ); wine_server_add_data( req, env, (env_end - env) * sizeof(WCHAR) ); + wine_server_add_data( req, process_sd, process_sd_size ); + wine_server_add_data( req, thread_sd, thread_sd_size ); if (!(status = wine_server_call( req ))) { info->dwProcessId = (DWORD)reply->pid; @@ -2052,6 +2149,9 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW SERVER_END_REQ; RtlReleasePebLock(); + RtlFreeHeap( GetProcessHeap(), 0, process_sd ); + RtlFreeHeap( GetProcessHeap(), 0, thread_sd ); + if (status) { switch (status) -- 2.1.2