mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Pulled changes from master.
This commit is contained in:
parent
86e6d52971
commit
386a2ce3ba
@ -9,6 +9,7 @@ These patches fix the following Wine bugs:
|
||||
* Support for Junction Points ([Wine Bug #12401](http://bugs.winehq.org/show_bug.cgi?id=12401 "Support junction points, i.e. DeviceIoCtl(FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)"))
|
||||
* GetSecurityInfo returns NULL DACL for process object ([Wine Bug #15980](http://bugs.winehq.org/show_bug.cgi?id=15980 "Rhapsody 2 crashes on startup (GetSecurityInfo returns NULL DACL for process object)"))
|
||||
* Workaround for TransactNamedPipe not being supported ([Wine Bug #17273](http://bugs.winehq.org/show_bug.cgi?id=17273 "Many apps and games need SetNamedPipeHandleState implementation (support for named pipe message mode)(FireFox+Flash, Win8/NET 4.x SDK/vcrun2012, WiX installers)"))
|
||||
* Support for process ACLs ([Wine Bug #22006](http://bugs.winehq.org/show_bug.cgi?id=22006 "OpenProcess does not enforce ACL"))
|
||||
* Add implementation of WTSEnumerateProcessesW ([Wine Bug #29903](http://bugs.winehq.org/show_bug.cgi?id=29903 "Some Microsoft debuggers fail to enumerate processes due to wtsapi32.WTSEnumerateProcessesW() being a stub (Microsoft Visual Studio 2005, DbgCLR from .NET 2.0 SDK)"))
|
||||
* Support for stored file ACLs ([Wine Bug #31858](http://bugs.winehq.org/show_bug.cgi?id=31858 "Netflix on Firefox fails with Internet Connection Problem when loading bar is at 99%"))
|
||||
* Implement an Arial replacement font ([Wine Bug #32323](http://bugs.winehq.org/show_bug.cgi?id=32323 "Netflix (Silverlight 4.x) and several .NET Framework 3.x/4.0 WPF apps require either Arial or Verdana to be installed"))
|
||||
|
5
debian/changelog
vendored
5
debian/changelog
vendored
@ -1,4 +1,5 @@
|
||||
wine-compholio (1.7.22) UNRELEASED; urgency=low
|
||||
wine-compholio (1.7.22) unstable; 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 13:00:03 -0600
|
||||
|
||||
wine-compholio (1.7.21) unstable; urgency=low
|
||||
* Remove several patches (accepted upstream).
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
11
patches/16-server-CreateProcess_ACLs/definition
Normal file
11
patches/16-server-CreateProcess_ACLs/definition
Normal file
@ -0,0 +1,11 @@
|
||||
Author: Joris van der Wel
|
||||
Subject: Implement passing ACLs to CreateProcess.
|
||||
Revision: 1
|
||||
Fixes: [22006] Support for process ACLs
|
||||
|
||||
# Both patches modify server/process.c
|
||||
Depends: 13-Misc_ACL
|
||||
|
||||
# Both patches modify server/protocol.def
|
||||
Depends: 09-TransmitFile
|
||||
|
@ -19,6 +19,7 @@ PATCHLIST := 00-Commandline.ok \
|
||||
13-Misc_ACL.ok \
|
||||
14-UrlCombineW.ok \
|
||||
15-wtsapi32.ok \
|
||||
16-server-CreateProcess_ACLs.ok \
|
||||
97-Pipelight.ok \
|
||||
98-Miscellaneous.ok
|
||||
|
||||
@ -277,6 +278,23 @@ abort:
|
||||
echo "+ { \"15-wtsapi32\", \"Sebastian Lackner\", \"Partial implementation of WTSEnumerateProcessesW.\" },"; \
|
||||
) > 15-wtsapi32.ok
|
||||
|
||||
# Patchset 16-server-CreateProcess_ACLs
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Implement passing ACLs to CreateProcess. [by Joris van der Wel]
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#22006] OpenProcess does not enforce ACL
|
||||
# |
|
||||
16-server-CreateProcess_ACLs.ok: 09-TransmitFile.ok 13-Misc_ACL.ok
|
||||
$(PATCH) < 16-server-CreateProcess_ACLs/0001-server-A-new-function-set_sd_defaults_from_token-try.patch
|
||||
$(PATCH) < 16-server-CreateProcess_ACLs/0002-server-Support-sending-process-and-thread-security-d.patch
|
||||
$(PATCH) < 16-server-CreateProcess_ACLs/0003-server-implement-passing-a-process-security-descript.patch
|
||||
$(PATCH) < 16-server-CreateProcess_ACLs/0004-server-implement-passing-a-thread-security-descripto.patch
|
||||
( \
|
||||
echo "+ { \"16-server-CreateProcess_ACLs\", \"Joris van der Wel\", \"Implement passing ACLs to CreateProcess.\" },"; \
|
||||
) > 16-server-CreateProcess_ACLs.ok
|
||||
|
||||
# Patchset 97-Pipelight
|
||||
# |
|
||||
# | Included patches:
|
||||
|
Loading…
Reference in New Issue
Block a user