Commit 0807714f authored by Will Harris's avatar Will Harris Committed by Commit Bot

Allow shared memory IPC client to work before kernel32 is fully loaded.

This is required for intercepts to work very early during
the initialization of the target process.

BUG=750886

Change-Id: I81a4bc43fc6652d473b557ade7f55d54cdb2a6d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1658591
Commit-Queue: Will Harris <wfh@chromium.org>
Reviewed-by: default avatarJames Forshaw <forshaw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#669052}
parent 01a2f52e
......@@ -695,6 +695,11 @@ typedef NTSTATUS(WINAPI* NtSignalAndWaitForSingleObjectFunction)(
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL);
typedef NTSTATUS(WINAPI* NtWaitForSingleObjectFunction)(
IN HANDLE ObjectHandle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL);
typedef NTSTATUS(WINAPI* NtQuerySystemInformation)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
......
......@@ -55,6 +55,8 @@ bool InitGlobalNt() {
INIT_GLOBAL_NT(QuerySection);
INIT_GLOBAL_NT(QueryVirtualMemory);
INIT_GLOBAL_NT(UnmapViewOfSection);
INIT_GLOBAL_NT(SignalAndWaitForSingleObject);
INIT_GLOBAL_NT(WaitForSingleObject);
INIT_GLOBAL_RTL(RtlAllocateHeap);
INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString);
......
......@@ -10,28 +10,30 @@
namespace sandbox {
struct NtExports {
NtAllocateVirtualMemoryFunction AllocateVirtualMemory;
NtCloseFunction Close;
NtDuplicateObjectFunction DuplicateObject;
NtFreeVirtualMemoryFunction FreeVirtualMemory;
NtMapViewOfSectionFunction MapViewOfSection;
NtProtectVirtualMemoryFunction ProtectVirtualMemory;
NtQueryInformationProcessFunction QueryInformationProcess;
NtQueryObjectFunction QueryObject;
NtQuerySectionFunction QuerySection;
NtQueryVirtualMemoryFunction QueryVirtualMemory;
NtUnmapViewOfSectionFunction UnmapViewOfSection;
RtlAllocateHeapFunction RtlAllocateHeap;
RtlAnsiStringToUnicodeStringFunction RtlAnsiStringToUnicodeString;
RtlCompareUnicodeStringFunction RtlCompareUnicodeString;
RtlCreateHeapFunction RtlCreateHeap;
RtlCreateUserThreadFunction RtlCreateUserThread;
RtlDestroyHeapFunction RtlDestroyHeap;
RtlFreeHeapFunction RtlFreeHeap;
_strnicmpFunction _strnicmp;
strlenFunction strlen;
wcslenFunction wcslen;
memcpyFunction memcpy;
NtAllocateVirtualMemoryFunction AllocateVirtualMemory;
NtCloseFunction Close;
NtDuplicateObjectFunction DuplicateObject;
NtFreeVirtualMemoryFunction FreeVirtualMemory;
NtMapViewOfSectionFunction MapViewOfSection;
NtProtectVirtualMemoryFunction ProtectVirtualMemory;
NtQueryInformationProcessFunction QueryInformationProcess;
NtQueryObjectFunction QueryObject;
NtQuerySectionFunction QuerySection;
NtQueryVirtualMemoryFunction QueryVirtualMemory;
NtUnmapViewOfSectionFunction UnmapViewOfSection;
NtSignalAndWaitForSingleObjectFunction SignalAndWaitForSingleObject;
NtWaitForSingleObjectFunction WaitForSingleObject;
RtlAllocateHeapFunction RtlAllocateHeap;
RtlAnsiStringToUnicodeStringFunction RtlAnsiStringToUnicodeString;
RtlCompareUnicodeStringFunction RtlCompareUnicodeString;
RtlCreateHeapFunction RtlCreateHeap;
RtlCreateUserThreadFunction RtlCreateUserThread;
RtlDestroyHeapFunction RtlDestroyHeap;
RtlFreeHeapFunction RtlFreeHeap;
_strnicmpFunction _strnicmp;
strlenFunction strlen;
wcslenFunction wcslen;
memcpyFunction memcpy;
};
// This is the value used for the ntdll level allocator.
......
......@@ -11,9 +11,50 @@
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/crosscall_params.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_nt_types.h"
#include "sandbox/win/src/sandbox_nt_util.h"
namespace sandbox {
SANDBOX_INTERCEPT NtExports g_nt;
namespace {
DWORD SignalObjectAndWaitWrapper(HANDLE object_to_signal,
HANDLE object_to_wait_on,
DWORD millis,
BOOL alertable) {
// Not running in a sandboxed process so can call directly.
if (!g_nt.SignalAndWaitForSingleObject)
return SignalObjectAndWait(object_to_signal, object_to_wait_on, millis,
alertable);
// Don't support alertable.
CHECK_NT(!alertable);
LARGE_INTEGER timeout;
timeout.QuadPart = millis * -10000LL;
NTSTATUS status = g_nt.SignalAndWaitForSingleObject(
object_to_signal, object_to_wait_on, alertable,
millis == INFINITE ? nullptr : &timeout);
if (!NT_SUCCESS(status))
return WAIT_FAILED;
return status;
}
DWORD WaitForSingleObjectWrapper(HANDLE handle, DWORD millis) {
// Not running in a sandboxed process so can call directly.
if (!g_nt.WaitForSingleObject)
return WaitForSingleObject(handle, millis);
LARGE_INTEGER timeout;
timeout.QuadPart = millis * -10000LL;
NTSTATUS status = g_nt.WaitForSingleObject(
handle, FALSE, millis == INFINITE ? nullptr : &timeout);
if (!NT_SUCCESS(status))
return WAIT_FAILED;
return status;
}
} // namespace
// Get the base of the data buffer of the channel; this is where the input
// parameters get serialized. Since they get serialized directly into the
// channel we avoid one copy.
......@@ -68,18 +109,19 @@ ResultCode SharedMemIPCClient::DoCall(CrossCallParams* params,
// While the atomic signaling and waiting is not a requirement, it
// is nice because we save a trip to kernel.
DWORD wait =
::SignalObjectAndWait(channel[num].ping_event, channel[num].pong_event,
kIPCWaitTimeOut1, false);
DWORD wait = SignalObjectAndWaitWrapper(channel[num].ping_event,
channel[num].pong_event,
kIPCWaitTimeOut1, false);
if (WAIT_TIMEOUT == wait) {
// The server is taking too long. Enter a loop were we check if the
// server_alive mutex has been abandoned which would signal a server crash
// or else we keep waiting for a response.
while (true) {
wait = ::WaitForSingleObject(control_->server_alive, 0);
wait = WaitForSingleObjectWrapper(control_->server_alive, 0);
if (WAIT_TIMEOUT == wait) {
// Server seems still alive. We already signaled so here we just wait.
wait = ::WaitForSingleObject(channel[num].pong_event, kIPCWaitTimeOut1);
wait = WaitForSingleObjectWrapper(channel[num].pong_event,
kIPCWaitTimeOut1);
if (WAIT_OBJECT_0 == wait) {
// The server took a long time but responded.
break;
......@@ -131,7 +173,7 @@ size_t SharedMemIPCClient::LockFreeChannel(bool* severe_failure) {
}
// We did not find any available channel, maybe the server is dead.
DWORD wait =
::WaitForSingleObject(control_->server_alive, kIPCWaitTimeOut2);
WaitForSingleObjectWrapper(control_->server_alive, kIPCWaitTimeOut2);
if (WAIT_TIMEOUT != wait) {
// The server is dead and we outlive it enough to get in trouble.
*severe_failure = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment