Implement passing ACLs to CreateProcess.

This commit is contained in:
Erich E. Hoover 2014-07-11 12:57:10 -06:00
parent 9d3369d7a6
commit 180fa60a17
7 changed files with 762 additions and 2 deletions

3
debian/changelog vendored
View File

@ -1,4 +1,5 @@
wine-compholio (1.7.22) UNRELEASED; urgency=low
* Implement passing ACLs to CreateProcess.
* Removed several patches (accepted upstream).
* Added NT4 support to the process ACL tests.
* Implement RegSetKeySecurity on top of NtSetSecurityObject.
@ -8,7 +9,7 @@ wine-compholio (1.7.22) UNRELEASED; urgency=low
* Updated main extended attributes patch to include BSD support.
* Return NULL-terminated list of arguments in CommandLineToArgvW.
* Updated main extended attributes patch to include additional data checks.
-- Erich E. Hoover <erich.e.hoover@gmail.com> Tue, 08 Jul 2014 14:32:30 -0600
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 11 Jul 2014 12:55:54 -0600
wine-compholio (1.7.21) unstable; urgency=low
* Remove several patches (accepted upstream).

View File

@ -0,0 +1,103 @@
From 91fb6970f6b7f5a5c93d066c143e96398fba294e Mon Sep 17 00:00:00 2001
From: Joris van der Wel <joris@jorisvanderwel.com>
Date: Wed, 9 Jul 2014 00:58:10 +0200
Subject: server: A new function "set_sd_defaults_from_token" (try 3)
server: A new function "set_sd_defaults_from_token" that sets the
security descriptor along with a token that will be used to gather
defaults, instead of always using the primary token.
Some objects take their defaults not from a primary token but from a
different one
(such as from the impersonation token or the process token).
This function can be used to create the various set_sd implementations
for the objects that need it.
As a bonus, a NULL token will skip setting any defaults, this is
useful for object implementations that would like to set their
defaults _only_ upon creation.
---
server/object.c | 23 +++++++++++++++--------
server/object.h | 2 ++
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/server/object.c b/server/object.c
index 11ef0ce..6389409 100644
--- a/server/object.c
+++ b/server/object.c
@@ -423,8 +423,8 @@ struct security_descriptor *default_get_sd( struct object *obj )
return obj->sd;
}
-int default_set_sd( struct object *obj, const struct security_descriptor *sd,
- unsigned int set_info )
+int set_sd_defaults_from_token( struct object *obj, const struct security_descriptor *sd,
+ unsigned int set_info, struct token *token )
{
struct security_descriptor new_sd, *new_sd_ptr;
int present;
@@ -446,9 +446,9 @@ int default_set_sd( struct object *obj, const struct security_descriptor *sd,
owner = sd_get_owner( obj->sd );
new_sd.owner_len = obj->sd->owner_len;
}
- else
+ else if (token)
{
- owner = token_get_user( current->process->token );
+ owner = token_get_user( token );
new_sd.owner_len = security_sid_len( owner );
}
@@ -462,9 +462,9 @@ int default_set_sd( struct object *obj, const struct security_descriptor *sd,
group = sd_get_group( obj->sd );
new_sd.group_len = obj->sd->group_len;
}
- else
+ else if (token)
{
- group = token_get_primary_group( current->process->token );
+ group = token_get_primary_group( token );
new_sd.group_len = security_sid_len( group );
}
@@ -494,9 +494,9 @@ int default_set_sd( struct object *obj, const struct security_descriptor *sd,
if (obj->sd && present)
new_sd.dacl_len = obj->sd->dacl_len;
- else
+ else if (token)
{
- dacl = token_get_default_dacl( current->process->token );
+ dacl = token_get_default_dacl( token );
new_sd.dacl_len = dacl->AclSize;
}
}
@@ -521,6 +521,13 @@ int default_set_sd( struct object *obj, const struct security_descriptor *sd,
return 1;
}
+/** Set the security descriptor using the current primary token for defaults. */
+int default_set_sd( struct object *obj, const struct security_descriptor *sd,
+ unsigned int set_info )
+{
+ return set_sd_defaults_from_token( obj, sd, set_info, current->process->token );
+}
+
struct object *no_lookup_name( struct object *obj, struct unicode_str *name,
unsigned int attr )
{
diff --git a/server/object.h b/server/object.h
index bb3ff21..7201ff9 100644
--- a/server/object.h
+++ b/server/object.h
@@ -139,6 +139,8 @@ extern struct fd *no_get_fd( struct object *obj );
extern unsigned int no_map_access( struct object *obj, unsigned int access );
extern struct security_descriptor *default_get_sd( struct object *obj );
extern int default_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info );
+extern int set_sd_defaults_from_token( struct object *obj, const struct security_descriptor *sd,
+ unsigned int set_info, struct token *token );
extern struct object *no_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attributes );
extern struct object *no_open_file( struct object *obj, unsigned int access, unsigned int sharing,
unsigned int options );
--
1.7.9.5

