| 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 |