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

Side by Side Diff: sandbox/win/tests/common/controller.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/tests/common/controller.h ('k') | sandbox/win/tests/common/test_utils.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 #include "sandbox/win/tests/common/controller.h"
6
7 #include <string>
8
9 #include "base/memory/shared_memory.h"
10 #include "base/process/process.h"
11 #include "base/process/process_handle.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/win/windows_version.h"
15 #include "sandbox/win/src/sandbox_factory.h"
16
17 namespace {
18
19 static const int kDefaultTimeout = 60000;
20
21 bool IsProcessRunning(HANDLE process) {
22 DWORD exit_code = 0;
23 if (::GetExitCodeProcess(process, &exit_code))
24 return exit_code == STILL_ACTIVE;
25 return false;
26 }
27
28 } // namespace
29
30 namespace sandbox {
31
32 // Constructs a full path to a file inside the system32 folder.
33 base::string16 MakePathToSys32(const wchar_t* name, bool is_obj_man_path) {
34 wchar_t windows_path[MAX_PATH] = {0};
35 if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH))
36 return base::string16();
37
38 base::string16 full_path(windows_path);
39 if (full_path.empty())
40 return full_path;
41
42 if (is_obj_man_path)
43 full_path.insert(0, L"\\??\\");
44
45 full_path += L"\\system32\\";
46 full_path += name;
47 return full_path;
48 }
49
50 // Constructs a full path to a file inside the syswow64 folder.
51 base::string16 MakePathToSysWow64(const wchar_t* name, bool is_obj_man_path) {
52 wchar_t windows_path[MAX_PATH] = {0};
53 if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH))
54 return base::string16();
55
56 base::string16 full_path(windows_path);
57 if (full_path.empty())
58 return full_path;
59
60 if (is_obj_man_path)
61 full_path.insert(0, L"\\??\\");
62
63 full_path += L"\\SysWOW64\\";
64 full_path += name;
65 return full_path;
66 }
67
68 base::string16 MakePathToSys(const wchar_t* name, bool is_obj_man_path) {
69 return (base::win::OSInfo::GetInstance()->wow64_status() ==
70 base::win::OSInfo::WOW64_ENABLED) ?
71 MakePathToSysWow64(name, is_obj_man_path) :
72 MakePathToSys32(name, is_obj_man_path);
73 }
74
75 BrokerServices* GetBroker() {
76 static BrokerServices* broker = SandboxFactory::GetBrokerServices();
77 static bool is_initialized = false;
78
79 if (!broker) {
80 return NULL;
81 }
82
83 if (!is_initialized) {
84 if (SBOX_ALL_OK != broker->Init())
85 return NULL;
86
87 is_initialized = true;
88 }
89
90 return broker;
91 }
92
93 TestRunner::TestRunner(JobLevel job_level,
94 TokenLevel startup_token,
95 TokenLevel main_token)
96 : is_init_(false),
97 is_async_(false),
98 no_sandbox_(false),
99 disable_csrss_(true),
100 target_process_id_(0) {
101 Init(job_level, startup_token, main_token);
102 }
103
104 TestRunner::TestRunner()
105 : is_init_(false),
106 is_async_(false),
107 no_sandbox_(false),
108 disable_csrss_(true),
109 target_process_id_(0) {
110 Init(JOB_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
111 }
112
113 void TestRunner::Init(JobLevel job_level,
114 TokenLevel startup_token,
115 TokenLevel main_token) {
116 broker_ = NULL;
117 policy_ = NULL;
118 timeout_ = kDefaultTimeout;
119 state_ = AFTER_REVERT;
120 is_async_= false;
121 kill_on_destruction_ = true;
122 target_process_id_ = 0;
123
124 broker_ = GetBroker();
125 if (!broker_)
126 return;
127
128 policy_ = broker_->CreatePolicy();
129 if (!policy_)
130 return;
131
132 policy_->SetJobLevel(job_level, 0);
133 policy_->SetTokenLevel(startup_token, main_token);
134
135 is_init_ = true;
136 }
137
138 TargetPolicy* TestRunner::GetPolicy() {
139 return policy_;
140 }
141
142 TestRunner::~TestRunner() {
143 if (target_process_.IsValid() && kill_on_destruction_)
144 ::TerminateProcess(target_process_.Get(), 0);
145
146 if (policy_)
147 policy_->Release();
148 }
149
150 bool TestRunner::AddRule(TargetPolicy::SubSystem subsystem,
151 TargetPolicy::Semantics semantics,
152 const wchar_t* pattern) {
153 if (!is_init_)
154 return false;
155
156 return (SBOX_ALL_OK == policy_->AddRule(subsystem, semantics, pattern));
157 }
158
159 bool TestRunner::AddRuleSys32(TargetPolicy::Semantics semantics,
160 const wchar_t* pattern) {
161 if (!is_init_)
162 return false;
163
164 base::string16 win32_path = MakePathToSys32(pattern, false);
165 if (win32_path.empty())
166 return false;
167
168 if (!AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str()))
169 return false;
170
171 if (base::win::OSInfo::GetInstance()->wow64_status() !=
172 base::win::OSInfo::WOW64_ENABLED)
173 return true;
174
175 win32_path = MakePathToSysWow64(pattern, false);
176 if (win32_path.empty())
177 return false;
178
179 return AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str());
180 }
181
182 bool TestRunner::AddFsRule(TargetPolicy::Semantics semantics,
183 const wchar_t* pattern) {
184 if (!is_init_)
185 return false;
186
187 return AddRule(TargetPolicy::SUBSYS_FILES, semantics, pattern);
188 }
189
190 int TestRunner::RunTest(const wchar_t* command) {
191 if (MAX_STATE > 10)
192 return SBOX_TEST_INVALID_PARAMETER;
193
194 wchar_t state_number[2];
195 state_number[0] = static_cast<wchar_t>(L'0' + state_);
196 state_number[1] = L'\0';
197 base::string16 full_command(state_number);
198 full_command += L" ";
199 full_command += command;
200
201 return InternalRunTest(full_command.c_str());
202 }
203
204 int TestRunner::InternalRunTest(const wchar_t* command) {
205 if (!is_init_)
206 return SBOX_TEST_FAILED_TO_RUN_TEST;
207
208 // For simplicity TestRunner supports only one process per instance.
209 if (target_process_.IsValid()) {
210 if (IsProcessRunning(target_process_.Get()))
211 return SBOX_TEST_FAILED_TO_RUN_TEST;
212 target_process_.Close();
213 target_process_id_ = 0;
214 }
215
216 if (disable_csrss_)
217 policy_->SetDisconnectCsrss();
218
219 // Get the path to the sandboxed process.
220 wchar_t prog_name[MAX_PATH];
221 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
222
223 // Launch the sandboxed process.
224 ResultCode result = SBOX_ALL_OK;
225 PROCESS_INFORMATION target = {0};
226
227 base::string16 arguments(L"\"");
228 arguments += prog_name;
229 arguments += L"\" -child";
230 arguments += no_sandbox_ ? L"-no-sandbox " : L" ";
231 arguments += command;
232
233 if (no_sandbox_) {
234 STARTUPINFO startup_info = {sizeof(STARTUPINFO)};
235 if (!::CreateProcessW(prog_name, &arguments[0], NULL, NULL, FALSE, 0,
236 NULL, NULL, &startup_info, &target)) {
237 return SBOX_ERROR_GENERIC;
238 }
239 broker_->AddTargetPeer(target.hProcess);
240 } else {
241 result = broker_->SpawnTarget(prog_name, arguments.c_str(), policy_,
242 &target);
243 }
244
245 if (SBOX_ALL_OK != result)
246 return SBOX_TEST_FAILED_TO_RUN_TEST;
247
248 ::ResumeThread(target.hThread);
249
250 // For an asynchronous run we don't bother waiting.
251 if (is_async_) {
252 target_process_.Set(target.hProcess);
253 target_process_id_ = target.dwProcessId;
254 ::CloseHandle(target.hThread);
255 return SBOX_TEST_SUCCEEDED;
256 }
257
258 if (::IsDebuggerPresent()) {
259 // Don't kill the target process on a time-out while we are debugging.
260 timeout_ = INFINITE;
261 }
262
263 if (WAIT_TIMEOUT == ::WaitForSingleObject(target.hProcess, timeout_)) {
264 ::TerminateProcess(target.hProcess, static_cast<UINT>(SBOX_TEST_TIMED_OUT));
265 ::CloseHandle(target.hProcess);
266 ::CloseHandle(target.hThread);
267 return SBOX_TEST_TIMED_OUT;
268 }
269
270 DWORD exit_code = static_cast<DWORD>(SBOX_TEST_LAST_RESULT);
271 if (!::GetExitCodeProcess(target.hProcess, &exit_code)) {
272 ::CloseHandle(target.hProcess);
273 ::CloseHandle(target.hThread);
274 return SBOX_TEST_FAILED_TO_RUN_TEST;
275 }
276
277 ::CloseHandle(target.hProcess);
278 ::CloseHandle(target.hThread);
279
280 return exit_code;
281 }
282
283 void TestRunner::SetTimeout(DWORD timeout_ms) {
284 timeout_ = timeout_ms;
285 }
286
287 void TestRunner::SetTestState(SboxTestsState desired_state) {
288 state_ = desired_state;
289 }
290
291 // This is the main procedure for the target (child) application. We'll find out
292 // the target test and call it.
293 // We expect the arguments to be:
294 // argv[1] = "-child"
295 // argv[2] = SboxTestsState when to run the command
296 // argv[3] = command to run
297 // argv[4...] = command arguments.
298 int DispatchCall(int argc, wchar_t **argv) {
299 if (argc < 4)
300 return SBOX_TEST_INVALID_PARAMETER;
301
302 // We hard code two tests to avoid dispatch failures.
303 if (0 == _wcsicmp(argv[3], L"wait")) {
304 Sleep(INFINITE);
305 return SBOX_TEST_TIMED_OUT;
306 }
307
308 if (0 == _wcsicmp(argv[3], L"ping"))
309 return SBOX_TEST_PING_OK;
310
311 // If the caller shared a shared memory handle with us attempt to open it
312 // in read only mode and sleep infinitely if we succeed.
313 if (0 == _wcsicmp(argv[3], L"shared_memory_handle")) {
314 HANDLE raw_handle = nullptr;
315 base::StringToUint(argv[4], reinterpret_cast<unsigned int*>(&raw_handle));
316 if (raw_handle == nullptr)
317 return SBOX_TEST_INVALID_PARAMETER;
318 base::SharedMemoryHandle shared_handle(raw_handle,
319 base::GetCurrentProcId());
320 base::SharedMemory read_only_view(shared_handle, true);
321 if (!read_only_view.Map(0))
322 return SBOX_TEST_INVALID_PARAMETER;
323 std::string contents(reinterpret_cast<char*>(read_only_view.memory()));
324 if (contents != "Hello World")
325 return SBOX_TEST_INVALID_PARAMETER;
326 Sleep(INFINITE);
327 return SBOX_TEST_TIMED_OUT;
328 }
329
330 SboxTestsState state = static_cast<SboxTestsState>(_wtoi(argv[2]));
331 if ((state <= MIN_STATE) || (state >= MAX_STATE))
332 return SBOX_TEST_INVALID_PARAMETER;
333
334 HMODULE module;
335 if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
336 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
337 reinterpret_cast<wchar_t*>(&DispatchCall), &module))
338 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
339
340 std::string command_name = base::SysWideToMultiByte(argv[3], CP_UTF8);
341 CommandFunction command = reinterpret_cast<CommandFunction>(
342 ::GetProcAddress(module, command_name.c_str()));
343 if (!command)
344 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
345
346 if (BEFORE_INIT == state)
347 return command(argc - 4, argv + 4);
348 else if (EVERY_STATE == state)
349 command(argc - 4, argv + 4);
350
351 TargetServices* target = SandboxFactory::GetTargetServices();
352 if (target) {
353 if (SBOX_ALL_OK != target->Init())
354 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
355
356 if (BEFORE_REVERT == state)
357 return command(argc - 4, argv + 4);
358 else if (EVERY_STATE == state)
359 command(argc - 4, argv + 4);
360
361 #if defined(ADDRESS_SANITIZER)
362 // Bind and leak dbghelp.dll before the token is lowered, otherwise
363 // AddressSanitizer will crash when trying to symbolize a report.
364 if (!LoadLibraryA("dbghelp.dll"))
365 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
366 #endif
367
368 target->LowerToken();
369 } else if (0 != _wcsicmp(argv[1], L"-child-no-sandbox")) {
370 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
371 }
372
373 return command(argc - 4, argv + 4);
374 }
375
376 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/tests/common/controller.h ('k') | sandbox/win/tests/common/test_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698