OLD | NEW |
| (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 <memory> | |
6 #include <string> | |
7 | |
8 #include "base/memory/free_deleter.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/strings/string16.h" | |
11 #include "base/strings/sys_string_conversions.h" | |
12 #include "base/win/scoped_handle.h" | |
13 #include "base/win/scoped_process_information.h" | |
14 #include "base/win/windows_version.h" | |
15 #include "sandbox/win/src/process_thread_interception.h" | |
16 #include "sandbox/win/src/sandbox.h" | |
17 #include "sandbox/win/src/sandbox_factory.h" | |
18 #include "sandbox/win/src/sandbox_policy.h" | |
19 #include "sandbox/win/tests/common/controller.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 | |
22 namespace { | |
23 | |
24 // Creates a process with the |exe| and |command| parameter using the | |
25 // unicode and ascii version of the api. | |
26 sandbox::SboxTestResult CreateProcessHelper(const base::string16& exe, | |
27 const base::string16& command) { | |
28 base::win::ScopedProcessInformation pi; | |
29 STARTUPINFOW si = {sizeof(si)}; | |
30 const wchar_t* exe_name = NULL; | |
31 if (!exe.empty()) | |
32 exe_name = exe.c_str(); | |
33 | |
34 scoped_ptr<wchar_t, base::FreeDeleter> writable_command( | |
35 _wcsdup(command.c_str())); | |
36 | |
37 // Create the process with the unicode version of the API. | |
38 sandbox::SboxTestResult ret1 = sandbox::SBOX_TEST_FAILED; | |
39 PROCESS_INFORMATION temp_process_info = {}; | |
40 if (::CreateProcessW(exe_name, | |
41 command.empty() ? NULL : writable_command.get(), | |
42 NULL, | |
43 NULL, | |
44 FALSE, | |
45 0, | |
46 NULL, | |
47 NULL, | |
48 &si, | |
49 &temp_process_info)) { | |
50 pi.Set(temp_process_info); | |
51 ret1 = sandbox::SBOX_TEST_SUCCEEDED; | |
52 } else { | |
53 DWORD last_error = GetLastError(); | |
54 if ((ERROR_NOT_ENOUGH_QUOTA == last_error) || | |
55 (ERROR_ACCESS_DENIED == last_error) || | |
56 (ERROR_FILE_NOT_FOUND == last_error)) { | |
57 ret1 = sandbox::SBOX_TEST_DENIED; | |
58 } else { | |
59 ret1 = sandbox::SBOX_TEST_FAILED; | |
60 } | |
61 } | |
62 | |
63 pi.Close(); | |
64 | |
65 // Do the same with the ansi version of the api | |
66 STARTUPINFOA sia = {sizeof(sia)}; | |
67 sandbox::SboxTestResult ret2 = sandbox::SBOX_TEST_FAILED; | |
68 | |
69 std::string narrow_cmd_line = | |
70 base::SysWideToMultiByte(command.c_str(), CP_UTF8); | |
71 if (::CreateProcessA( | |
72 exe_name ? base::SysWideToMultiByte(exe_name, CP_UTF8).c_str() : NULL, | |
73 command.empty() ? NULL : &narrow_cmd_line[0], | |
74 NULL, NULL, FALSE, 0, NULL, NULL, &sia, &temp_process_info)) { | |
75 pi.Set(temp_process_info); | |
76 ret2 = sandbox::SBOX_TEST_SUCCEEDED; | |
77 } else { | |
78 DWORD last_error = GetLastError(); | |
79 if ((ERROR_NOT_ENOUGH_QUOTA == last_error) || | |
80 (ERROR_ACCESS_DENIED == last_error) || | |
81 (ERROR_FILE_NOT_FOUND == last_error)) { | |
82 ret2 = sandbox::SBOX_TEST_DENIED; | |
83 } else { | |
84 ret2 = sandbox::SBOX_TEST_FAILED; | |
85 } | |
86 } | |
87 | |
88 if (ret1 == ret2) | |
89 return ret1; | |
90 | |
91 return sandbox::SBOX_TEST_FAILED; | |
92 } | |
93 | |
94 } // namespace | |
95 | |
96 namespace sandbox { | |
97 | |
98 SBOX_TESTS_COMMAND int Process_RunApp1(int argc, wchar_t **argv) { | |
99 if (argc != 1) { | |
100 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
101 } | |
102 if ((NULL == argv) || (NULL == argv[0])) { | |
103 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
104 } | |
105 base::string16 path = MakePathToSys(argv[0], false); | |
106 | |
107 // TEST 1: Try with the path in the app_name. | |
108 return CreateProcessHelper(path, base::string16()); | |
109 } | |
110 | |
111 SBOX_TESTS_COMMAND int Process_RunApp2(int argc, wchar_t **argv) { | |
112 if (argc != 1) { | |
113 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
114 } | |
115 if ((NULL == argv) || (NULL == argv[0])) { | |
116 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
117 } | |
118 base::string16 path = MakePathToSys(argv[0], false); | |
119 | |
120 // TEST 2: Try with the path in the cmd_line. | |
121 base::string16 cmd_line = L"\""; | |
122 cmd_line += path; | |
123 cmd_line += L"\""; | |
124 return CreateProcessHelper(base::string16(), cmd_line); | |
125 } | |
126 | |
127 SBOX_TESTS_COMMAND int Process_RunApp3(int argc, wchar_t **argv) { | |
128 if (argc != 1) { | |
129 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
130 } | |
131 if ((NULL == argv) || (NULL == argv[0])) { | |
132 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
133 } | |
134 // TEST 3: Try file name in the cmd_line. | |
135 return CreateProcessHelper(base::string16(), argv[0]); | |
136 } | |
137 | |
138 SBOX_TESTS_COMMAND int Process_RunApp4(int argc, wchar_t **argv) { | |
139 if (argc != 1) { | |
140 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
141 } | |
142 if ((NULL == argv) || (NULL == argv[0])) { | |
143 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
144 } | |
145 | |
146 // TEST 4: Try file name in the app_name and current directory sets correctly. | |
147 base::string16 system32 = MakePathToSys(L"", false); | |
148 wchar_t current_directory[MAX_PATH + 1]; | |
149 DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); | |
150 if (!ret) | |
151 return SBOX_TEST_FIRST_ERROR; | |
152 if (ret >= MAX_PATH) | |
153 return SBOX_TEST_FAILED; | |
154 | |
155 current_directory[ret] = L'\\'; | |
156 current_directory[ret+1] = L'\0'; | |
157 if (!::SetCurrentDirectory(system32.c_str())) { | |
158 return SBOX_TEST_SECOND_ERROR; | |
159 } | |
160 | |
161 const int result4 = CreateProcessHelper(argv[0], base::string16()); | |
162 return ::SetCurrentDirectory(current_directory) ? result4 : SBOX_TEST_FAILED; | |
163 } | |
164 | |
165 SBOX_TESTS_COMMAND int Process_RunApp5(int argc, wchar_t **argv) { | |
166 if (argc != 1) { | |
167 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
168 } | |
169 if ((NULL == argv) || (NULL == argv[0])) { | |
170 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
171 } | |
172 base::string16 path = MakePathToSys(argv[0], false); | |
173 | |
174 // TEST 5: Try with the path in the cmd_line and arguments. | |
175 base::string16 cmd_line = L"\""; | |
176 cmd_line += path; | |
177 cmd_line += L"\" /I"; | |
178 return CreateProcessHelper(base::string16(), cmd_line); | |
179 } | |
180 | |
181 SBOX_TESTS_COMMAND int Process_RunApp6(int argc, wchar_t **argv) { | |
182 if (argc != 1) { | |
183 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
184 } | |
185 if ((NULL == argv) || (NULL == argv[0])) { | |
186 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
187 } | |
188 | |
189 // TEST 6: Try with the file_name in the cmd_line and arguments. | |
190 base::string16 cmd_line = argv[0]; | |
191 cmd_line += L" /I"; | |
192 return CreateProcessHelper(base::string16(), cmd_line); | |
193 } | |
194 | |
195 // Creates a process and checks if it's possible to get a handle to it's token. | |
196 SBOX_TESTS_COMMAND int Process_GetChildProcessToken(int argc, wchar_t **argv) { | |
197 if (argc != 1) | |
198 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
199 | |
200 if ((NULL == argv) || (NULL == argv[0])) | |
201 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
202 | |
203 base::string16 path = MakePathToSys(argv[0], false); | |
204 | |
205 STARTUPINFOW si = {sizeof(si)}; | |
206 | |
207 PROCESS_INFORMATION temp_process_info = {}; | |
208 if (!::CreateProcessW(path.c_str(), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, | |
209 NULL, NULL, &si, &temp_process_info)) { | |
210 return SBOX_TEST_FAILED; | |
211 } | |
212 base::win::ScopedProcessInformation pi(temp_process_info); | |
213 | |
214 HANDLE token = NULL; | |
215 BOOL result = | |
216 ::OpenProcessToken(pi.process_handle(), TOKEN_IMPERSONATE, &token); | |
217 DWORD error = ::GetLastError(); | |
218 | |
219 base::win::ScopedHandle token_handle(token); | |
220 | |
221 if (!::TerminateProcess(pi.process_handle(), 0)) | |
222 return SBOX_TEST_FAILED; | |
223 | |
224 if (result && token) | |
225 return SBOX_TEST_SUCCEEDED; | |
226 | |
227 if (ERROR_ACCESS_DENIED == error) | |
228 return SBOX_TEST_DENIED; | |
229 | |
230 return SBOX_TEST_FAILED; | |
231 } | |
232 | |
233 // Creates a suspended process using CreateProcessA then kill it. | |
234 SBOX_TESTS_COMMAND int Process_CreateProcessA(int argc, wchar_t** argv) { | |
235 if (argc != 1) | |
236 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
237 | |
238 if ((NULL == argv) || (NULL == argv[0])) | |
239 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
240 | |
241 STARTUPINFOA si = {sizeof(si)}; | |
242 | |
243 base::string16 path = MakePathToSys(argv[0], false); | |
244 | |
245 PROCESS_INFORMATION temp_process_info = {}; | |
246 // Create suspended to avoid popping calc. | |
247 if (!::CreateProcessA(base::SysWideToMultiByte(path, CP_UTF8).c_str(), NULL, | |
248 NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, | |
249 &temp_process_info)) { | |
250 return SBOX_TEST_FAILED; | |
251 } | |
252 base::win::ScopedProcessInformation pi(temp_process_info); | |
253 | |
254 if (!::TerminateProcess(pi.process_handle(), 0)) | |
255 return SBOX_TEST_FAILED; | |
256 | |
257 return SBOX_TEST_SUCCEEDED; | |
258 } | |
259 | |
260 SBOX_TESTS_COMMAND int Process_OpenToken(int argc, wchar_t **argv) { | |
261 HANDLE token; | |
262 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) { | |
263 if (ERROR_ACCESS_DENIED == ::GetLastError()) { | |
264 return SBOX_TEST_DENIED; | |
265 } | |
266 } else { | |
267 ::CloseHandle(token); | |
268 return SBOX_TEST_SUCCEEDED; | |
269 } | |
270 | |
271 return SBOX_TEST_FAILED; | |
272 } | |
273 | |
274 SBOX_TESTS_COMMAND int Process_Crash(int argc, wchar_t **argv) { | |
275 __debugbreak(); | |
276 return SBOX_TEST_FAILED; | |
277 } | |
278 // Generate a event name, used to test thread creation. | |
279 std::wstring GenerateEventName(DWORD pid) { | |
280 wchar_t buff[30] = {0}; | |
281 int res = swprintf_s(buff, sizeof(buff) / sizeof(buff[0]), | |
282 L"ProcessPolicyTest_%08x", pid); | |
283 if (-1 != res) { | |
284 return std::wstring(buff); | |
285 } | |
286 return std::wstring(); | |
287 } | |
288 | |
289 // This is the function that is called when testing thread creation. | |
290 // It is expected to set an event that the caller is waiting on. | |
291 DWORD WINAPI TestThreadFunc(LPVOID lpdwThreadParam) { | |
292 std::wstring event_name = GenerateEventName( | |
293 static_cast<DWORD>(reinterpret_cast<uintptr_t>(lpdwThreadParam))); | |
294 if (!event_name.length()) { | |
295 return 1; | |
296 } | |
297 HANDLE event = ::OpenEvent(EVENT_ALL_ACCESS | EVENT_MODIFY_STATE, FALSE, | |
298 event_name.c_str()); | |
299 if (!event) { | |
300 return 1; | |
301 } | |
302 if (!SetEvent(event)) { | |
303 return 1; | |
304 } | |
305 return 0; | |
306 } | |
307 | |
308 SBOX_TESTS_COMMAND int Process_CreateThread(int argc, wchar_t** argv) { | |
309 DWORD pid = ::GetCurrentProcessId(); | |
310 std::wstring event_name = GenerateEventName(pid); | |
311 if (!event_name.length()) { | |
312 return SBOX_TEST_FIRST_ERROR; | |
313 } | |
314 HANDLE event = ::CreateEvent(NULL, TRUE, FALSE, event_name.c_str()); | |
315 if (!event) { | |
316 return SBOX_TEST_SECOND_ERROR; | |
317 } | |
318 | |
319 DWORD thread_id = 0; | |
320 HANDLE thread = NULL; | |
321 thread = ::CreateThread(NULL, 0, &TestThreadFunc, | |
322 reinterpret_cast<LPVOID>(static_cast<uintptr_t>(pid)), | |
323 0, &thread_id); | |
324 | |
325 if (!thread) { | |
326 return SBOX_TEST_THIRD_ERROR; | |
327 } | |
328 if (!thread_id) { | |
329 return SBOX_TEST_FOURTH_ERROR; | |
330 } | |
331 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) { | |
332 return SBOX_TEST_FIFTH_ERROR; | |
333 } | |
334 DWORD exit_code = 0; | |
335 if (!GetExitCodeThread(thread, &exit_code)) { | |
336 return SBOX_TEST_SIXTH_ERROR; | |
337 } | |
338 if (exit_code) { | |
339 return SBOX_TEST_SEVENTH_ERROR; | |
340 } | |
341 if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) { | |
342 return SBOX_TEST_FAILED; | |
343 } | |
344 return SBOX_TEST_SUCCEEDED; | |
345 } | |
346 | |
347 TEST(ProcessPolicyTest, TestAllAccess) { | |
348 // Check if the "all access" rule fails to be added when the token is too | |
349 // powerful. | |
350 TestRunner runner; | |
351 | |
352 // Check the failing case. | |
353 runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); | |
354 EXPECT_EQ(SBOX_ERROR_UNSUPPORTED, | |
355 runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS, | |
356 TargetPolicy::PROCESS_ALL_EXEC, | |
357 L"this is not important")); | |
358 | |
359 // Check the working case. | |
360 runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_INTERACTIVE); | |
361 | |
362 EXPECT_EQ(SBOX_ALL_OK, | |
363 runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS, | |
364 TargetPolicy::PROCESS_ALL_EXEC, | |
365 L"this is not important")); | |
366 } | |
367 | |
368 TEST(ProcessPolicyTest, CreateProcessAW) { | |
369 TestRunner runner; | |
370 base::string16 maybe_virtual_exe_path = MakePathToSys(L"findstr.exe", false); | |
371 base::string16 non_virtual_exe_path = MakePathToSys32(L"findstr.exe", false); | |
372 ASSERT_TRUE(!maybe_virtual_exe_path.empty()); | |
373 | |
374 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
375 TargetPolicy::PROCESS_MIN_EXEC, | |
376 maybe_virtual_exe_path.c_str())); | |
377 | |
378 if (non_virtual_exe_path != maybe_virtual_exe_path) { | |
379 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
380 TargetPolicy::PROCESS_MIN_EXEC, | |
381 non_virtual_exe_path.c_str())); | |
382 } | |
383 | |
384 // Need to add directory rules for the directories that we use in | |
385 // SetCurrentDirectory. | |
386 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L"")); | |
387 | |
388 wchar_t current_directory[MAX_PATH]; | |
389 DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); | |
390 ASSERT_TRUE(0 != ret && ret < MAX_PATH); | |
391 | |
392 wcscat_s(current_directory, MAX_PATH, L"\\"); | |
393 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, | |
394 current_directory)); | |
395 | |
396 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp1 calc.exe")); | |
397 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp2 calc.exe")); | |
398 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp3 calc.exe")); | |
399 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp4 calc.exe")); | |
400 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp5 calc.exe")); | |
401 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp6 calc.exe")); | |
402 | |
403 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
404 runner.RunTest(L"Process_RunApp1 findstr.exe")); | |
405 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
406 runner.RunTest(L"Process_RunApp2 findstr.exe")); | |
407 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
408 runner.RunTest(L"Process_RunApp3 findstr.exe")); | |
409 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
410 runner.RunTest(L"Process_RunApp4 findstr.exe")); | |
411 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
412 runner.RunTest(L"Process_RunApp5 findstr.exe")); | |
413 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
414 runner.RunTest(L"Process_RunApp6 findstr.exe")); | |
415 } | |
416 | |
417 // Tests that the broker correctly handles a process crashing within the job. | |
418 TEST(ProcessPolicyTest, CreateProcessCrashy) { | |
419 TestRunner runner; | |
420 EXPECT_EQ(static_cast<int>(STATUS_BREAKPOINT), | |
421 runner.RunTest(L"Process_Crash")); | |
422 } | |
423 | |
424 TEST(ProcessPolicyTest, OpenToken) { | |
425 TestRunner runner; | |
426 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_OpenToken")); | |
427 } | |
428 | |
429 TEST(ProcessPolicyTest, TestGetProcessTokenMinAccess) { | |
430 TestRunner runner; | |
431 base::string16 exe_path = MakePathToSys(L"findstr.exe", false); | |
432 ASSERT_TRUE(!exe_path.empty()); | |
433 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
434 TargetPolicy::PROCESS_MIN_EXEC, | |
435 exe_path.c_str())); | |
436 | |
437 EXPECT_EQ(SBOX_TEST_DENIED, | |
438 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); | |
439 } | |
440 | |
441 TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccess) { | |
442 TestRunner runner(JOB_UNPROTECTED, USER_INTERACTIVE, USER_INTERACTIVE); | |
443 base::string16 exe_path = MakePathToSys(L"findstr.exe", false); | |
444 ASSERT_TRUE(!exe_path.empty()); | |
445 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
446 TargetPolicy::PROCESS_ALL_EXEC, | |
447 exe_path.c_str())); | |
448 | |
449 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
450 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); | |
451 } | |
452 | |
453 TEST(ProcessPolicyTest, TestGetProcessTokenMinAccessNoJob) { | |
454 TestRunner runner(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN); | |
455 base::string16 exe_path = MakePathToSys(L"findstr.exe", false); | |
456 ASSERT_TRUE(!exe_path.empty()); | |
457 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
458 TargetPolicy::PROCESS_MIN_EXEC, | |
459 exe_path.c_str())); | |
460 | |
461 EXPECT_EQ(SBOX_TEST_DENIED, | |
462 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); | |
463 } | |
464 | |
465 TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccessNoJob) { | |
466 TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE); | |
467 base::string16 exe_path = MakePathToSys(L"findstr.exe", false); | |
468 ASSERT_TRUE(!exe_path.empty()); | |
469 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
470 TargetPolicy::PROCESS_ALL_EXEC, | |
471 exe_path.c_str())); | |
472 | |
473 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
474 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); | |
475 } | |
476 | |
477 TEST(ProcessPolicyTest, TestCreateProcessA) { | |
478 TestRunner runner; | |
479 sandbox::TargetPolicy* policy = runner.GetPolicy(); | |
480 policy->SetJobLevel(JOB_NONE, 0); | |
481 policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED); | |
482 base::string16 exe_path = MakePathToSys(L"calc.exe", false); | |
483 ASSERT_TRUE(!exe_path.empty()); | |
484 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | |
485 TargetPolicy::PROCESS_ALL_EXEC, exe_path.c_str())); | |
486 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
487 runner.RunTest(L"Process_CreateProcessA calc.exe")); | |
488 } | |
489 | |
490 // This tests that the CreateThread works with CSRSS not locked down. | |
491 // In other words, that the interception passes through OK. | |
492 TEST(ProcessPolicyTest, TestCreateThreadWithCsrss) { | |
493 TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE); | |
494 runner.SetDisableCsrss(false); | |
495 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_CreateThread")); | |
496 } | |
497 | |
498 // This tests that the CreateThread works with CSRSS locked down. | |
499 // In other words, that the interception correctly works. | |
500 TEST(ProcessPolicyTest, TestCreateThreadWithoutCsrss) { | |
501 TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE); | |
502 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_CreateThread")); | |
503 } | |
504 | |
505 // This tests that our CreateThread interceptors works when called directly. | |
506 TEST(ProcessPolicyTest, TestCreateThreadOutsideSandbox) { | |
507 DWORD pid = ::GetCurrentProcessId(); | |
508 std::wstring event_name = GenerateEventName(pid); | |
509 ASSERT_STRNE(NULL, event_name.c_str()); | |
510 HANDLE event = ::CreateEvent(NULL, TRUE, FALSE, event_name.c_str()); | |
511 EXPECT_NE(static_cast<HANDLE>(NULL), event); | |
512 | |
513 DWORD thread_id = 0; | |
514 HANDLE thread = NULL; | |
515 thread = TargetCreateThread( | |
516 ::CreateThread, NULL, 0, &TestThreadFunc, | |
517 reinterpret_cast<LPVOID>(static_cast<uintptr_t>(pid)), 0, &thread_id); | |
518 EXPECT_NE(static_cast<HANDLE>(NULL), thread); | |
519 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, INFINITE)); | |
520 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(event, INFINITE)); | |
521 } | |
522 | |
523 } // namespace sandbox | |
OLD | NEW |