diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-10 22:37:16 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-10 22:37:16 +0000 |
commit | 9420c240cd8428c63530675e25e97702a007a848 (patch) | |
tree | 2915461707676a6074a8f384acfa8f1082ab7458 | |
parent | e603d9502bf6f6a5f0887bc0e0feeb8925d0296e (diff) | |
download | chromium_src-9420c240cd8428c63530675e25e97702a007a848.zip chromium_src-9420c240cd8428c63530675e25e97702a007a848.tar.gz chromium_src-9420c240cd8428c63530675e25e97702a007a848.tar.bz2 |
Sandbox: Add support for EAT interceptions in 64 bit.
BUG=27218
TEST=manual integration tests.
Review URL: http://codereview.chromium.org/600035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38681 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | sandbox/src/eat_resolver.cc | 19 | ||||
-rw-r--r-- | sandbox/src/interception.h | 2 | ||||
-rw-r--r-- | sandbox/src/interception_agent.cc | 9 | ||||
-rw-r--r-- | sandbox/src/interception_internal.h | 3 | ||||
-rw-r--r-- | sandbox/src/resolver_64.cc | 16 | ||||
-rw-r--r-- | sandbox/src/sandbox_nt_util.cc | 94 | ||||
-rw-r--r-- | sandbox/src/sandbox_nt_util.h | 5 |
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 |