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

Side by Side Diff: sandbox/tests/common/controller.cc

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

Powered by Google App Engine
This is Rietveld 408576698