summaryrefslogtreecommitdiffstats
path: root/sandbox/src
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-01 23:42:58 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-01 23:42:58 +0000
commitea38baf5b3a5a8dd0287d61b26502a2c9ffb4661 (patch)
treee98d94950f14f9230691b354e1da7d784d281ae0 /sandbox/src
parent0043ca1beb5d67cccfbd4290ce170e36ffeaff11 (diff)
downloadchromium_src-ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661.zip
chromium_src-ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661.tar.gz
chromium_src-ea38baf5b3a5a8dd0287d61b26502a2c9ffb4661.tar.bz2
Sandbox: Add the 64-bit service resolver and a few
extra bits of infrastructure. BUG=27218 TEST=none Review URL: http://codereview.chromium.org/558032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37764 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/src')
-rw-r--r--sandbox/src/interceptors.h27
-rw-r--r--sandbox/src/interceptors_64.cc64
-rw-r--r--sandbox/src/interceptors_64.h54
-rw-r--r--sandbox/src/resolver_64.cc106
-rw-r--r--sandbox/src/service_resolver_64.cc209
-rw-r--r--sandbox/src/service_resolver_unittest.cc15
6 files changed, 319 insertions, 156 deletions
diff --git a/sandbox/src/interceptors.h b/sandbox/src/interceptors.h
new file mode 100644
index 0000000..7064e07
--- /dev/null
+++ b/sandbox/src/interceptors.h
@@ -0,0 +1,27 @@
+// Copyright (c) 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.
+
+#ifndef SANDBOX_SRC_INTERCEPTORS_H_
+#define SANDBOX_SRC_INTERCEPTORS_H_
+
+#if defined(_WIN64)
+#include "sandbox/src/interceptors_64.h"
+#endif
+
+namespace sandbox {
+
+enum InterceptorId {
+ MAP_VIEW_OF_SECTION_ID = 0,
+ UNMAP_VIEW_OF_SECTION_ID,
+ SET_INFORMATION_THREAD_ID,
+ OPEN_THREAD_TOKEN_ID,
+ OPEN_THREAD_TOKEN_EX_ID,
+ MAX_ID
+};
+
+typedef void* OriginalFunctions[MAX_ID];
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_INTERCEPTORS_H_
diff --git a/sandbox/src/interceptors_64.cc b/sandbox/src/interceptors_64.cc
new file mode 100644
index 0000000..77c35b8
--- /dev/null
+++ b/sandbox/src/interceptors_64.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 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.
+
+#include "sandbox/src/interceptors_64.h"
+
+#include "sandbox/src/interceptors.h"
+#include "sandbox/src/policy_target.h"
+#include "sandbox/src/sandbox_nt_types.h"
+#include "sandbox/src/sandbox_types.h"
+#include "sandbox/src/target_interceptions.h"
+
+namespace sandbox {
+
+SANDBOX_INTERCEPT NtExports g_nt;
+SANDBOX_INTERCEPT OriginalFunctions g_originals;
+
+NTSTATUS WINAPI TargetNtMapViewOfSection64(
+ HANDLE section, HANDLE process, PVOID *base, ULONG_PTR zero_bits,
+ SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size,
+ SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect) {
+ NtMapViewOfSectionFunction orig_fn = reinterpret_cast<
+ NtMapViewOfSectionFunction>(g_originals[MAP_VIEW_OF_SECTION_ID]);
+
+ return TargetNtMapViewOfSection(orig_fn, section, process, base, zero_bits,
+ commit_size, offset, view_size, inherit,
+ allocation_type, protect);
+}
+
+NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, PVOID base) {
+ NtUnmapViewOfSectionFunction orig_fn = reinterpret_cast<
+ NtUnmapViewOfSectionFunction>(g_originals[UNMAP_VIEW_OF_SECTION_ID]);
+ return TargetNtUnmapViewOfSection(orig_fn, process, base);
+}
+
+NTSTATUS WINAPI TargetNtSetInformationThread64(
+ HANDLE thread, THREAD_INFORMATION_CLASS thread_info_class,
+ PVOID thread_information, ULONG thread_information_bytes) {
+ NtSetInformationThreadFunction orig_fn = reinterpret_cast<
+ NtSetInformationThreadFunction>(g_originals[SET_INFORMATION_THREAD_ID]);
+ return TargetNtSetInformationThread(orig_fn, thread, thread_info_class,
+ thread_information,
+ thread_information_bytes);
+}
+
+NTSTATUS WINAPI TargetNtOpenThreadToken64(
+ HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self,
+ PHANDLE token) {
+ NtOpenThreadTokenFunction orig_fn = reinterpret_cast<
+ NtOpenThreadTokenFunction>(g_originals[OPEN_THREAD_TOKEN_ID]);
+ return TargetNtOpenThreadToken(orig_fn, thread, desired_access, open_as_self,
+ token);
+}
+
+NTSTATUS WINAPI TargetNtOpenThreadTokenEx64(
+ HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self,
+ ULONG handle_attributes, PHANDLE token) {
+ NtOpenThreadTokenExFunction orig_fn = reinterpret_cast<
+ NtOpenThreadTokenExFunction>(g_originals[OPEN_THREAD_TOKEN_EX_ID]);
+ return TargetNtOpenThreadTokenEx(orig_fn, thread, desired_access,
+ open_as_self, handle_attributes, token);
+}
+
+} // namespace sandbox
diff --git a/sandbox/src/interceptors_64.h b/sandbox/src/interceptors_64.h
new file mode 100644
index 0000000..8be5af4
--- /dev/null
+++ b/sandbox/src/interceptors_64.h
@@ -0,0 +1,54 @@
+// Copyright (c) 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.
+
+#include "sandbox/src/nt_internals.h"
+#include "sandbox/src/sandbox_types.h"
+
+#ifndef SANDBOX_SRC_INTERCEPTORS_64_H_
+#define SANDBOX_SRC_INTERCEPTORS_64_H_
+
+namespace sandbox {
+
+extern "C" {
+
+// Interception of NtMapViewOfSection on the child process.
+// It should never be called directly. This function provides the means to
+// detect dlls being loaded, so we can patch them if needed.
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtMapViewOfSection64(
+ HANDLE section, HANDLE process, PVOID *base, ULONG_PTR zero_bits,
+ SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size,
+ SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect);
+
+// Interception of NtUnmapViewOfSection on the child process.
+// It should never be called directly. This function provides the means to
+// detect dlls being unloaded, so we can clean up our interceptions.
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process,
+ PVOID base);
+
+// -----------------------------------------------------------------------
+// Interceptors without IPC.
+
+// Interception of NtSetInformationThread on the child process.
+// It should never be called directly.
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationThread64(
+ HANDLE thread, THREAD_INFORMATION_CLASS thread_info_class,
+ PVOID thread_information, ULONG thread_information_bytes);
+
+// Interception of NtOpenThreadToken on the child process.
+// It should never be called directly
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadToken64(
+ HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self,
+ PHANDLE token);
+
+// Interception of NtOpenThreadTokenEx on the child process.
+// It should never be called directly
+SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadTokenEx64(
+ HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self,
+ ULONG handle_attributes, PHANDLE token);
+
+} // extern "C"
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_INTERCEPTORS_64_H_
diff --git a/sandbox/src/resolver_64.cc b/sandbox/src/resolver_64.cc
new file mode 100644
index 0000000..c0accc7
--- /dev/null
+++ b/sandbox/src/resolver_64.cc
@@ -0,0 +1,106 @@
+// 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.
+
+#include "sandbox/src/resolver.h"
+
+#include "base/pe_image.h"
+#include "sandbox/src/sandbox_nt_util.h"
+
+namespace {
+
+const BYTE kPushRax = 0x50;
+const USHORT kMovRax = 0xB848;
+const ULONG kMovRspRax = 0x24048948;
+const BYTE kRetNp = 0xC3;
+
+#pragma pack(push, 1)
+struct InternalThunk {
+ // This struct contains roughly the following code:
+ // 00 50 push rax
+ // 01 48b8f0debc9a78563412 mov rax,123456789ABCDEF0h
+ // 0b 48890424 mov qword ptr [rsp],rax
+ // 0f c3 ret
+ //
+ // The code modifies rax, but that should not be an issue for the common
+ // calling conventions.
+
+ InternalThunk() {
+ push_rax = kPushRax;
+ mov_rax = kMovRax;
+ interceptor_function = 0;
+ mov_rsp_rax = kMovRspRax;
+ ret = kRetNp;
+ };
+ BYTE push_rax; // = 50
+ USHORT mov_rax; // = 48 B8
+ ULONG_PTR interceptor_function;
+ ULONG mov_rsp_rax; // = 48 89 04 24
+ BYTE ret; // = C3
+};
+#pragma pack(pop)
+
+} // namespace.
+
+namespace sandbox {
+
+NTSTATUS ResolverThunk::Init(const void* target_module,
+ const void* interceptor_module,
+ const char* target_name,
+ const char* interceptor_name,
+ const void* interceptor_entry_point,
+ void* thunk_storage,
+ size_t storage_bytes) {
+ if (NULL == thunk_storage || 0 == storage_bytes ||
+ NULL == target_module || NULL == target_name)
+ return STATUS_INVALID_PARAMETER;
+
+ if (storage_bytes < GetThunkSize())
+ return STATUS_BUFFER_TOO_SMALL;
+
+ NTSTATUS ret = STATUS_SUCCESS;
+ if (NULL == interceptor_entry_point) {
+ ret = ResolveInterceptor(interceptor_module, interceptor_name,
+ &interceptor_entry_point);
+ if (!NT_SUCCESS(ret))
+ return ret;
+ }
+
+ ret = ResolveTarget(target_module, target_name, &target_);
+ if (!NT_SUCCESS(ret))
+ return ret;
+
+ interceptor_ = interceptor_entry_point;
+
+ return ret;
+}
+
+size_t ResolverThunk::GetInternalThunkSize() const {
+ return sizeof(InternalThunk);
+}
+
+bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes,
+ const void* original_function,
+ const void* interceptor) {
+ if (storage_bytes < sizeof(InternalThunk))
+ return false;
+
+ InternalThunk* thunk = new(storage, NT_PLACE) InternalThunk;
+ thunk->interceptor_function = reinterpret_cast<ULONG_PTR>(interceptor);
+
+ return true;
+}
+
+NTSTATUS ResolverThunk::ResolveInterceptor(const void* interceptor_module,
+ const char* interceptor_name,
+ const void** address) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS ResolverThunk::ResolveTarget(const void* module,
+ const char* function_name,
+ void** address) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+} // namespace sandbox
diff --git a/sandbox/src/service_resolver_64.cc b/sandbox/src/service_resolver_64.cc
index 3a46d73..3045840 100644
--- a/sandbox/src/service_resolver_64.cc
+++ b/sandbox/src/service_resolver_64.cc
@@ -2,50 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "sandbox/wow_helper/service64_resolver.h"
+#include "sandbox/src/service_resolver.h"
+#include "base/logging.h"
+#include "base/pe_image.h"
#include "base/scoped_ptr.h"
-#include "sandbox/wow_helper/target_code.h"
namespace {
#pragma pack(push, 1)
-const BYTE kMovEax = 0xB8;
-const BYTE kMovEdx = 0xBA;
-const USHORT kCallPtrEdx = 0x12FF;
-const BYTE kRet = 0xC2;
-const BYTE kNop = 0x90;
-const USHORT kJmpEdx = 0xE2FF;
-const USHORT kXorEcx = 0xC933;
-const ULONG kLeaEdx = 0x0424548D;
-const ULONG kCallFs1 = 0xC015FF64;
-const ULONG kCallFs2Ret = 0xC2000000;
-const BYTE kPopEdx = 0x5A;
-const BYTE kPushEdx = 0x52;
-const BYTE kPush32 = 0x68;
-
const ULONG kMmovR10EcxMovEax = 0xB8D18B4C;
const USHORT kSyscall = 0x050F;
const BYTE kRetNp = 0xC3;
-const BYTE kPad = 0x66;
-const USHORT kNop16 = 0x9066;
-const BYTE kRelJmp = 0xE9;
-
-const ULONG kXorRaxMovEax = 0xB8C03148;
-const ULONG kSaveRcx = 0x10488948;
-const ULONG kMovRcxRaxJmp = 0xE9C88B48;
// Service code for 64 bit systems.
struct ServiceEntry {
- // this struct contains roughly the following code:
- // mov r10,rcx
- // mov eax,52h
- // syscall
- // ret
- // xchg ax,ax
- // xchg ax,ax
-
- ULONG mov_r10_ecx_mov_eax; // = 4C 8B D1 B8
+ // This struct contains roughly the following code:
+ // 00 mov r10,rcx
+ // 03 mov eax,52h
+ // 08 syscall
+ // 0a ret
+ // 0b xchg ax,ax
+ // 0e xchg ax,ax
+
+ ULONG mov_r10_rcx_mov_eax; // = 4C 8B D1 B8
ULONG service_id;
USHORT syscall; // = 0F 05
BYTE ret; // = C3
@@ -54,49 +34,9 @@ struct ServiceEntry {
USHORT xchg_ax_ax2; // = 66 90
};
-struct Redirected {
- // this struct contains roughly the following code:
- // jmp relative_32
- // xchg ax,ax // 3 byte nop
-
- Redirected() {
- jmp = kRelJmp;
- relative = 0;
- pad = kPad;
- xchg_ax_ax = kNop16;
- };
- BYTE jmp; // = E9
- ULONG relative;
- BYTE pad; // = 66
- USHORT xchg_ax_ax; // = 66 90
-};
-
-struct InternalThunk {
- // this struct contains roughly the following code:
- // xor rax,rax
- // mov eax, 0x00080000 // Thunk storage.
- // mov [rax]PatchInfo.service, rcx // Save first argument.
- // mov rcx, rax
- // jmp relative_to_interceptor
-
- InternalThunk() {
- xor_rax_mov_eax = kXorRaxMovEax;
- patch_info = 0;
- save_rcx = kSaveRcx;
- mov_rcx_rax_jmp = kMovRcxRaxJmp;
- relative = 0;
- };
- ULONG xor_rax_mov_eax; // = 48 31 C0 B8
- ULONG patch_info;
- ULONG save_rcx; // = 48 89 48 10
- ULONG mov_rcx_rax_jmp; // = 48 8b c8 e9
- ULONG relative;
-};
-
+// We don't have an internal thunk for x64.
struct ServiceFullThunk {
- sandbox::PatchInfo patch_info;
ServiceEntry original;
- InternalThunk internal_thunk;
};
#pragma pack(pop)
@@ -131,35 +71,18 @@ bool WriteProtectedChildMemory(HANDLE child_process,
return ok;
}
-// Get pointers to the functions that we need from ntdll.dll.
-NTSTATUS ResolveNtdll(sandbox::PatchInfo* patch_info) {
- wchar_t* ntdll_name = L"ntdll.dll";
- HMODULE ntdll = ::GetModuleHandle(ntdll_name);
- if (!ntdll)
- return STATUS_PROCEDURE_NOT_FOUND;
-
- void* signal = ::GetProcAddress(ntdll, "NtSignalAndWaitForSingleObject");
- if (!signal)
- return STATUS_PROCEDURE_NOT_FOUND;
-
- patch_info->signal_and_wait =
- reinterpret_cast<NtSignalAndWaitForSingleObjectFunction>(signal);
-
- return STATUS_SUCCESS;
-}
-
}; // namespace
namespace sandbox {
-NTSTATUS Service64ResolverThunk::Setup(const void* target_module,
- const void* interceptor_module,
- const char* target_name,
- const char* interceptor_name,
- const void* interceptor_entry_point,
- void* thunk_storage,
- size_t storage_bytes,
- size_t* storage_used) {
+NTSTATUS ServiceResolverThunk::Setup(const void* target_module,
+ const void* interceptor_module,
+ const char* target_name,
+ const char* interceptor_name,
+ const void* interceptor_entry_point,
+ void* thunk_storage,
+ size_t storage_bytes,
+ size_t* storage_used) {
NTSTATUS ret = Init(target_module, interceptor_module, target_name,
interceptor_name, interceptor_entry_point,
thunk_storage, storage_bytes);
@@ -182,7 +105,7 @@ NTSTATUS Service64ResolverThunk::Setup(const void* target_module,
return ret;
}
-NTSTATUS Service64ResolverThunk::ResolveInterceptor(
+NTSTATUS ServiceResolverThunk::ResolveInterceptor(
const void* interceptor_module,
const char* interceptor_name,
const void** address) {
@@ -194,13 +117,15 @@ NTSTATUS Service64ResolverThunk::ResolveInterceptor(
// In this case all the work is done from the parent, so resolve is
// just a simple GetProcAddress.
-NTSTATUS Service64ResolverThunk::ResolveTarget(const void* module,
+NTSTATUS ServiceResolverThunk::ResolveTarget(const void* module,
const char* function_name,
void** address) {
+ DCHECK(address);
if (NULL == module)
return STATUS_UNSUCCESSFUL;
- *address = ::GetProcAddress(bit_cast<HMODULE>(module), function_name);
+ PEImage module_image(module);
+ *address = module_image.GetProcAddress(function_name);
if (NULL == *address)
return STATUS_UNSUCCESSFUL;
@@ -208,11 +133,11 @@ NTSTATUS Service64ResolverThunk::ResolveTarget(const void* module,
return STATUS_SUCCESS;
}
-size_t Service64ResolverThunk::GetThunkSize() const {
+size_t ServiceResolverThunk::GetThunkSize() const {
return sizeof(ServiceFullThunk);
}
-bool Service64ResolverThunk::IsFunctionAService(void* local_thunk) const {
+bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const {
ServiceEntry function_code;
SIZE_T read;
if (!::ReadProcessMemory(process_, target_, &function_code,
@@ -222,65 +147,32 @@ bool Service64ResolverThunk::IsFunctionAService(void* local_thunk) const {
if (sizeof(function_code) != read)
return false;
- if (kMmovR10EcxMovEax != function_code.mov_r10_ecx_mov_eax ||
+ if (kMmovR10EcxMovEax != function_code.mov_r10_rcx_mov_eax ||
kSyscall != function_code.syscall || kRetNp != function_code.ret)
return false;
- // Save the verified code
+ // Save the verified code.
memcpy(local_thunk, &function_code, sizeof(function_code));
return true;
}
-NTSTATUS Service64ResolverThunk::PerformPatch(void* local_thunk,
- void* remote_thunk) {
+NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk,
+ void* remote_thunk) {
ServiceFullThunk* full_local_thunk = reinterpret_cast<ServiceFullThunk*>(
local_thunk);
ServiceFullThunk* full_remote_thunk = reinterpret_cast<ServiceFullThunk*>(
- remote_thunk);
-
- // If the source or target are above 4GB we cannot do this relative jump.
- if (reinterpret_cast<ULONG_PTR>(full_remote_thunk) >
- static_cast<ULONG_PTR>(ULONG_MAX))
- return STATUS_CONFLICTING_ADDRESSES;
-
- if (reinterpret_cast<ULONG_PTR>(target_) > static_cast<ULONG_PTR>(ULONG_MAX))
- return STATUS_CONFLICTING_ADDRESSES;
+ remote_thunk);
// Patch the original code.
- Redirected local_service;
- Redirected* remote_service = reinterpret_cast<Redirected*>(target_);
- ULONG_PTR diff = reinterpret_cast<BYTE*>(&full_remote_thunk->internal_thunk) -
- &remote_service->pad;
- local_service.relative = static_cast<ULONG>(diff);
-
- // Setup the PatchInfo structure.
- SIZE_T actual;
- if (!::ReadProcessMemory(process_, remote_thunk, local_thunk,
- sizeof(PatchInfo), &actual))
+ ServiceEntry local_service;
+ DCHECK_GE(GetInternalThunkSize(), sizeof(local_service));
+ if (!SetInternalThunk(&local_service, sizeof(local_service), NULL,
+ interceptor_))
return STATUS_UNSUCCESSFUL;
- if (sizeof(PatchInfo) != actual)
- return STATUS_UNSUCCESSFUL;
-
- full_local_thunk->patch_info.orig_MapViewOfSection = reinterpret_cast<
- NtMapViewOfSectionFunction>(&full_remote_thunk->original);
- full_local_thunk->patch_info.patch_location = target_;
- NTSTATUS ret = ResolveNtdll(&full_local_thunk->patch_info);
- if (!NT_SUCCESS(ret))
- return ret;
-
- // Setup the thunk. The jump out is performed from right after the end of the
- // thunk (full_remote_thunk + 1).
- InternalThunk my_thunk;
- ULONG_PTR patch_info = reinterpret_cast<ULONG_PTR>(remote_thunk);
- my_thunk.patch_info = static_cast<ULONG>(patch_info);
- diff = reinterpret_cast<const BYTE*>(interceptor_) -
- reinterpret_cast<BYTE*>(full_remote_thunk + 1);
- my_thunk.relative = static_cast<ULONG>(diff);
- memcpy(&full_local_thunk->internal_thunk, &my_thunk, sizeof(my_thunk));
-
- // copy the local thunk buffer to the child
+ // Copy the local thunk buffer to the child.
+ SIZE_T actual;
if (!::WriteProcessMemory(process_, remote_thunk, local_thunk,
sizeof(ServiceFullThunk), &actual))
return STATUS_UNSUCCESSFUL;
@@ -288,12 +180,29 @@ NTSTATUS Service64ResolverThunk::PerformPatch(void* local_thunk,
if (sizeof(ServiceFullThunk) != actual)
return STATUS_UNSUCCESSFUL;
- // and now change the function to intercept, on the child
- if (!::WriteProtectedChildMemory(process_, target_, &local_service,
+ // And now change the function to intercept, on the child.
+ if (NULL != ntdll_base_) {
+ // Running a unit test.
+ if (!::WriteProcessMemory(process_, target_, &local_service,
+ sizeof(local_service), &actual))
+ return STATUS_UNSUCCESSFUL;
+ } else {
+ if (!WriteProtectedChildMemory(process_, target_, &local_service,
sizeof(local_service)))
- return STATUS_UNSUCCESSFUL;
+ return STATUS_UNSUCCESSFUL;
+ }
return STATUS_SUCCESS;
}
+bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const {
+ NOTREACHED();
+ return false;
+}
+
+bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const {
+ NOTREACHED();
+ return false;
+}
+
} // namespace sandbox
diff --git a/sandbox/src/service_resolver_unittest.cc b/sandbox/src/service_resolver_unittest.cc
index 3af81f2..ee26c9e 100644
--- a/sandbox/src/service_resolver_unittest.cc
+++ b/sandbox/src/service_resolver_unittest.cc
@@ -36,7 +36,7 @@ class ResolverThunkTest : public T {
const char* interceptor_name,
const void* interceptor_entry_point,
void* thunk_storage,
- uint32 storage_bytes) {
+ size_t storage_bytes) {
NTSTATUS ret = STATUS_SUCCESS;
ret = ResolverThunk::Init(target_module, interceptor_module, target_name,
interceptor_name, interceptor_entry_point,
@@ -86,7 +86,7 @@ NTSTATUS PatchNtdll(const char* function, bool relaxed) {
void* function_entry = resolver;
size_t thunk_size = resolver->GetThunkSize();
scoped_array<char> thunk(new char[thunk_size]);
- uint32 used;
+ size_t used;
NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL,
function_entry, thunk.get(), thunk_size,
@@ -125,14 +125,16 @@ TEST(ServiceResolverTest, PatchesServices) {
}
TEST(ServiceResolverTest, FailsIfNotService) {
- NTSTATUS ret = PatchNtdll("RtlUlongByteSwap", false);
- EXPECT_NE(STATUS_SUCCESS, ret);
+#if !defined(_WIN64)
+ EXPECT_NE(STATUS_SUCCESS, PatchNtdll("RtlUlongByteSwap", false));
+#endif
- ret = PatchNtdll("LdrLoadDll", false);
- EXPECT_NE(STATUS_SUCCESS, ret);
+ EXPECT_NE(STATUS_SUCCESS, PatchNtdll("LdrLoadDll", false));
}
TEST(ServiceResolverTest, PatchesPatchedServices) {
+// We don't support "relaxed mode" for Win64 apps.
+#if !defined(_WIN64)
NTSTATUS ret = PatchNtdll("NtClose", true);
EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
@@ -147,6 +149,7 @@ TEST(ServiceResolverTest, PatchesPatchedServices) {
ret = PatchNtdll("NtMapViewOfSection", true);
EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
::GetLastError();
+#endif
}
} // namespace