summaryrefslogtreecommitdiffstats
path: root/sandbox/win
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-25 18:46:20 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-25 18:46:20 +0000
commitf8a86cffd8f1d5a1ec5d5ad509122aea413b3939 (patch)
tree959031ed2f07cb9875783fd56b8f596e74543317 /sandbox/win
parenta9bda5e7dbfe1fa93febda8bf45eb7c2dab5bd9e (diff)
downloadchromium_src-f8a86cffd8f1d5a1ec5d5ad509122aea413b3939.zip
chromium_src-f8a86cffd8f1d5a1ec5d5ad509122aea413b3939.tar.gz
chromium_src-f8a86cffd8f1d5a1ec5d5ad509122aea413b3939.tar.bz2
Attempt3 at landing this. The previous attempt failed on Windows XP because the \Sessions\Session id\BaseNamedObjects path
does not always exist on Windows XP. It only exists for terminal server sessions. Relanding this with fixes for the SyncPolicyTest.TestEvent and SyncPolicyTest.TestEventReadOnly tests. Replace the CreateEvent/OpenEvent patches with their Nt counterparts like NtOpenEvent and NtCreateEvent. Reason being :- We patch these APIS via the Export table patch which does not work with bound imports. This results in our patched functions never getting called. This should fix the GPU process hang with the XP presentation path. The change from the previous patch is to resolve the BaseNamedObjects path via the \Sessions\BNOLinks directory which contains the BaseNamedObjects symbolic links for the running sessions BUG=305815 R=cpu@chromium.org, rvargas@chromium.org, cpu, rvargas Review URL: https://codereview.chromium.org/41193002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231063 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/win')
-rw-r--r--sandbox/win/src/interceptors.h6
-rw-r--r--sandbox/win/src/interceptors_64.cc43
-rw-r--r--sandbox/win/src/interceptors_64.h26
-rw-r--r--sandbox/win/src/nt_internals.h26
-rw-r--r--sandbox/win/src/sync_dispatcher.cc36
-rw-r--r--sandbox/win/src/sync_dispatcher.h5
-rw-r--r--sandbox/win/src/sync_interception.cc234
-rw-r--r--sandbox/win/src/sync_interception.h75
-rw-r--r--sandbox/win/src/sync_policy.cc169
-rw-r--r--sandbox/win/src/sync_policy.h3
10 files changed, 350 insertions, 273 deletions
diff --git a/sandbox/win/src/interceptors.h b/sandbox/win/src/interceptors.h
index 2e6dc8d..43126d0 100644
--- a/sandbox/win/src/interceptors.h
+++ b/sandbox/win/src/interceptors.h
@@ -39,10 +39,8 @@ enum InterceptorId {
OPEN_KEY_ID,
OPEN_KEY_EX_ID,
// Sync dispatcher:
- CREATE_EVENTW_ID,
- CREATE_EVENTA_ID,
- OPEN_EVENTW_ID,
- OPEN_EVENTA_ID,
+ CREATE_EVENT_ID,
+ OPEN_EVENT_ID,
// CSRSS bypasses for HandleCloser:
CREATE_THREAD_ID,
GET_USER_DEFAULT_LCID_ID,
diff --git a/sandbox/win/src/interceptors_64.cc b/sandbox/win/src/interceptors_64.cc
index a363732..c71d5a2 100644
--- a/sandbox/win/src/interceptors_64.cc
+++ b/sandbox/win/src/interceptors_64.cc
@@ -249,36 +249,23 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKeyEx64(
// -----------------------------------------------------------------------
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateEventW64(
- LPSECURITY_ATTRIBUTES security_attributes, BOOL manual_reset,
- BOOL initial_state, LPCWSTR name) {
- CreateEventWFunction orig_fn = reinterpret_cast<
- CreateEventWFunction>(g_originals[CREATE_EVENTW_ID]);
- return TargetCreateEventW(orig_fn, security_attributes, manual_reset,
- initial_state, name);
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateEvent64(
+ PHANDLE event_handle, ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes, EVENT_TYPE event_type,
+ BOOLEAN initial_state) {
+ NtCreateEventFunction orig_fn = reinterpret_cast<
+ NtCreateEventFunction>(g_originals[CREATE_EVENT_ID]);
+ return TargetNtCreateEvent(orig_fn, event_handle, desired_access,
+ object_attributes, event_type, initial_state);
}
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateEventA64(
- LPSECURITY_ATTRIBUTES security_attributes, BOOL manual_reset,
- BOOL initial_state, LPCSTR name) {
- CreateEventAFunction orig_fn = reinterpret_cast<
- CreateEventAFunction>(g_originals[CREATE_EVENTA_ID]);
- return TargetCreateEventA(orig_fn, security_attributes, manual_reset,
- initial_state, name);
-}
-
-SANDBOX_INTERCEPT HANDLE WINAPI TargetOpenEventW64(
- DWORD desired_access, BOOL inherit_handle, LPCWSTR name) {
- OpenEventWFunction orig_fn = reinterpret_cast<
- OpenEventWFunction>(g_originals[OPEN_EVENTW_ID]);
- return TargetOpenEventW(orig_fn, desired_access, inherit_handle, name);
-}
-
-SANDBOX_INTERCEPT HANDLE WINAPI TargetOpenEventA64(
- DWORD desired_access, BOOL inherit_handle, LPCSTR name) {
- OpenEventAFunction orig_fn = reinterpret_cast<
- OpenEventAFunction>(g_originals[OPEN_EVENTA_ID]);
- return TargetOpenEventA(orig_fn, desired_access, inherit_handle, name);
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent64(
+ PHANDLE event_handle, ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes) {
+ NtOpenEventFunction orig_fn = reinterpret_cast<
+ NtOpenEventFunction>(g_originals[OPEN_EVENT_ID]);
+ return TargetNtOpenEvent(orig_fn, event_handle, desired_access,
+ object_attributes);
}
} // namespace sandbox
diff --git a/sandbox/win/src/interceptors_64.h b/sandbox/win/src/interceptors_64.h
index 717fb6d..ef2c10d 100644
--- a/sandbox/win/src/interceptors_64.h
+++ b/sandbox/win/src/interceptors_64.h
@@ -153,23 +153,15 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKeyEx64(
// -----------------------------------------------------------------------
// Interceptors handled by the sync dispatcher.
-// Interception of CreateEventW on the child process.
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateEventW64(
- LPSECURITY_ATTRIBUTES security_attributes, BOOL manual_reset,
- BOOL initial_state, LPCWSTR name);
-
-// Interception of CreateEventA on the child process.
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateEventA64(
- LPSECURITY_ATTRIBUTES security_attributes, BOOL manual_reset,
- BOOL initial_state, LPCSTR name);
-
-// Interception of OpenEventW on the child process.
-SANDBOX_INTERCEPT HANDLE WINAPI TargetOpenEventW64(
- DWORD desired_access, BOOL inherit_handle, LPCWSTR name);
-
-// Interception of OpenEventA on the child process.
-SANDBOX_INTERCEPT HANDLE WINAPI TargetOpenEventA64(
- DWORD desired_access, BOOL inherit_handle, LPCSTR name);
+// Interception of NtCreateEvent/NtOpenEvent on the child process.
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateEvent64(
+ PHANDLE event_handle, ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes, EVENT_TYPE event_type,
+ BOOLEAN initial_state);
+
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent64(
+ PHANDLE event_handle, ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes);
} // extern "C"
diff --git a/sandbox/win/src/nt_internals.h b/sandbox/win/src/nt_internals.h
index c9aaf92..1423be4 100644
--- a/sandbox/win/src/nt_internals.h
+++ b/sandbox/win/src/nt_internals.h
@@ -615,5 +615,31 @@ typedef VOID (WINAPI *RtlInitUnicodeStringFunction) (
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString);
+typedef enum _EVENT_TYPE {
+ NotificationEvent,
+ SynchronizationEvent
+} EVENT_TYPE, *PEVENT_TYPE;
+
+typedef NTSTATUS (WINAPI* NtOpenDirectoryObjectFunction) (
+ PHANDLE DirectoryHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes);
+
+typedef NTSTATUS (WINAPI* NtQuerySymbolicLinkObjectFunction) (
+ HANDLE LinkHandle,
+ PUNICODE_STRING LinkTarget,
+ PULONG ReturnedLength);
+
+typedef NTSTATUS (WINAPI* NtOpenSymbolicLinkObjectFunction) (
+ PHANDLE LinkHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes);
+
+#define DIRECTORY_QUERY 0x0001
+#define DIRECTORY_TRAVERSE 0x0002
+#define DIRECTORY_CREATE_OBJECT 0x0004
+#define DIRECTORY_CREATE_SUBDIRECTORY 0x0008
+#define DIRECTORY_ALL_ACCESS 0x000F
+
#endif // SANDBOX_WIN_SRC_NT_INTERNALS_H__
diff --git a/sandbox/win/src/sync_dispatcher.cc b/sandbox/win/src/sync_dispatcher.cc
index 6897dac..3769fc6 100644
--- a/sandbox/win/src/sync_dispatcher.cc
+++ b/sandbox/win/src/sync_dispatcher.cc
@@ -25,7 +25,7 @@ SyncDispatcher::SyncDispatcher(PolicyBase* policy_base)
};
static const IPCCall open_params = {
- {IPC_OPENEVENT_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE},
+ {IPC_OPENEVENT_TAG, WCHAR_TYPE, ULONG_TYPE},
reinterpret_cast<CallbackGeneric>(&SyncDispatcher::OpenEvent)
};
@@ -35,33 +35,16 @@ SyncDispatcher::SyncDispatcher(PolicyBase* policy_base)
bool SyncDispatcher::SetupService(InterceptionManager* manager,
int service) {
- bool ret = false;
- // We need to intercept kernelbase.dll on Windows 7 and beyond and
- // kernel32.dll for earlier versions.
- static const wchar_t* kWin32SyncDllName =
- base::win::GetVersion() >= base::win::VERSION_WIN7 ? kKernelBasedllName :
- kKerneldllName;
-
if (IPC_CREATEEVENT_TAG == service) {
- ret = INTERCEPT_EAT(manager, kWin32SyncDllName, CreateEventW,
- CREATE_EVENTW_ID, 20);
- if (ret) {
- ret = INTERCEPT_EAT(manager, kWin32SyncDllName, CreateEventA,
- CREATE_EVENTA_ID, 20);
- }
+ return INTERCEPT_NT(manager, NtCreateEvent, CREATE_EVENT_ID, 24);
} else if (IPC_OPENEVENT_TAG == service) {
- ret = INTERCEPT_EAT(manager, kWin32SyncDllName, OpenEventW, OPEN_EVENTW_ID,
- 16);
- if (ret) {
- ret = INTERCEPT_EAT(manager, kWin32SyncDllName, OpenEventA,
- OPEN_EVENTA_ID, 16);
- }
+ return INTERCEPT_NT(manager, NtOpenEvent, OPEN_EVENT_ID, 16);
}
- return ret;
+ return false;
}
bool SyncDispatcher::CreateEvent(IPCInfo* ipc, std::wstring* name,
- DWORD manual_reset, DWORD initial_state) {
+ DWORD event_type, DWORD initial_state) {
const wchar_t* event_name = name->c_str();
CountedParameterSet<NameBased> params;
params[NameBased::NAME] = ParamPickerMake(event_name);
@@ -70,16 +53,16 @@ bool SyncDispatcher::CreateEvent(IPCInfo* ipc, std::wstring* name,
params.GetBase());
HANDLE handle = NULL;
DWORD ret = SyncPolicy::CreateEventAction(result, *ipc->client_info, *name,
- manual_reset, initial_state,
+ event_type, initial_state,
&handle);
// Return operation status on the IPC.
- ipc->return_info.win32_result = ret;
+ ipc->return_info.nt_status = ret;
ipc->return_info.handle = handle;
return true;
}
bool SyncDispatcher::OpenEvent(IPCInfo* ipc, std::wstring* name,
- DWORD desired_access, DWORD inherit_handle) {
+ DWORD desired_access) {
const wchar_t* event_name = name->c_str();
CountedParameterSet<OpenEventParams> params;
@@ -90,8 +73,7 @@ bool SyncDispatcher::OpenEvent(IPCInfo* ipc, std::wstring* name,
params.GetBase());
HANDLE handle = NULL;
DWORD ret = SyncPolicy::OpenEventAction(result, *ipc->client_info, *name,
- desired_access, inherit_handle,
- &handle);
+ desired_access, &handle);
// Return operation status on the IPC.
ipc->return_info.win32_result = ret;
ipc->return_info.handle = handle;
diff --git a/sandbox/win/src/sync_dispatcher.h b/sandbox/win/src/sync_dispatcher.h
index 13c8b9d3..1d1b978 100644
--- a/sandbox/win/src/sync_dispatcher.h
+++ b/sandbox/win/src/sync_dispatcher.h
@@ -22,12 +22,11 @@ class SyncDispatcher : public Dispatcher {
private:
// Processes IPC requests coming from calls to CreateEvent in the target.
- bool CreateEvent(IPCInfo* ipc, std::wstring* name, DWORD manual_reset,
+ bool CreateEvent(IPCInfo* ipc, std::wstring* name, DWORD event_type,
DWORD initial_state);
// Processes IPC requests coming from calls to OpenEvent in the target.
- bool OpenEvent(IPCInfo* ipc, std::wstring* name, DWORD desired_access,
- DWORD inherit_handle);
+ bool OpenEvent(IPCInfo* ipc, std::wstring* name, DWORD desired_access);
PolicyBase* policy_base_;
DISALLOW_COPY_AND_ASSIGN(SyncDispatcher);
diff --git a/sandbox/win/src/sync_interception.cc b/sandbox/win/src/sync_interception.cc
index ddbcc05..cafbcb0 100644
--- a/sandbox/win/src/sync_interception.cc
+++ b/sandbox/win/src/sync_interception.cc
@@ -17,33 +17,25 @@ namespace sandbox {
ResultCode ProxyCreateEvent(LPCWSTR name,
BOOL initial_state,
- BOOL manual_reset,
+ EVENT_TYPE event_type,
+ void* ipc_memory,
CrossCallReturn* answer) {
- void* memory = GetGlobalIPCMemory();
- if (!memory)
- return SBOX_ERROR_GENERIC;
-
CountedParameterSet<NameBased> params;
params[NameBased::NAME] = ParamPickerMake(name);
if (!QueryBroker(IPC_CREATEEVENT_TAG, params.GetBase()))
return SBOX_ERROR_GENERIC;
- SharedMemIPCClient ipc(memory);
- ResultCode code = CrossCall(ipc, IPC_CREATEEVENT_TAG, name, manual_reset,
+ SharedMemIPCClient ipc(ipc_memory);
+ ResultCode code = CrossCall(ipc, IPC_CREATEEVENT_TAG, name, event_type,
initial_state, answer);
return code;
}
ResultCode ProxyOpenEvent(LPCWSTR name,
ACCESS_MASK desired_access,
- BOOL inherit_handle,
+ void* ipc_memory,
CrossCallReturn* answer) {
- void* memory = GetGlobalIPCMemory();
- if (!memory)
- return SBOX_ERROR_GENERIC;
-
- uint32 inherit_handle_ipc = inherit_handle;
CountedParameterSet<OpenEventParams> params;
params[OpenEventParams::NAME] = ParamPickerMake(name);
params[OpenEventParams::ACCESS] = ParamPickerMake(desired_access);
@@ -51,135 +43,119 @@ ResultCode ProxyOpenEvent(LPCWSTR name,
if (!QueryBroker(IPC_OPENEVENT_TAG, params.GetBase()))
return SBOX_ERROR_GENERIC;
- SharedMemIPCClient ipc(memory);
+ SharedMemIPCClient ipc(ipc_memory);
ResultCode code = CrossCall(ipc, IPC_OPENEVENT_TAG, name, desired_access,
- inherit_handle_ipc, answer);
+ answer);
return code;
}
-HANDLE WINAPI TargetCreateEventW(CreateEventWFunction orig_CreateEvent,
- LPSECURITY_ATTRIBUTES security_attributes,
- BOOL manual_reset,
- BOOL initial_state,
- LPCWSTR name) {
- // Check if the process can create it first.
- HANDLE handle = orig_CreateEvent(security_attributes, manual_reset,
- initial_state, name);
- if (handle || !name)
- return handle;
-
- // We don't trust that the IPC can work this early.
- if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
- return NULL;
-
- DWORD original_error = ::GetLastError();
-
- CrossCallReturn answer = {0};
- ResultCode code = ProxyCreateEvent(name, initial_state, manual_reset,
- &answer);
-
- if (code == SBOX_ALL_OK) {
- ::SetLastError(answer.win32_result);
- return answer.handle;
- }
- ::SetLastError(original_error);
- return NULL;
-}
-
-HANDLE WINAPI TargetCreateEventA(CreateEventAFunction orig_CreateEvent,
- LPSECURITY_ATTRIBUTES security_attributes,
- BOOL manual_reset,
- BOOL initial_state,
- LPCSTR name) {
- // Check if the process can create it first.
- HANDLE handle = orig_CreateEvent(security_attributes, manual_reset,
- initial_state, name);
- if (handle || !name)
- return handle;
-
- // We don't trust that the IPC can work this early.
- if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
- return NULL;
-
- DWORD original_error = ::GetLastError();
-
- UNICODE_STRING* wide_name = AnsiToUnicode(name);
- if (!wide_name)
- return NULL;
-
- CrossCallReturn answer = {0};
- ResultCode code = ProxyCreateEvent(wide_name->Buffer, initial_state,
- manual_reset, &answer);
- operator delete(wide_name, NT_ALLOC);
-
- if (code == SBOX_ALL_OK) {
- ::SetLastError(answer.win32_result);
- return answer.handle;
- }
- ::SetLastError(original_error);
- return NULL;
-}
-
-// Interception of OpenEventW on the child process.
-// It should never be called directly
-HANDLE WINAPI TargetOpenEventW(OpenEventWFunction orig_OpenEvent,
- DWORD desired_access,
- BOOL inherit_handle,
- LPCWSTR name) {
- // Check if the process can open it first.
- HANDLE handle = orig_OpenEvent(desired_access, inherit_handle, name);
- if (handle || !name)
- return handle;
+NTSTATUS WINAPI TargetNtCreateEvent(NtCreateEventFunction orig_CreateEvent,
+ PHANDLE event_handle,
+ ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes,
+ EVENT_TYPE event_type,
+ BOOLEAN initial_state) {
+ NTSTATUS status = orig_CreateEvent(event_handle, desired_access,
+ object_attributes, event_type,
+ initial_state);
+ if (status != STATUS_ACCESS_DENIED || !object_attributes)
+ return status;
// We don't trust that the IPC can work this early.
if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
- return NULL;
-
- DWORD original_error = ::GetLastError();
-
- CrossCallReturn answer = {0};
-
- ResultCode code = ProxyOpenEvent(name, desired_access, inherit_handle,
- &answer);
- if (code == SBOX_ALL_OK) {
- ::SetLastError(answer.win32_result);
- return answer.handle;
- }
- ::SetLastError(original_error);
- return NULL;
+ return status;
+
+ do {
+ if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE))
+ break;
+
+ void* memory = GetGlobalIPCMemory();
+ if (memory == NULL)
+ break;
+
+ OBJECT_ATTRIBUTES object_attribs_copy = *object_attributes;
+ // The RootDirectory points to BaseNamedObjects. We can ignore it.
+ object_attribs_copy.RootDirectory = NULL;
+
+ wchar_t* name = NULL;
+ uint32 attributes = 0;
+ NTSTATUS ret = AllocAndCopyName(&object_attribs_copy, &name, &attributes,
+ NULL);
+ if (!NT_SUCCESS(ret) || name == NULL)
+ break;
+
+ CrossCallReturn answer = {0};
+ answer.nt_status = status;
+ ResultCode code = ProxyCreateEvent(name, initial_state, event_type, memory,
+ &answer);
+ operator delete(name, NT_ALLOC);
+
+ if (code != SBOX_ALL_OK) {
+ status = answer.nt_status;
+ break;
+ }
+ __try {
+ *event_handle = answer.handle;
+ status = STATUS_SUCCESS;
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ break;
+ }
+ } while (false);
+
+ return status;
}
-HANDLE WINAPI TargetOpenEventA(OpenEventAFunction orig_OpenEvent,
- DWORD desired_access,
- BOOL inherit_handle,
- LPCSTR name) {
- // Check if the process can open it first.
- HANDLE handle = orig_OpenEvent(desired_access, inherit_handle, name);
- if (handle || !name)
- return handle;
+NTSTATUS WINAPI TargetNtOpenEvent(NtOpenEventFunction orig_OpenEvent,
+ PHANDLE event_handle,
+ ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes) {
+ NTSTATUS status = orig_OpenEvent(event_handle, desired_access,
+ object_attributes);
+ if (status != STATUS_ACCESS_DENIED || !object_attributes)
+ return status;
// We don't trust that the IPC can work this early.
if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
- return NULL;
-
- DWORD original_error = ::GetLastError();
-
- UNICODE_STRING* wide_name = AnsiToUnicode(name);
- if (!wide_name)
- return NULL;
-
- CrossCallReturn answer = {0};
- ResultCode code = ProxyOpenEvent(wide_name->Buffer, desired_access,
- inherit_handle, &answer);
- operator delete(wide_name, NT_ALLOC);
-
- if (code == SBOX_ALL_OK) {
- ::SetLastError(answer.win32_result);
- return answer.handle;
- }
- ::SetLastError(original_error);
- return NULL;
+ return status;
+
+ do {
+ if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE))
+ break;
+
+ void* memory = GetGlobalIPCMemory();
+ if (memory == NULL)
+ break;
+
+ OBJECT_ATTRIBUTES object_attribs_copy = *object_attributes;
+ // The RootDirectory points to BaseNamedObjects. We can ignore it.
+ object_attribs_copy.RootDirectory = NULL;
+
+ wchar_t* name = NULL;
+ uint32 attributes = 0;
+ NTSTATUS ret = AllocAndCopyName(&object_attribs_copy, &name, &attributes,
+ NULL);
+ if (!NT_SUCCESS(ret) || name == NULL)
+ break;
+
+ CrossCallReturn answer = {0};
+ answer.nt_status = status;
+ ResultCode code = ProxyOpenEvent(name, desired_access, memory, &answer);
+ operator delete(name, NT_ALLOC);
+
+ if (code != SBOX_ALL_OK) {
+ status = answer.nt_status;
+ break;
+ }
+ __try {
+ *event_handle = answer.handle;
+ status = STATUS_SUCCESS;
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ break;
+ }
+ } while (false);
+
+ return status;
}
} // namespace sandbox
diff --git a/sandbox/win/src/sync_interception.h b/sandbox/win/src/sync_interception.h
index 19790f7..0f985a8 100644
--- a/sandbox/win/src/sync_interception.h
+++ b/sandbox/win/src/sync_interception.h
@@ -12,55 +12,32 @@ namespace sandbox {
extern "C" {
-typedef HANDLE (WINAPI *CreateEventWFunction) (
- LPSECURITY_ATTRIBUTES lpEventAttributes,
- BOOL bManualReset,
- BOOL bInitialState,
- LPCWSTR lpName);
-
-typedef HANDLE (WINAPI *CreateEventAFunction) (
- LPSECURITY_ATTRIBUTES lpEventAttributes,
- BOOL bManualReset,
- BOOL bInitialState,
- LPCSTR lpName);
-
-typedef HANDLE (WINAPI *OpenEventWFunction) (
- DWORD dwDesiredAccess,
- BOOL bInitialState,
- LPCWSTR lpName);
-
-typedef HANDLE (WINAPI *OpenEventAFunction) (
- DWORD dwDesiredAccess,
- BOOL bInheritHandle,
- LPCSTR lpName);
-
-// Interceptors for CreateEventW/A
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateEventW(
- CreateEventWFunction orig_CreateEvent,
- LPSECURITY_ATTRIBUTES security_attributes,
- BOOL manual_reset,
- BOOL initial_state,
- LPCWSTR name);
-
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateEventA(
- CreateEventAFunction orig_CreateEvent,
- LPSECURITY_ATTRIBUTES security_attributes,
- BOOL manual_reset,
- BOOL initial_state,
- LPCSTR name);
-
-// Interceptors for OpenEventW/A
-SANDBOX_INTERCEPT HANDLE WINAPI TargetOpenEventW(
- OpenEventWFunction orig_OpenEvent,
- DWORD desired_access,
- BOOL inherit_handle,
- LPCWSTR name);
-
-SANDBOX_INTERCEPT HANDLE WINAPI TargetOpenEventA(
- OpenEventAFunction orig_OpenEvent,
- DWORD desired_access,
- BOOL inherit_handle,
- LPCSTR name);
+typedef NTSTATUS (WINAPI* NtCreateEventFunction) (
+ PHANDLE EventHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ EVENT_TYPE EventType,
+ BOOLEAN InitialState);
+
+typedef NTSTATUS (WINAPI *NtOpenEventFunction) (
+ PHANDLE EventHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes);
+
+// Interceptors for NtCreateEvent/NtOpenEvent
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateEvent(
+ NtCreateEventFunction orig_CreateEvent,
+ PHANDLE event_handle,
+ ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes,
+ EVENT_TYPE event_type,
+ BOOLEAN initial_state);
+
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent(
+ NtOpenEventFunction orig_OpenEvent,
+ PHANDLE event_handle,
+ ACCESS_MASK desired_access,
+ POBJECT_ATTRIBUTES object_attributes);
} // extern "C"
diff --git a/sandbox/win/src/sync_policy.cc b/sandbox/win/src/sync_policy.cc
index 87ef0bd..e3b6530 100644
--- a/sandbox/win/src/sync_policy.cc
+++ b/sandbox/win/src/sync_policy.cc
@@ -7,14 +7,129 @@
#include "sandbox/win/src/sync_policy.h"
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/policy_engine_opcodes.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/sandbox_utils.h"
+#include "sandbox/win/src/sync_interception.h"
+#include "sandbox/win/src/win_utils.h"
namespace sandbox {
+// Provides functionality to resolve a symbolic link within the object
+// directory passed in.
+NTSTATUS ResolveSymbolicLink(const std::wstring& directory_name,
+ const std::wstring& name,
+ std::wstring* target) {
+ NtOpenDirectoryObjectFunction NtOpenDirectoryObject = NULL;
+ ResolveNTFunctionPtr("NtOpenDirectoryObject", &NtOpenDirectoryObject);
+
+ NtQuerySymbolicLinkObjectFunction NtQuerySymbolicLinkObject = NULL;
+ ResolveNTFunctionPtr("NtQuerySymbolicLinkObject",
+ &NtQuerySymbolicLinkObject);
+
+ NtOpenSymbolicLinkObjectFunction NtOpenSymbolicLinkObject = NULL;
+ ResolveNTFunctionPtr("NtOpenSymbolicLinkObject", &NtOpenSymbolicLinkObject);
+
+ NtCloseFunction NtClose = NULL;
+ ResolveNTFunctionPtr("NtClose", &NtClose);
+
+ OBJECT_ATTRIBUTES symbolic_link_directory_attributes = {};
+ UNICODE_STRING symbolic_link_directory_string = {};
+ InitObjectAttribs(directory_name, OBJ_CASE_INSENSITIVE, NULL,
+ &symbolic_link_directory_attributes,
+ &symbolic_link_directory_string);
+
+ HANDLE symbolic_link_directory = NULL;
+ NTSTATUS status = NtOpenDirectoryObject(&symbolic_link_directory,
+ DIRECTORY_QUERY,
+ &symbolic_link_directory_attributes);
+ if (status != STATUS_SUCCESS) {
+ DLOG(ERROR) << "Failed to open symbolic link directory. Error: "
+ << status;
+ return status;
+ }
+
+ OBJECT_ATTRIBUTES symbolic_link_attributes = {};
+ UNICODE_STRING name_string = {};
+ InitObjectAttribs(name, OBJ_CASE_INSENSITIVE, symbolic_link_directory,
+ &symbolic_link_attributes, &name_string);
+
+ HANDLE symbolic_link = NULL;
+ status = NtOpenSymbolicLinkObject(&symbolic_link, GENERIC_READ,
+ &symbolic_link_attributes);
+ NtClose(symbolic_link_directory);
+ if (status != STATUS_SUCCESS) {
+ DLOG(ERROR) << "Failed to open symbolic link Error: " << status;
+ return status;
+ }
+
+ UNICODE_STRING target_path = {};
+ unsigned long target_length = 0;
+ status = NtQuerySymbolicLinkObject(symbolic_link, &target_path,
+ &target_length);
+ if (status != STATUS_BUFFER_TOO_SMALL) {
+ NtClose(symbolic_link);
+ DLOG(ERROR) << "Failed to get length for symbolic link target. Error: "
+ << status;
+ return status;
+ }
+
+ target_path.Buffer = new wchar_t[target_length + 1];
+ target_path.Length = 0;
+ target_path.MaximumLength = target_length;
+ status = NtQuerySymbolicLinkObject(symbolic_link, &target_path,
+ &target_length);
+ if (status == STATUS_SUCCESS) {
+ target->assign(target_path.Buffer, target_length);
+ } else {
+ DLOG(ERROR) << "Failed to resolve symbolic link. Error: " << status;
+ }
+
+ NtClose(symbolic_link);
+ delete[] target_path.Buffer;
+ return status;
+}
+
+NTSTATUS GetBaseNamedObjectsDirectory(HANDLE* directory) {
+ static HANDLE base_named_objects_handle = NULL;
+ if (base_named_objects_handle) {
+ *directory = base_named_objects_handle;
+ return STATUS_SUCCESS;
+ }
+
+ NtOpenDirectoryObjectFunction NtOpenDirectoryObject = NULL;
+ ResolveNTFunctionPtr("NtOpenDirectoryObject", &NtOpenDirectoryObject);
+
+ DWORD session_id = 0;
+ ProcessIdToSessionId(::GetCurrentProcessId(), &session_id);
+
+ std::wstring base_named_objects_path;
+
+ NTSTATUS status = ResolveSymbolicLink(L"\\Sessions\\BNOLINKS",
+ base::StringPrintf(L"%d", session_id),
+ &base_named_objects_path);
+ if (status != STATUS_SUCCESS) {
+ DLOG(ERROR) << "Failed to resolve BaseNamedObjects path. Error: "
+ << status;
+ return status;
+ }
+
+ UNICODE_STRING directory_name = {};
+ OBJECT_ATTRIBUTES object_attributes = {};
+ InitObjectAttribs(base_named_objects_path, OBJ_CASE_INSENSITIVE, NULL,
+ &object_attributes, &directory_name);
+ status = NtOpenDirectoryObject(&base_named_objects_handle,
+ DIRECTORY_ALL_ACCESS,
+ &object_attributes);
+ if (status == STATUS_SUCCESS)
+ *directory = base_named_objects_handle;
+ return status;
+}
+
bool SyncPolicy::GenerateRules(const wchar_t* name,
TargetPolicy::Semantics semantics,
LowLevelPolicy* policy) {
@@ -64,49 +179,75 @@ bool SyncPolicy::GenerateRules(const wchar_t* name,
DWORD SyncPolicy::CreateEventAction(EvalResult eval_result,
const ClientInfo& client_info,
const std::wstring &event_name,
- uint32 manual_reset,
+ uint32 event_type,
uint32 initial_state,
HANDLE *handle) {
+ NtCreateEventFunction NtCreateEvent = NULL;
+ ResolveNTFunctionPtr("NtCreateEvent", &NtCreateEvent);
+
// The only action supported is ASK_BROKER which means create the requested
// file as specified.
if (ASK_BROKER != eval_result)
return false;
- HANDLE local_handle = ::CreateEvent(NULL, manual_reset, initial_state,
- event_name.c_str());
+ HANDLE object_directory = NULL;
+ NTSTATUS status = GetBaseNamedObjectsDirectory(&object_directory);
+ if (status != STATUS_SUCCESS)
+ return status;
+
+ UNICODE_STRING unicode_event_name = {};
+ OBJECT_ATTRIBUTES object_attributes = {};
+ InitObjectAttribs(event_name, OBJ_CASE_INSENSITIVE, object_directory,
+ &object_attributes, &unicode_event_name);
+
+ HANDLE local_handle = NULL;
+ status = NtCreateEvent(&local_handle, EVENT_ALL_ACCESS, &object_attributes,
+ static_cast<EVENT_TYPE>(event_type), initial_state);
if (NULL == local_handle)
- return ::GetLastError();
+ return status;
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, FALSE,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
- return ERROR_ACCESS_DENIED;
+ return STATUS_ACCESS_DENIED;
}
- return ERROR_SUCCESS;
+ return status;
}
DWORD SyncPolicy::OpenEventAction(EvalResult eval_result,
const ClientInfo& client_info,
const std::wstring &event_name,
uint32 desired_access,
- uint32 inherit_handle,
HANDLE *handle) {
+ NtOpenEventFunction NtOpenEvent = NULL;
+ ResolveNTFunctionPtr("NtOpenEvent", &NtOpenEvent);
+
// The only action supported is ASK_BROKER which means create the requested
- // file as specified.
+ // event as specified.
if (ASK_BROKER != eval_result)
return false;
- HANDLE local_handle = ::OpenEvent(desired_access, FALSE,
- event_name.c_str());
+ HANDLE object_directory = NULL;
+ NTSTATUS status = GetBaseNamedObjectsDirectory(&object_directory);
+ if (status != STATUS_SUCCESS)
+ return status;
+
+ UNICODE_STRING unicode_event_name = {};
+ OBJECT_ATTRIBUTES object_attributes = {};
+ InitObjectAttribs(event_name, OBJ_CASE_INSENSITIVE, object_directory,
+ &object_attributes, &unicode_event_name);
+
+ HANDLE local_handle = NULL;
+ status = NtOpenEvent(&local_handle, desired_access, &object_attributes);
if (NULL == local_handle)
- return ::GetLastError();
+ return status;
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
- client_info.process, handle, 0, inherit_handle,
+ client_info.process, handle, 0, FALSE,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
- return ERROR_ACCESS_DENIED;
+ return STATUS_ACCESS_DENIED;
}
- return ERROR_SUCCESS;
+ return status;
}
} // namespace sandbox
diff --git a/sandbox/win/src/sync_policy.h b/sandbox/win/src/sync_policy.h
index 2b8b422..93aef64 100644
--- a/sandbox/win/src/sync_policy.h
+++ b/sandbox/win/src/sync_policy.h
@@ -35,14 +35,13 @@ class SyncPolicy {
static DWORD CreateEventAction(EvalResult eval_result,
const ClientInfo& client_info,
const std::wstring &event_name,
- uint32 manual_reset,
+ uint32 event_type,
uint32 initial_state,
HANDLE *handle);
static DWORD OpenEventAction(EvalResult eval_result,
const ClientInfo& client_info,
const std::wstring &event_name,
uint32 desired_access,
- uint32 inherit_handle,
HANDLE *handle);
};