Added GetState, GetManagedProperties, CreateNetwork methods to WiFiService.
[chromium-blink-merge.git] / sandbox / win / src / service_resolver_unittest.cc
blobb01fedfbf09cfb73f292ee7d2e9bdeae6724d25a
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file contains unit tests for ServiceResolverThunk.
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/win/windows_version.h"
10 #include "sandbox/win/src/resolver.h"
11 #include "sandbox/win/src/sandbox_utils.h"
12 #include "sandbox/win/src/service_resolver.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace {
17 // This is the concrete resolver used to perform service-call type functions
18 // inside ntdll.dll.
19 template<typename T>
20 class ResolverThunkTest : public T {
21 public:
22 // The service resolver needs a child process to write to.
23 explicit ResolverThunkTest(bool relaxed)
24 : T(::GetCurrentProcess(), relaxed) {}
26 // Sets the interception target to the desired address.
27 void set_target(void* target) {
28 fake_target_ = target;
31 protected:
32 // Overrides Resolver::Init
33 virtual NTSTATUS Init(const void* target_module,
34 const void* interceptor_module,
35 const char* target_name,
36 const char* interceptor_name,
37 const void* interceptor_entry_point,
38 void* thunk_storage,
39 size_t storage_bytes) {
40 NTSTATUS ret = STATUS_SUCCESS;
41 ret = ResolverThunk::Init(target_module, interceptor_module, target_name,
42 interceptor_name, interceptor_entry_point,
43 thunk_storage, storage_bytes);
44 EXPECT_EQ(STATUS_SUCCESS, ret);
46 target_ = fake_target_;
48 return ret;
51 private:
52 // Holds the address of the fake target.
53 void* fake_target_;
55 DISALLOW_COPY_AND_ASSIGN(ResolverThunkTest);
58 typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest;
60 #if !defined(_WIN64)
61 typedef ResolverThunkTest<sandbox::Win2kResolverThunk> Win2kResolverTest;
62 typedef ResolverThunkTest<sandbox::Win8ResolverThunk> Win8ResolverTest;
63 typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest;
64 typedef ResolverThunkTest<sandbox::Wow64W8ResolverThunk> Wow64W8ResolverTest;
65 #endif
67 const BYTE kJump32 = 0xE9;
69 void CheckJump(void* source, void* target) {
70 #pragma pack(push)
71 #pragma pack(1)
72 struct Code {
73 BYTE jump;
74 ULONG delta;
76 #pragma pack(pop)
78 #if defined(_WIN64)
79 FAIL() << "Running 32-bit codepath";
80 #else
81 Code* patched = reinterpret_cast<Code*>(source);
82 EXPECT_EQ(kJump32, patched->jump);
84 ULONG source_addr = bit_cast<ULONG>(source);
85 ULONG target_addr = bit_cast<ULONG>(target);
86 EXPECT_EQ(target_addr + 19 - source_addr, patched->delta);
87 #endif
90 NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
91 sandbox::ServiceResolverThunk* resolver) {
92 HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
93 EXPECT_TRUE(NULL != ntdll_base);
95 void* target = ::GetProcAddress(ntdll_base, function);
96 EXPECT_TRUE(NULL != target);
97 if (NULL == target)
98 return STATUS_UNSUCCESSFUL;
100 BYTE service[50];
101 memcpy(service, target, sizeof(service));
103 static_cast<WinXpResolverTest*>(resolver)->set_target(service);
105 // Any pointer will do as an interception_entry_point
106 void* function_entry = resolver;
107 size_t thunk_size = resolver->GetThunkSize();
108 scoped_ptr<char[]> thunk(new char[thunk_size]);
109 size_t used;
111 resolver->AllowLocalPatches();
113 NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL,
114 function_entry, thunk.get(), thunk_size,
115 &used);
116 if (NT_SUCCESS(ret)) {
117 EXPECT_EQ(thunk_size, used);
118 EXPECT_NE(0, memcmp(service, target, sizeof(service)));
119 EXPECT_NE(kJump32, service[0]);
121 if (relaxed) {
122 // It's already patched, let's patch again, and simulate a direct patch.
123 service[0] = kJump32;
124 ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry,
125 thunk.get(), thunk_size, &used);
126 CheckJump(service, thunk.get());
130 return ret;
133 sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) {
134 #if defined(_WIN64)
135 return new WinXpResolverTest(relaxed);
136 #else
137 base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
138 if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) {
139 if (os_info->version() >= base::win::VERSION_WIN8)
140 return new Wow64W8ResolverTest(relaxed);
141 return new Wow64ResolverTest(relaxed);
144 if (!sandbox::IsXPSP2OrLater())
145 return new Win2kResolverTest(relaxed);
147 if (os_info->version() >= base::win::VERSION_WIN8)
148 return new Win8ResolverTest(relaxed);
150 return new WinXpResolverTest(relaxed);
151 #endif
154 NTSTATUS PatchNtdll(const char* function, bool relaxed) {
155 sandbox::ServiceResolverThunk* resolver = GetTestResolver(relaxed);
157 NTSTATUS ret = PatchNtdllWithResolver(function, relaxed, resolver);
158 delete resolver;
159 return ret;
162 TEST(ServiceResolverTest, PatchesServices) {
163 NTSTATUS ret = PatchNtdll("NtClose", false);
164 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
166 ret = PatchNtdll("NtCreateFile", false);
167 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
168 ::GetLastError();
170 ret = PatchNtdll("NtCreateMutant", false);
171 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
172 ::GetLastError();
174 ret = PatchNtdll("NtMapViewOfSection", false);
175 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
176 ::GetLastError();
179 TEST(ServiceResolverTest, FailsIfNotService) {
180 #if !defined(_WIN64)
181 EXPECT_NE(STATUS_SUCCESS, PatchNtdll("RtlUlongByteSwap", false));
182 #endif
184 EXPECT_NE(STATUS_SUCCESS, PatchNtdll("LdrLoadDll", false));
187 TEST(ServiceResolverTest, PatchesPatchedServices) {
188 // We don't support "relaxed mode" for Win64 apps.
189 #if !defined(_WIN64)
190 NTSTATUS ret = PatchNtdll("NtClose", true);
191 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
193 ret = PatchNtdll("NtCreateFile", true);
194 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
195 ::GetLastError();
197 ret = PatchNtdll("NtCreateMutant", true);
198 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
199 ::GetLastError();
201 ret = PatchNtdll("NtMapViewOfSection", true);
202 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
203 ::GetLastError();
204 #endif
207 TEST(ServiceResolverTest, MultiplePatchedServices) {
208 // We don't support "relaxed mode" for Win64 apps.
209 #if !defined(_WIN64)
210 sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
211 NTSTATUS ret = PatchNtdllWithResolver("NtClose", true, resolver);
212 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
214 ret = PatchNtdllWithResolver("NtCreateFile", true, resolver);
215 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
216 ::GetLastError();
218 ret = PatchNtdllWithResolver("NtCreateMutant", true, resolver);
219 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
220 ::GetLastError();
222 ret = PatchNtdllWithResolver("NtMapViewOfSection", true, resolver);
223 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
224 ::GetLastError();
225 delete resolver;
226 #endif
229 TEST(ServiceResolverTest, LocalPatchesAllowed) {
230 sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
232 HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
233 ASSERT_TRUE(NULL != ntdll_base);
235 const char kFunctionName[] = "NtClose";
237 void* target = ::GetProcAddress(ntdll_base, kFunctionName);
238 ASSERT_TRUE(NULL != target);
240 BYTE service[50];
241 memcpy(service, target, sizeof(service));
242 static_cast<WinXpResolverTest*>(resolver)->set_target(service);
244 // Any pointer will do as an interception_entry_point
245 void* function_entry = resolver;
246 size_t thunk_size = resolver->GetThunkSize();
247 scoped_ptr<char[]> thunk(new char[thunk_size]);
248 size_t used;
250 NTSTATUS ret = STATUS_UNSUCCESSFUL;
252 // First try patching without having allowed local patches.
253 ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL,
254 function_entry, thunk.get(), thunk_size,
255 &used);
256 EXPECT_FALSE(NT_SUCCESS(ret));
258 // Now allow local patches and check that things work.
259 resolver->AllowLocalPatches();
260 ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL,
261 function_entry, thunk.get(), thunk_size,
262 &used);
263 EXPECT_EQ(STATUS_SUCCESS, ret);
266 } // namespace