Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(904)

Side by Side Diff: sandbox/win/src/service_resolver_unittest.cc

Issue 1851213002: Remove sandbox on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nacl compile issues Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/win/src/service_resolver_64.cc ('k') | sandbox/win/src/sharedmem_ipc_client.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 // This file contains unit tests for ServiceResolverThunk.
6
7 #include <stddef.h>
8
9 #include "base/bit_cast.h"
10 #include "base/macros.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/win/windows_version.h"
13 #include "sandbox/win/src/resolver.h"
14 #include "sandbox/win/src/sandbox_utils.h"
15 #include "sandbox/win/src/service_resolver.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace {
19
20 // This is the concrete resolver used to perform service-call type functions
21 // inside ntdll.dll.
22 template<typename T>
23 class ResolverThunkTest : public T {
24 public:
25 // The service resolver needs a child process to write to.
26 explicit ResolverThunkTest(bool relaxed)
27 : T(::GetCurrentProcess(), relaxed) {}
28
29 // Sets the interception target to the desired address.
30 void set_target(void* target) {
31 fake_target_ = target;
32 }
33
34 protected:
35 // Overrides Resolver::Init
36 virtual NTSTATUS Init(const void* target_module,
37 const void* interceptor_module,
38 const char* target_name,
39 const char* interceptor_name,
40 const void* interceptor_entry_point,
41 void* thunk_storage,
42 size_t storage_bytes) {
43 NTSTATUS ret = STATUS_SUCCESS;
44 ret = T::Init(target_module, interceptor_module, target_name,
45 interceptor_name, interceptor_entry_point, thunk_storage,
46 storage_bytes);
47 EXPECT_EQ(STATUS_SUCCESS, ret);
48
49 this->target_ = fake_target_;
50
51 return ret;
52 };
53
54 private:
55 // Holds the address of the fake target.
56 void* fake_target_;
57
58 DISALLOW_COPY_AND_ASSIGN(ResolverThunkTest);
59 };
60
61 typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest;
62
63 #if !defined(_WIN64)
64 typedef ResolverThunkTest<sandbox::Win8ResolverThunk> Win8ResolverTest;
65 typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest;
66 typedef ResolverThunkTest<sandbox::Wow64W8ResolverThunk> Wow64W8ResolverTest;
67 typedef ResolverThunkTest<sandbox::Wow64W10ResolverThunk> Wow64W10ResolverTest;
68 #endif
69
70 const BYTE kJump32 = 0xE9;
71
72 void CheckJump(void* source, void* target) {
73 #pragma pack(push)
74 #pragma pack(1)
75 struct Code {
76 BYTE jump;
77 ULONG delta;
78 };
79 #pragma pack(pop)
80
81 #if defined(_WIN64)
82 FAIL() << "Running 32-bit codepath";
83 #else
84 Code* patched = reinterpret_cast<Code*>(source);
85 EXPECT_EQ(kJump32, patched->jump);
86
87 ULONG source_addr = bit_cast<ULONG>(source);
88 ULONG target_addr = bit_cast<ULONG>(target);
89 EXPECT_EQ(target_addr + 19 - source_addr, patched->delta);
90 #endif
91 }
92
93 NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
94 sandbox::ServiceResolverThunk* resolver) {
95 HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
96 EXPECT_TRUE(NULL != ntdll_base);
97
98 void* target = ::GetProcAddress(ntdll_base, function);
99 EXPECT_TRUE(NULL != target);
100 if (NULL == target)
101 return STATUS_UNSUCCESSFUL;
102
103 BYTE service[50];
104 memcpy(service, target, sizeof(service));
105
106 static_cast<WinXpResolverTest*>(resolver)->set_target(service);
107
108 // Any pointer will do as an interception_entry_point
109 void* function_entry = resolver;
110 size_t thunk_size = resolver->GetThunkSize();
111 scoped_ptr<char[]> thunk(new char[thunk_size]);
112 size_t used;
113
114 resolver->AllowLocalPatches();
115
116 NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL,
117 function_entry, thunk.get(), thunk_size,
118 &used);
119 if (NT_SUCCESS(ret)) {
120 EXPECT_EQ(thunk_size, used);
121 EXPECT_NE(0, memcmp(service, target, sizeof(service)));
122 EXPECT_NE(kJump32, service[0]);
123
124 if (relaxed) {
125 // It's already patched, let's patch again, and simulate a direct patch.
126 service[0] = kJump32;
127 ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry,
128 thunk.get(), thunk_size, &used);
129 CheckJump(service, thunk.get());
130 }
131 }
132
133 return ret;
134 }
135
136 sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) {
137 #if defined(_WIN64)
138 return new WinXpResolverTest(relaxed);
139 #else
140 base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
141 if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) {
142 if (os_info->version() >= base::win::VERSION_WIN10)
143 return new Wow64W10ResolverTest(relaxed);
144 if (os_info->version() >= base::win::VERSION_WIN8)
145 return new Wow64W8ResolverTest(relaxed);
146 return new Wow64ResolverTest(relaxed);
147 }
148
149 if (os_info->version() >= base::win::VERSION_WIN8)
150 return new Win8ResolverTest(relaxed);
151
152 return new WinXpResolverTest(relaxed);
153 #endif
154 }
155
156 NTSTATUS PatchNtdll(const char* function, bool relaxed) {
157 sandbox::ServiceResolverThunk* resolver = GetTestResolver(relaxed);
158
159 NTSTATUS ret = PatchNtdllWithResolver(function, relaxed, resolver);
160 delete resolver;
161 return ret;
162 }
163
164 TEST(ServiceResolverTest, PatchesServices) {
165 NTSTATUS ret = PatchNtdll("NtClose", false);
166 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
167
168 ret = PatchNtdll("NtCreateFile", false);
169 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
170 ::GetLastError();
171
172 ret = PatchNtdll("NtCreateMutant", false);
173 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
174 ::GetLastError();
175
176 ret = PatchNtdll("NtMapViewOfSection", false);
177 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
178 ::GetLastError();
179 }
180
181 TEST(ServiceResolverTest, FailsIfNotService) {
182 #if !defined(_WIN64)
183 EXPECT_NE(STATUS_SUCCESS, PatchNtdll("RtlUlongByteSwap", false));
184 #endif
185
186 EXPECT_NE(STATUS_SUCCESS, PatchNtdll("LdrLoadDll", false));
187 }
188
189 TEST(ServiceResolverTest, PatchesPatchedServices) {
190 // We don't support "relaxed mode" for Win64 apps.
191 #if !defined(_WIN64)
192 NTSTATUS ret = PatchNtdll("NtClose", true);
193 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
194
195 ret = PatchNtdll("NtCreateFile", true);
196 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
197 ::GetLastError();
198
199 ret = PatchNtdll("NtCreateMutant", true);
200 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
201 ::GetLastError();
202
203 ret = PatchNtdll("NtMapViewOfSection", true);
204 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
205 ::GetLastError();
206 #endif
207 }
208
209 TEST(ServiceResolverTest, MultiplePatchedServices) {
210 // We don't support "relaxed mode" for Win64 apps.
211 #if !defined(_WIN64)
212 sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
213 NTSTATUS ret = PatchNtdllWithResolver("NtClose", true, resolver);
214 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError();
215
216 ret = PatchNtdllWithResolver("NtCreateFile", true, resolver);
217 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " <<
218 ::GetLastError();
219
220 ret = PatchNtdllWithResolver("NtCreateMutant", true, resolver);
221 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " <<
222 ::GetLastError();
223
224 ret = PatchNtdllWithResolver("NtMapViewOfSection", true, resolver);
225 EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " <<
226 ::GetLastError();
227 delete resolver;
228 #endif
229 }
230
231 TEST(ServiceResolverTest, LocalPatchesAllowed) {
232 sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
233
234 HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
235 ASSERT_TRUE(NULL != ntdll_base);
236
237 const char kFunctionName[] = "NtClose";
238
239 void* target = ::GetProcAddress(ntdll_base, kFunctionName);
240 ASSERT_TRUE(NULL != target);
241
242 BYTE service[50];
243 memcpy(service, target, sizeof(service));
244 static_cast<WinXpResolverTest*>(resolver)->set_target(service);
245
246 // Any pointer will do as an interception_entry_point
247 void* function_entry = resolver;
248 size_t thunk_size = resolver->GetThunkSize();
249 scoped_ptr<char[]> thunk(new char[thunk_size]);
250 size_t used;
251
252 NTSTATUS ret = STATUS_UNSUCCESSFUL;
253
254 // First try patching without having allowed local patches.
255 ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL,
256 function_entry, thunk.get(), thunk_size,
257 &used);
258 EXPECT_FALSE(NT_SUCCESS(ret));
259
260 // Now allow local patches and check that things work.
261 resolver->AllowLocalPatches();
262 ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL,
263 function_entry, thunk.get(), thunk_size,
264 &used);
265 EXPECT_EQ(STATUS_SUCCESS, ret);
266 }
267
268 } // namespace
OLDNEW
« no previous file with comments | « sandbox/win/src/service_resolver_64.cc ('k') | sandbox/win/src/sharedmem_ipc_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698