summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sandbox/src/eat_resolver.cc19
-rw-r--r--sandbox/src/interception.h2
-rw-r--r--sandbox/src/interception_agent.cc9
-rw-r--r--sandbox/src/interception_internal.h3
-rw-r--r--sandbox/src/resolver_64.cc16
-rw-r--r--sandbox/src/sandbox_nt_util.cc94
-rw-r--r--sandbox/src/sandbox_nt_util.h5
7 files changed, 128 insertions, 20 deletions
diff --git a/sandbox/src/eat_resolver.cc b/sandbox/src/eat_resolver.cc
index 89d8c94..d4f6e83 100644
--- a/sandbox/src/eat_resolver.cc
+++ b/sandbox/src/eat_resolver.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -26,6 +26,17 @@ NTSTATUS EatResolverThunk::Setup(const void* target_module,
if (!eat_entry_)
return STATUS_INVALID_PARAMETER;
+ size_t thunk_bytes = GetInternalThunkSize();
+
+#if defined(_WIN64)
+ // We have two thunks, in order: the return path and the forward path.
+ if (!SetInternalThunk(thunk_storage, storage_bytes, NULL, target_))
+ return STATUS_BUFFER_TOO_SMALL;
+
+ storage_bytes -= thunk_bytes;
+ thunk_storage = reinterpret_cast<char*>(thunk_storage) + thunk_bytes;
+#endif
+
if (!SetInternalThunk(thunk_storage, storage_bytes, target_, interceptor_))
return STATUS_BUFFER_TOO_SMALL;
@@ -41,7 +52,7 @@ NTSTATUS EatResolverThunk::Setup(const void* target_module,
#pragma warning(pop)
if (NULL != storage_used)
- *storage_used = GetInternalThunkSize();
+ *storage_used = GetThunkSize();
return ret;
}
@@ -68,7 +79,11 @@ NTSTATUS EatResolverThunk::ResolveTarget(const void* module,
}
size_t EatResolverThunk::GetThunkSize() const {
+#if defined(_WIN64)
+ return GetInternalThunkSize() * 2;
+#else
return GetInternalThunkSize();
+#endif
}
} // namespace sandbox
diff --git a/sandbox/src/interception.h b/sandbox/src/interception.h
index 261a6cf..3dd3639 100644
--- a/sandbox/src/interception.h
+++ b/sandbox/src/interception.h
@@ -228,7 +228,7 @@ class InterceptionManager {
// (WINAPI = with the "C" underscore).
#if SANDBOX_EXPORTS
#if defined(_WIN64)
-#define MAKE_SERVICE_NAME(service, params) Target ## service ## 64
+#define MAKE_SERVICE_NAME(service, params) "Target" # service "64"
#else
#define MAKE_SERVICE_NAME(service, params) "_Target" # service "@" # params
#endif
diff --git a/sandbox/src/interception_agent.cc b/sandbox/src/interception_agent.cc
index f9f9cf7..b40364f 100644
--- a/sandbox/src/interception_agent.cc
+++ b/sandbox/src/interception_agent.cc
@@ -8,6 +8,7 @@
#include "sandbox/src/interception_agent.h"
#include "sandbox/src/interception_internal.h"
+#include "sandbox/src/interceptors.h"
#include "sandbox/src/eat_resolver.h"
#include "sandbox/src/sidestep_resolver.h"
#include "sandbox/src/sandbox_nt_util.h"
@@ -27,6 +28,9 @@ namespace sandbox {
// This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt;
+// The list of intercepted functions back-pointers.
+SANDBOX_INTERCEPT OriginalFunctions g_originals;
+
// Memory buffer mapped from the parent, with the list of interceptions.
SANDBOX_INTERCEPT SharedMemory* g_interceptions = NULL;
@@ -105,7 +109,7 @@ bool InterceptionAgent::OnDllLoad(const UNICODE_STRING* full_path,
size_t buffer_bytes = offsetof(DllInterceptionData, thunks) +
dll_info->num_functions * sizeof(ThunkData);
dlls_[i] = reinterpret_cast<DllInterceptionData*>(
- new(NT_PAGE) char[buffer_bytes]);
+ new(NT_PAGE, base_address) char[buffer_bytes]);
DCHECK_NT(dlls_[i]);
if (!dlls_[i])
@@ -181,6 +185,9 @@ bool InterceptionAgent::PatchDll(const DllPatchInfo* dll_info,
return false;
}
+ DCHECK_NT(!g_originals[function->id]);
+ g_originals[function->id] = &thunks->thunks[i];
+
thunks->num_thunks++;
thunks->used_bytes += sizeof(ThunkData);
diff --git a/sandbox/src/interception_internal.h b/sandbox/src/interception_internal.h
index 2447a67..f3c401c 100644
--- a/sandbox/src/interception_internal.h
+++ b/sandbox/src/interception_internal.h
@@ -63,6 +63,9 @@ struct DllInterceptionData {
size_t used_bytes;
void* base;
int num_thunks;
+#if defined(_WIN64)
+ int dummy; // Improve alignment.
+#endif
ThunkData thunks[1];
};
diff --git a/sandbox/src/resolver_64.cc b/sandbox/src/resolver_64.cc
index c0accc7..4c736c2 100644
--- a/sandbox/src/resolver_64.cc
+++ b/sandbox/src/resolver_64.cc
@@ -94,12 +94,26 @@ bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes,
NTSTATUS ResolverThunk::ResolveInterceptor(const void* interceptor_module,
const char* interceptor_name,
const void** address) {
- return STATUS_NOT_IMPLEMENTED;
+ DCHECK_NT(address);
+ if (!interceptor_module)
+ return STATUS_INVALID_PARAMETER;
+
+ PEImage pe(interceptor_module);
+ if (!pe.VerifyMagic())
+ return STATUS_INVALID_IMAGE_FORMAT;
+
+ *address = pe.GetProcAddress(interceptor_name);
+
+ if (!(*address))
+ return STATUS_PROCEDURE_NOT_FOUND;
+
+ return STATUS_SUCCESS;
}
NTSTATUS ResolverThunk::ResolveTarget(const void* module,
const char* function_name,
void** address) {
+ // We don't support sidestep & co.
return STATUS_NOT_IMPLEMENTED;
}
diff --git a/sandbox/src/sandbox_nt_util.cc b/sandbox/src/sandbox_nt_util.cc
index f13ca87..10399fe 100644
--- a/sandbox/src/sandbox_nt_util.cc
+++ b/sandbox/src/sandbox_nt_util.cc
@@ -10,12 +10,87 @@
namespace sandbox {
-// Handle for our private heap.
-void* g_heap = NULL;
-
// This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt = { NULL };
+}
+
+namespace {
+
+#if defined(_WIN64)
+void* AllocateNearTo(void* source, size_t size) {
+ using sandbox::g_nt;
+
+ // Start with 1 GB above the source.
+ const unsigned int kOneGB = 0x40000000;
+ void* base = reinterpret_cast<char*>(source) + kOneGB;
+ SIZE_T actual_size = size;
+ ULONG_PTR zero_bits = 0; // Not the correct type if used.
+ ULONG type = MEM_RESERVE;
+
+ if (reinterpret_cast<SIZE_T>(source) > 0x7ff80000000) {
+ // We are at the top of the address space. Let's try the highest available
+ // address.
+ base = NULL;
+ type |= MEM_TOP_DOWN;
+ }
+
+ NTSTATUS ret;
+ int attempts = 0;
+ for (; attempts < 20; attempts++) {
+ ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, zero_bits,
+ &actual_size, type, PAGE_READWRITE);
+ if (NT_SUCCESS(ret)) {
+ if (base < source) {
+ // We won't be able to patch this dll.
+ VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size,
+ MEM_RELEASE));
+ return NULL;
+ }
+ break;
+ }
+
+ // Try 100 MB higher.
+ base = reinterpret_cast<char*>(base) + 100 * 0x100000;
+ };
+
+ if (attempts == 20)
+ return NULL;
+
+ ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, zero_bits,
+ &actual_size, MEM_COMMIT, PAGE_READWRITE);
+
+ if (!NT_SUCCESS(ret)) {
+ VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size,
+ MEM_RELEASE));
+ base = NULL;
+ }
+
+ return base;
+}
+#else // defined(_WIN64).
+void* AllocateNearTo(void* source, size_t size) {
+ using sandbox::g_nt;
+ UNREFERENCED_PARAMETER(source);
+ void* base = 0;
+ SIZE_T actual_size = size;
+ ULONG_PTR zero_bits = 0; // Not the correct type if used.
+ NTSTATUS ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base,
+ zero_bits, &actual_size,
+ MEM_COMMIT, PAGE_READWRITE);
+ if (!NT_SUCCESS(ret))
+ return NULL;
+ return base;
+}
+#endif // defined(_WIN64).
+
+} // namespace.
+
+namespace sandbox {
+
+// Handle for our private heap.
+void* g_heap = NULL;
+
SANDBOX_INTERCEPT HANDLE g_shared_section;
SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0;
SANDBOX_INTERCEPT size_t g_shared_policy_size = 0;
@@ -452,7 +527,8 @@ bool IsSupportedRenameCall(FILE_RENAME_INFORMATION* file_info, DWORD length,
} // namespace sandbox
-void* operator new(size_t size, sandbox::AllocationType type) {
+void* operator new(size_t size, sandbox::AllocationType type,
+ void* near_to) {
using namespace sandbox;
if (NT_ALLOC == type) {
@@ -462,15 +538,7 @@ void* operator new(size_t size, sandbox::AllocationType type) {
// Use default flags for the allocation.
return g_nt.RtlAllocateHeap(sandbox::g_heap, 0, size);
} else if (NT_PAGE == type) {
- void* base = 0;
- SIZE_T actual_size = size;
- ULONG_PTR zero_bits = 0;
- NTSTATUS ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base,
- zero_bits, &actual_size,
- MEM_COMMIT, PAGE_READWRITE);
- if (!NT_SUCCESS(ret))
- return NULL;
- return base;
+ return AllocateNearTo(near_to, size);
}
NOTREACHED_NT();
return NULL;
diff --git a/sandbox/src/sandbox_nt_util.h b/sandbox/src/sandbox_nt_util.h
index 36c22c5..d01407e 100644
--- a/sandbox/src/sandbox_nt_util.h
+++ b/sandbox/src/sandbox_nt_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -10,7 +10,8 @@
#include "sandbox/src/sandbox_nt_types.h"
// Placement new and delete to be used from ntdll interception code.
-void* __cdecl operator new(size_t size, sandbox::AllocationType type);
+void* __cdecl operator new(size_t size, sandbox::AllocationType type,
+ void* near_to = NULL);
void __cdecl operator delete(void* memory, sandbox::AllocationType type);
// Regular placement new and delete