View File

@ -0,0 +1,176 @@
From fe16cbc2062778bef273ac84eca992dcc45653e6 Mon Sep 17 00:00:00 2001
From: Joris van der Wel <joris@jorisvanderwel.com>
Date: Wed, 9 Jul 2014 00:58:47 +0200
Subject: server: Support sending process and thread security descriptors for
the "new_process" request in the protocol.
server: Support sending process and thread security descriptors for
the "new_process" request in the protocol.
---
dlls/kernel32/process.c | 30 +++++++++++++++++-------------
server/process.c | 33 ++++++++++++++++++++-------------
server/protocol.def | 41 +++++++++++++++++++++++------------------
3 files changed, 60 insertions(+), 44 deletions(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 2566ac4..8bf1934 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -2025,19 +2025,23 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
SERVER_START_REQ( new_process )
{
- req->inherit_all = inherit;
- req->create_flags = flags;
- req->socket_fd = socketfd[1];
- req->exe_file = wine_server_obj_handle( hFile );
- req->process_access = PROCESS_ALL_ACCESS;
- req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0;
- req->thread_access = THREAD_ALL_ACCESS;
- req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
- req->cpu = cpu;
- req->info_size = startup_info_size;
-
- wine_server_add_data( req, startup_info, startup_info_size );
- wine_server_add_data( req, env, (env_end - env) * sizeof(WCHAR) );
+ req->inherit_all = inherit;
+ req->create_flags = flags;
+ req->socket_fd = socketfd[1];
+ req->exe_file = wine_server_obj_handle( hFile );
+ req->process_access = PROCESS_ALL_ACCESS;
+ req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0;
+ req->thread_access = THREAD_ALL_ACCESS;
+ req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
+ req->cpu = cpu;
+ req->process_sd_size = 0;
+ req->thread_sd_size = 0;
+ req->info_size = startup_info_size;
+ req->env_size = (env_end - env) * sizeof(WCHAR);
+
+ wine_server_add_data( req, startup_info, req->info_size );
+ wine_server_add_data( req, env , req->env_size );
+
if (!(status = wine_server_call( req )))
{
info->dwProcessId = (DWORD)reply->pid;
diff --git a/server/process.c b/server/process.c
index 7b9a3b2..9942eb3 100644
--- a/server/process.c
+++ b/server/process.c
@@ -880,6 +880,9 @@ DECL_HANDLER(new_process)
struct process *process;
struct process *parent = current->process;
int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
+ const startup_info_t *req_info;
+ data_size_t req_info_size;
+ const WCHAR *req_env;
if (socket_fd == -1)
{
@@ -903,6 +906,12 @@ DECL_HANDLER(new_process)
close( socket_fd );
return;
}
+
+ req_info = (const startup_info_t *)
+ ((char*)get_req_data() + req->process_sd_size + req->thread_sd_size);
+
+ req_env = (const WCHAR *)
+ ((char*)get_req_data() + req->process_sd_size + req->thread_sd_size + req->info_size);
if (!req->info_size) /* create an orphaned process */
{
@@ -920,27 +929,25 @@ DECL_HANDLER(new_process)
!(info->exe_file = get_file_obj( current->process, req->exe_file, FILE_READ_DATA )))
goto done;
- info->data_size = get_req_data_size();
- info->info_size = min( req->info_size, info->data_size );
-
if (req->info_size < sizeof(*info->data))
{
/* make sure we have a full startup_info_t structure */
- data_size_t env_size = info->data_size - info->info_size;
- data_size_t info_size = min( req->info_size, FIELD_OFFSET( startup_info_t, curdir_len ));
-
- if (!(info->data = mem_alloc( sizeof(*info->data) + env_size ))) goto done;
- memcpy( info->data, get_req_data(), info_size );
- memset( (char *)info->data + info_size, 0, sizeof(*info->data) - info_size );
- memcpy( info->data + 1, (const char *)get_req_data() + req->info_size, env_size );
- info->info_size = sizeof(startup_info_t);
- info->data_size = info->info_size + env_size;
+ info->info_size = sizeof(*info->data);
+ info->data_size = sizeof(*info->data) + req->env_size;
+
+ req_info_size = min( req->info_size, FIELD_OFFSET( startup_info_t, curdir_len ));
+ if (!(info->data = mem_alloc( info->data_size ))) goto done;
+ memset( info->data, 0, info->data_size );
+ memcpy( info->data, req_info, req_info_size );
+ memcpy( info->data + 1, req_env, req->env_size );
}
else
{
data_size_t pos = sizeof(*info->data);
+ info->info_size = req->info_size;
+ info->data_size = req->info_size + req->env_size;
- if (!(info->data = memdup( get_req_data(), info->data_size ))) goto done;
+ if (!(info->data = memdup( req_info, info->data_size ))) goto done;
#define FIXUP_LEN(len) do { (len) = min( (len), info->info_size - pos ); pos += (len); } while(0)
FIXUP_LEN( info->data->curdir_len );
FIXUP_LEN( info->data->dllpath_len );
diff --git a/server/protocol.def b/server/protocol.def
index a8c1fb9..7b0b769 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -661,24 +661,29 @@ struct rawinput_device
/* Create a new process from the context of the parent */
@REQ(new_process)
- int inherit_all; /* inherit all handles from parent */
- unsigned int create_flags; /* creation flags */
- int socket_fd; /* file descriptor for process socket */
- obj_handle_t exe_file; /* file handle for main exe */
- unsigned int process_access; /* access rights for process object */
- unsigned int process_attr; /* attributes for process object */
- unsigned int thread_access; /* access rights for thread object */
- unsigned int thread_attr; /* attributes for thread object */
- cpu_type_t cpu; /* CPU that the new process will use */
- data_size_t info_size; /* size of startup info */
- VARARG(info,startup_info,info_size); /* startup information */
- VARARG(env,unicode_str); /* environment for new process */
-@REPLY
- obj_handle_t info; /* new process info handle */
- process_id_t pid; /* process id */
- obj_handle_t phandle; /* process handle (in the current process) */
- thread_id_t tid; /* thread id */
- obj_handle_t thandle; /* thread handle (in the current process) */
+ int inherit_all; /* inherit all handles from parent */
+ unsigned int create_flags; /* creation flags */
+ int socket_fd; /* file descriptor for process socket */
+ obj_handle_t exe_file; /* file handle for main exe */
+ unsigned int process_access; /* access rights for process object */
+ unsigned int process_attr; /* attributes for process object */
+ unsigned int thread_access; /* access rights for thread object */
+ unsigned int thread_attr; /* attributes for thread object */
+ cpu_type_t cpu; /* CPU that the new process will use */
+ data_size_t process_sd_size; /* size of the process security descriptor */
+ data_size_t thread_sd_size; /* size of the thread security descriptor */
+ data_size_t info_size; /* size of startup info */
+ data_size_t env_size; /* size of the environment */
+ VARARG(process_sd,security_descriptor,process_sd_size); /* security descriptor to set on the process */
+ VARARG(thread_sd,security_descriptor,thread_sd_size); /* security descriptor to set on the thread */
+ VARARG(info,startup_info,info_size); /* startup information */
+ VARARG(env,unicode_str,env_size); /* environment for new process */
+@REPLY
+ obj_handle_t info; /* new process info handle */
+ process_id_t pid; /* process id */
+ obj_handle_t phandle; /* process handle (in the current process) */
+ thread_id_t tid; /* thread id */
+ obj_handle_t thandle; /* thread handle (in the current process) */
@END
--
1.7.9.5

View File

@ -0,0 +1,242 @@
From d565d8b72c9f57d5553f72dfd7d18e2e05033c0c Mon Sep 17 00:00:00 2001
From: Joris van der Wel <joris@jorisvanderwel.com>
Date: Wed, 9 Jul 2014 00:59:30 +0200
Subject: server: implement passing a process security descriptor to
CreateProcess.
server: implement passing a process security descriptor to CreateProcess.
For now the function "NTDLL_create_struct_sd" has been duplicated in
kernel32.
This is needed because kernel32 makes the server call. kernel32 currently
makes the server call because NtCreateProcess(Ex) has not been implemented in
ntdll. When NtCreateProcessEx (and NtCreateThreadEx) gets implemented, the
server call will be made from within ntdll instead, and this extra function
in kernel32 will no longer be needed.
---
dlls/advapi32/tests/security.c | 3 --
dlls/kernel32/process.c | 85 +++++++++++++++++++++++++++++++++++++++-
server/process.c | 24 ++++++++++++
3 files changed, 108 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 8bf1934..5f6c2e5 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,17 +2003,31 @@ 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;
if ((cpu = get_process_cpu( filename, binary_info )) == -1)
{
SetLastError( ERROR_BAD_EXE_FORMAT );
return FALSE;
+ }
+
+ if (psa && (psa->nLength >= sizeof(*psa)) && psa->lpSecurityDescriptor)
+ {
+ status = create_struct_sd( psa->lpSecurityDescriptor, &psd, &psd_len );
+ if (status != STATUS_SUCCESS)
+ {
+ WARN("Invalid process 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)
{
+ RtlFreeHeap(GetProcessHeap(), 0, psd);
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
return FALSE;
}
@@ -1989,6 +2067,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
winedebug, binary_info, TRUE );
}
close( socketfd[0] );
+ RtlFreeHeap(GetProcessHeap(), 0, psd);
SetLastError( RtlNtStatusToDosError( status ));
return FALSE;
}
@@ -2001,6 +2080,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
RtlReleasePebLock();
close( socketfd[0] );
close( socketfd[1] );
+ RtlFreeHeap(GetProcessHeap(), 0, psd);
return FALSE;
}
if (!env) env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
@@ -2034,11 +2114,12 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
req->thread_access = THREAD_ALL_ACCESS;
req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
req->cpu = cpu;
- req->process_sd_size = 0;
+ req->process_sd_size = psd_len;
req->thread_sd_size = 0;
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, startup_info, req->info_size );
wine_server_add_data( req, env , req->env_size );
@@ -2053,6 +2134,8 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
}
SERVER_END_REQ;
+ RtlFreeHeap(GetProcessHeap(), 0, psd);
+
RtlReleasePebLock();
if (status)
{
diff --git a/server/process.c b/server/process.c
index 9942eb3..1fba134 100644
--- a/server/process.c
+++ b/server/process.c
@@ -883,6 +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;
if (socket_fd == -1)
{
@@ -907,6 +908,17 @@ DECL_HANDLER(new_process)
return;
}
+ if (req->process_sd_size)
+ {
+ req_psd = get_req_data();
+
+ if (!sd_is_valid( req_psd, req->process_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);
@@ -1011,6 +1023,18 @@ DECL_HANDLER(new_process)
reply->phandle = alloc_handle( parent, process, req->process_access, req->process_attr );
reply->thandle = alloc_handle( parent, thread, req->thread_access, req->thread_attr );
+ /* note: alloc_handle might fail with access denied
+ * if the security descriptor is set before that call */
+
+ if (req_psd)
+ {
+ default_set_sd( &process->obj,
+ req_psd,
+ OWNER_SECURITY_INFORMATION|
+ GROUP_SECURITY_INFORMATION|
+ DACL_SECURITY_INFORMATION|
+ SACL_SECURITY_INFORMATION );
+ }
done:
release_object( info );
}
--
1.7.9.5

View File

@ -0,0 +1,234 @@
From e924e19cc72127f16b64bef300e394a7f641dba1 Mon Sep 17 00:00:00 2001
From: Joris van der Wel <joris@jorisvanderwel.com>
Date: Wed, 9 Jul 2014 01:00:02 +0200
Subject: server: implement passing a thread security descriptor to
CreateProcess
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 b1b35aa..aab63f3 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 );
FreeSid(EveryoneSid);
@@ -2673,6 +2699,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)
@@ -2728,6 +2756,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 5f6c2e5..a01e681 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -2003,8 +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 *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)
{
@@ -2022,12 +2022,26 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
return FALSE;
}
}
+
+ if (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->lpSecurityDescriptor)
+ {
+ status = create_struct_sd( tsa->lpSecurityDescriptor, &tsd, &tsd_len );
+
+ if (status != STATUS_SUCCESS)
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, 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)
{
RtlFreeHeap(GetProcessHeap(), 0, psd);
+ RtlFreeHeap(GetProcessHeap(), 0, tsd);
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
return FALSE;
}
@@ -2068,6 +2082,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
}
close( socketfd[0] );
RtlFreeHeap(GetProcessHeap(), 0, psd);
+ RtlFreeHeap(GetProcessHeap(), 0, tsd);
SetLastError( RtlNtStatusToDosError( status ));
return FALSE;
}
@@ -2081,6 +2096,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
close( socketfd[0] );
close( socketfd[1] );
RtlFreeHeap(GetProcessHeap(), 0, psd);
+ RtlFreeHeap(GetProcessHeap(), 0, tsd);
return FALSE;
}
if (!env) env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
@@ -2115,11 +2131,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 );
@@ -2135,6 +2152,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
SERVER_END_REQ;
RtlFreeHeap(GetProcessHeap(), 0, psd);
+ RtlFreeHeap(GetProcessHeap(), 0, tsd);
RtlReleasePebLock();
if (status)
diff --git a/server/process.c b/server/process.c
index 1fba134..f9a4611 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);
@@ -1035,6 +1047,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.7.9.5

