summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-25 20:00:06 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-25 20:00:06 +0000
commit2b98e225b48f97766d42e630bf78bd489ecc9f5c (patch)
tree4b287d59d2ac8876b260f6aad621d96468057b40 /sandbox
parent574fde8a446ef302afaf92e9ab1586855c657777 (diff)
downloadchromium_src-2b98e225b48f97766d42e630bf78bd489ecc9f5c.zip
chromium_src-2b98e225b48f97766d42e630bf78bd489ecc9f5c.tar.gz
chromium_src-2b98e225b48f97766d42e630bf78bd489ecc9f5c.tar.bz2
Sandbox: Make sure that we reset relative_jump_ before
performing every patch. BUG=69952 TEST=sbox_unittests Review URL: http://codereview.chromium.org/6528033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/src/resolver.h2
-rw-r--r--sandbox/src/service_resolver_32.cc1
-rw-r--r--sandbox/src/service_resolver_unittest.cc83
3 files changed, 73 insertions, 13 deletions
diff --git a/sandbox/src/resolver.h b/sandbox/src/resolver.h
index 0ee3e9a..7ec0bf5 100644
--- a/sandbox/src/resolver.h
+++ b/sandbox/src/resolver.h
@@ -41,6 +41,8 @@ class ResolverThunk {
//
// In general, the idea is to allocate a single big buffer for all
// interceptions on the same dll, and call Setup n times.
+ // WARNING: This means that any data member that is specific to a single
+ // interception must be reset within this method.
virtual NTSTATUS Setup(const void* target_module,
const void* interceptor_module,
const char* target_name,
diff --git a/sandbox/src/service_resolver_32.cc b/sandbox/src/service_resolver_32.cc
index 01c2f0b..c731607 100644
--- a/sandbox/src/service_resolver_32.cc
+++ b/sandbox/src/service_resolver_32.cc
@@ -113,6 +113,7 @@ NTSTATUS ServiceResolverThunk::Setup(const void* target_module,
if (!NT_SUCCESS(ret))
return ret;
+ relative_jump_ = 0;
size_t thunk_bytes = GetThunkSize();
scoped_array<char> thunk_buffer(new char[thunk_bytes]);
ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(
diff --git a/sandbox/src/service_resolver_unittest.cc b/sandbox/src/service_resolver_unittest.cc
index 1756017..793d4a1 100644
--- a/sandbox/src/service_resolver_unittest.cc
+++ b/sandbox/src/service_resolver_unittest.cc
@@ -59,7 +59,27 @@ typedef ResolverThunkTest<sandbox::Win2kResolverThunk> Win2kResolverTest;
typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest;
typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest;
-NTSTATUS PatchNtdll(const char* function, bool relaxed) {
+const BYTE kJump32 = 0xE9;
+
+void CheckJump(void* source, void* target) {
+#pragma pack(push)
+#pragma pack(1)
+ struct Code {
+ BYTE jump;
+ ULONG delta;
+ };
+#pragma pack(pop)
+
+ Code* patched = reinterpret_cast<Code*>(source);
+ EXPECT_EQ(kJump32, patched->jump);
+
+ ULONG source_addr = bit_cast<ULONG>(source);
+ ULONG target_addr = bit_cast<ULONG>(target);
+ EXPECT_EQ(target_addr + 19 - source_addr, patched->delta);
+}
+
+NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
+ sandbox::ServiceResolverThunk* resolver) {
HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
EXPECT_TRUE(NULL != ntdll_base);
@@ -68,17 +88,8 @@ NTSTATUS PatchNtdll(const char* function, bool relaxed) {
if (NULL == target)
return STATUS_UNSUCCESSFUL;
- char service[50];
+ BYTE service[50];
memcpy(service, target, sizeof(service));
- sandbox::Wow64 WowHelper(NULL, ntdll_base);
-
- sandbox::ServiceResolverThunk* resolver;
- if (WowHelper.IsWow64())
- resolver = new Wow64ResolverTest(relaxed);
- else if (!sandbox::IsXPSP2OrLater())
- resolver = new Win2kResolverTest(relaxed);
- else
- resolver = new WinXpResolverTest(relaxed);
static_cast<WinXpResolverTest*>(resolver)->set_target(service);
@@ -94,16 +105,40 @@ NTSTATUS PatchNtdll(const char* function, bool relaxed) {
if (NT_SUCCESS(ret)) {
EXPECT_EQ(thunk_size, used);
EXPECT_NE(0, memcmp(service, target, sizeof(service)));
+ EXPECT_NE(kJump32, service[0]);
if (relaxed) {
- // It's already patched, let's patch again.
+ // It's already patched, let's patch again, and simulate a direct patch.
+ service[0] = kJump32;
ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry,
thunk.get(), thunk_size, &used);
+ CheckJump(service, thunk.get());
}
}
- delete resolver;
+ return ret;
+}
+
+sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) {
+ HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
+ EXPECT_TRUE(NULL != ntdll_base);
+ sandbox::Wow64 WowHelper(NULL, ntdll_base);
+
+ sandbox::ServiceResolverThunk* resolver;
+ if (WowHelper.IsWow64())
+ resolver = new Wow64ResolverTest(relaxed);
+ else if (!sandbox::IsXPSP2OrLater())
+ resolver = new Win2kResolverTest(relaxed);
+ else
+ resolver = new WinXpResolverTest(relaxed);
+ return resolver;
+}
+NTSTATUS PatchNtdll(const char* function, bool relaxed) {
+ sandbox::ServiceResolverThunk* resolver = GetTestResolver(relaxed);
+
+ NTSTATUS ret = PatchNtdllWithResolver(function, relaxed, resolver);
+ delete resolver;
return ret;
}
@@ -152,4 +187,26 @@ TEST(ServiceResolverTest, PatchesPatchedServices) {
#endif
}
+TEST(ServiceResolverTest, MultiplePatchedServices) {
+// We don't support "relaxed mode" for Win64 apps.
+#if !defined(_WIN64)
+ sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
+ NTSTATUS ret = PatchNtdllWithResolver("NtClose", true, resolver);
+ EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
+
+ ret = PatchNtdllWithResolver("NtCreateFile", true, resolver);
+ EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
+ ::GetLastError();
+
+ ret = PatchNtdllWithResolver("NtCreateMutant", true, resolver);
+ EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
+ ::GetLastError();
+
+ ret = PatchNtdllWithResolver("NtMapViewOfSection", true, resolver);
+ EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
+ ::GetLastError();
+ delete resolver;
+#endif
+}
+
} // namespace