View File

@ -0,0 +1,3 @@
Revision: 1
Author: Joris van der Wel
Title: Implement passing ACLs to CreateProcess.

View File

@ -6,7 +6,7 @@ diff --git a/libs/wine/config.c b/libs/wine/config.c
index a273502..5fa0cd5 100644
--- a/libs/wine/config.c
+++ b/libs/wine/config.c
@@ -478,6 +478,43 @@ const char *wine_get_version(void)
@@ -478,6 +478,44 @@ const char *wine_get_version(void)
return PACKAGE_VERSION;
}
@ -31,6 +31,7 @@ index a273502..5fa0cd5 100644
+ { "3405aa34-f341-11e3-83ce-0090f5c75ad5:1", "Erich E. Hoover", "Add default security descriptor ownership and DACLs for processes." },
+ { "e46b26df-3c1b-419c-9579-f0d1e1c50bea:1", "Sebastian Lackner", "Workaround for broken implementation of shlwapi url functions." },
+ { "3790a2d5-f930-423e-9c03-f7fc1c1e0811:1", "Sebastian Lackner", "Partial implementation of WTSEnumerateProcessesW." },
+ { "a3f43350-092c-11e4-9b1e-0090f5c75ad5:1", "Joris van der Wel", "Implement passing ACLs to CreateProcess." },
+ { "0b21d7ac-0387-4493-aa38-fbafe3e749f5:2", "Michael Müller", "Decrease minimum SetTimer interval to 5 ms." },
+ { "2394843e-2bc4-4fa4-8368-1ef32093b89e:1", "Michael Müller", "Allow changing strict draw ordering through an exported function." },
+ { "255473fa-4e0a-4f51-952b-4deecc1a2181:1", "Michael Müller", "Indicate direct rendering through OpenGL extension." },