policy_target_test.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. #include "base/memory/read_only_shared_memory_region.h"
  5. #include "base/memory/writable_shared_memory_region.h"
  6. #include "base/strings/string_number_conversions.h"
  7. #include "base/strings/string_piece.h"
  8. #include "base/strings/string_util.h"
  9. #include "base/win/scoped_process_information.h"
  10. #include "base/win/windows_version.h"
  11. #include "build/build_config.h"
  12. #include "sandbox/win/src/broker_services.h"
  13. #include "sandbox/win/src/sandbox.h"
  14. #include "sandbox/win/src/sandbox_factory.h"
  15. #include "sandbox/win/src/sandbox_policy.h"
  16. #include "sandbox/win/src/sandbox_utils.h"
  17. #include "sandbox/win/src/target_services.h"
  18. #include "sandbox/win/tests/common/controller.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. #if BUILDFLAG(IS_WIN)
  21. #include "base/win/win_util.h"
  22. #endif
  23. namespace sandbox {
  24. #define BINDNTDLL(name) \
  25. name##Function name = reinterpret_cast<name##Function>( \
  26. ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
  27. // Reverts to self and verify that SetInformationToken was faked. Returns
  28. // SBOX_TEST_SUCCEEDED if faked and SBOX_TEST_FAILED if not faked.
  29. SBOX_TESTS_COMMAND int PolicyTargetTest_token(int argc, wchar_t** argv) {
  30. HANDLE thread_token;
  31. // Get the thread token, using impersonation.
  32. if (!::OpenThreadToken(GetCurrentThread(),
  33. TOKEN_IMPERSONATE | TOKEN_DUPLICATE, false,
  34. &thread_token))
  35. return ::GetLastError();
  36. ::RevertToSelf();
  37. ::CloseHandle(thread_token);
  38. int ret = SBOX_TEST_FAILED;
  39. if (::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  40. false, &thread_token)) {
  41. ret = SBOX_TEST_SUCCEEDED;
  42. ::CloseHandle(thread_token);
  43. }
  44. return ret;
  45. }
  46. // Stores the high privilege token on a static variable, change impersonation
  47. // again to that one and verify that we are not interfering anymore with
  48. // RevertToSelf.
  49. SBOX_TESTS_COMMAND int PolicyTargetTest_steal(int argc, wchar_t** argv) {
  50. static HANDLE thread_token;
  51. if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
  52. if (!::OpenThreadToken(GetCurrentThread(),
  53. TOKEN_IMPERSONATE | TOKEN_DUPLICATE, false,
  54. &thread_token))
  55. return ::GetLastError();
  56. } else {
  57. if (!::SetThreadToken(nullptr, thread_token))
  58. return ::GetLastError();
  59. // See if we fake the call again.
  60. int ret = PolicyTargetTest_token(argc, argv);
  61. ::CloseHandle(thread_token);
  62. return ret;
  63. }
  64. return 0;
  65. }
  66. // Opens the thread token with and without impersonation.
  67. SBOX_TESTS_COMMAND int PolicyTargetTest_token2(int argc, wchar_t** argv) {
  68. HANDLE thread_token;
  69. // Get the thread token, using impersonation.
  70. if (!::OpenThreadToken(GetCurrentThread(),
  71. TOKEN_IMPERSONATE | TOKEN_DUPLICATE, false,
  72. &thread_token))
  73. return ::GetLastError();
  74. ::CloseHandle(thread_token);
  75. // Get the thread token, without impersonation.
  76. if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  77. true, &thread_token))
  78. return ::GetLastError();
  79. ::CloseHandle(thread_token);
  80. return SBOX_TEST_SUCCEEDED;
  81. }
  82. // Opens the thread token with and without impersonation, using
  83. // NtOpenThreadTokenEX.
  84. SBOX_TESTS_COMMAND int PolicyTargetTest_token3(int argc, wchar_t** argv) {
  85. BINDNTDLL(NtOpenThreadTokenEx);
  86. if (!NtOpenThreadTokenEx)
  87. return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
  88. HANDLE thread_token;
  89. // Get the thread token, using impersonation.
  90. NTSTATUS status = NtOpenThreadTokenEx(GetCurrentThread(),
  91. TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  92. false, 0, &thread_token);
  93. if (status == STATUS_NO_TOKEN)
  94. return ERROR_NO_TOKEN;
  95. if (!NT_SUCCESS(status))
  96. return SBOX_TEST_FAILED;
  97. ::CloseHandle(thread_token);
  98. // Get the thread token, without impersonation.
  99. status = NtOpenThreadTokenEx(GetCurrentThread(),
  100. TOKEN_IMPERSONATE | TOKEN_DUPLICATE, true, 0,
  101. &thread_token);
  102. if (!NT_SUCCESS(status))
  103. return SBOX_TEST_FAILED;
  104. ::CloseHandle(thread_token);
  105. return SBOX_TEST_SUCCEEDED;
  106. }
  107. // Tests that we can open the current thread.
  108. SBOX_TESTS_COMMAND int PolicyTargetTest_thread(int argc, wchar_t** argv) {
  109. DWORD thread_id = ::GetCurrentThreadId();
  110. HANDLE thread = ::OpenThread(SYNCHRONIZE, false, thread_id);
  111. if (!thread)
  112. return ::GetLastError();
  113. if (!::CloseHandle(thread))
  114. return ::GetLastError();
  115. return SBOX_TEST_SUCCEEDED;
  116. }
  117. // New thread entry point: do nothing.
  118. DWORD WINAPI PolicyTargetTest_thread_main(void* param) {
  119. ::Sleep(INFINITE);
  120. return 0;
  121. }
  122. // Tests that we can create a new thread, and open it.
  123. SBOX_TESTS_COMMAND int PolicyTargetTest_thread2(int argc, wchar_t** argv) {
  124. // Use default values to create a new thread.
  125. DWORD thread_id;
  126. HANDLE thread = ::CreateThread(nullptr, 0, &PolicyTargetTest_thread_main, 0,
  127. 0, &thread_id);
  128. if (!thread)
  129. return ::GetLastError();
  130. if (!::CloseHandle(thread))
  131. return ::GetLastError();
  132. thread = ::OpenThread(SYNCHRONIZE, false, thread_id);
  133. if (!thread)
  134. return ::GetLastError();
  135. if (!::CloseHandle(thread))
  136. return ::GetLastError();
  137. return SBOX_TEST_SUCCEEDED;
  138. }
  139. // Tests that we can call CreateProcess.
  140. SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t** argv) {
  141. // Use default values to create a new process.
  142. STARTUPINFO startup_info = {0};
  143. startup_info.cb = sizeof(startup_info);
  144. PROCESS_INFORMATION temp_process_info = {};
  145. // Note: CreateProcessW() can write to its lpCommandLine, don't pass a
  146. // raw string literal.
  147. std::wstring writable_cmdline_str(L"foo.exe");
  148. if (!::CreateProcessW(L"foo.exe", &writable_cmdline_str[0], nullptr, nullptr,
  149. false, 0, nullptr, nullptr, &startup_info,
  150. &temp_process_info))
  151. return SBOX_TEST_SUCCEEDED;
  152. base::win::ScopedProcessInformation process_info(temp_process_info);
  153. return SBOX_TEST_FAILED;
  154. }
  155. TEST(PolicyTargetTest, SetInformationThread) {
  156. TestRunner runner;
  157. runner.SetTestState(BEFORE_REVERT);
  158. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
  159. TestRunner runner1;
  160. runner1.SetTestState(AFTER_REVERT);
  161. EXPECT_EQ(ERROR_NO_TOKEN, runner1.RunTest(L"PolicyTargetTest_token"));
  162. TestRunner runner2;
  163. runner2.SetTestState(EVERY_STATE);
  164. EXPECT_EQ(SBOX_TEST_FAILED, runner2.RunTest(L"PolicyTargetTest_steal"));
  165. }
  166. TEST(PolicyTargetTest, OpenThreadToken) {
  167. TestRunner runner;
  168. runner.SetTestState(BEFORE_REVERT);
  169. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
  170. TestRunner runner2;
  171. runner2.SetTestState(AFTER_REVERT);
  172. EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token2"));
  173. }
  174. TEST(PolicyTargetTest, OpenThreadTokenEx) {
  175. TestRunner runner;
  176. runner.SetTestState(BEFORE_REVERT);
  177. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
  178. TestRunner runner2;
  179. runner2.SetTestState(AFTER_REVERT);
  180. EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token3"));
  181. }
  182. TEST(PolicyTargetTest, OpenThread) {
  183. TestRunner runner;
  184. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread"))
  185. << "Opens the current thread";
  186. TestRunner runner2;
  187. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(L"PolicyTargetTest_thread2"))
  188. << "Creates a new thread and opens it";
  189. }
  190. TEST(PolicyTargetTest, OpenProcess) {
  191. TestRunner runner;
  192. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_process"))
  193. << "Opens a process";
  194. }
  195. TEST(PolicyTargetTest, PolicyBaseNoJobLifetime) {
  196. TestRunner runner(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS,
  197. USER_LOCKDOWN);
  198. // TargetPolicy and its SharedMemIPCServer should continue to exist until
  199. // the child process dies.
  200. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread"))
  201. << "Opens the current thread";
  202. }
  203. // Sets the desktop for the current thread to be one with a null DACL, then
  204. // launches a sandboxed app. Validates that the sandboxed app has access to the
  205. // desktop.
  206. TEST(PolicyTargetTest, InheritedDesktopPolicy) {
  207. // Create a desktop with a null dacl - which should allow access to
  208. // everything.
  209. SECURITY_ATTRIBUTES attributes = {};
  210. attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  211. SECURITY_DESCRIPTOR security_desc = {};
  212. ::InitializeSecurityDescriptor(&security_desc, SECURITY_DESCRIPTOR_REVISION);
  213. ::SetSecurityDescriptorDacl(&security_desc, true, nullptr, false);
  214. attributes.lpSecurityDescriptor = &security_desc;
  215. HDESK null_dacl_desktop_handle = CreateDesktop(
  216. L"null_dacl_desktop", nullptr, nullptr, 0, GENERIC_ALL, &attributes);
  217. EXPECT_TRUE(null_dacl_desktop_handle);
  218. // Switch to the null dacl desktop and run the test.
  219. HDESK old_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
  220. EXPECT_TRUE(null_dacl_desktop_handle);
  221. EXPECT_TRUE(::SetThreadDesktop(null_dacl_desktop_handle));
  222. BrokerServices* broker = GetBroker();
  223. // Precreate the desktop.
  224. broker->CreatePolicy()->CreateAlternateDesktop(false);
  225. ASSERT_TRUE(broker);
  226. // Get the path to the sandboxed app.
  227. wchar_t prog_name[MAX_PATH];
  228. GetModuleFileNameW(nullptr, prog_name, MAX_PATH);
  229. std::wstring arguments(L"\"");
  230. arguments += prog_name;
  231. arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
  232. // Launch the app.
  233. ResultCode result = SBOX_ALL_OK;
  234. ResultCode warning_result = SBOX_ALL_OK;
  235. DWORD last_error = ERROR_SUCCESS;
  236. base::win::ScopedProcessInformation target;
  237. auto policy = broker->CreatePolicy();
  238. policy->SetAlternateDesktop(false);
  239. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  240. PROCESS_INFORMATION temp_process_info = {};
  241. result =
  242. broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
  243. &warning_result, &last_error, &temp_process_info);
  244. EXPECT_EQ(SBOX_ALL_OK, result);
  245. if (result == SBOX_ALL_OK)
  246. target.Set(temp_process_info);
  247. // Run the process for some time to make sure it doesn't crash on launch
  248. EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
  249. EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
  250. ::WaitForSingleObject(target.process_handle(), 2000));
  251. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  252. ::WaitForSingleObject(target.process_handle(), INFINITE);
  253. // Close the desktop handle.
  254. broker->CreatePolicy()->DestroyAlternateDesktop();
  255. // Close the null dacl desktop.
  256. EXPECT_TRUE(::SetThreadDesktop(old_desktop));
  257. EXPECT_TRUE(::CloseDesktop(null_dacl_desktop_handle));
  258. }
  259. // Launches the app in the sandbox and ask it to wait in an
  260. // infinite loop. Waits for 2 seconds and then check if the
  261. // desktop associated with the app thread is not the same as the
  262. // current desktop.
  263. TEST(PolicyTargetTest, DesktopPolicy) {
  264. BrokerServices* broker = GetBroker();
  265. // Precreate the desktop.
  266. broker->CreatePolicy()->CreateAlternateDesktop(false);
  267. ASSERT_TRUE(broker);
  268. // Get the path to the sandboxed app.
  269. wchar_t prog_name[MAX_PATH];
  270. GetModuleFileNameW(nullptr, prog_name, MAX_PATH);
  271. std::wstring arguments(L"\"");
  272. arguments += prog_name;
  273. arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
  274. // Launch the app.
  275. ResultCode result = SBOX_ALL_OK;
  276. ResultCode warning_result = SBOX_ALL_OK;
  277. DWORD last_error = ERROR_SUCCESS;
  278. base::win::ScopedProcessInformation target;
  279. auto policy = broker->CreatePolicy();
  280. policy->SetAlternateDesktop(false);
  281. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  282. PROCESS_INFORMATION temp_process_info = {};
  283. // Keep the desktop name to test against later.
  284. std::wstring desktop_name = policy->GetAlternateDesktop();
  285. result =
  286. broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
  287. &warning_result, &last_error, &temp_process_info);
  288. EXPECT_EQ(SBOX_ALL_OK, result);
  289. if (result == SBOX_ALL_OK)
  290. target.Set(temp_process_info);
  291. EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
  292. EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
  293. ::WaitForSingleObject(target.process_handle(), 2000));
  294. EXPECT_NE(::GetThreadDesktop(target.thread_id()),
  295. ::GetThreadDesktop(::GetCurrentThreadId()));
  296. HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, false, DESKTOP_ENUMERATE);
  297. EXPECT_TRUE(desk);
  298. EXPECT_TRUE(::CloseDesktop(desk));
  299. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  300. ::WaitForSingleObject(target.process_handle(), INFINITE);
  301. // Close the desktop handle.
  302. broker->CreatePolicy()->DestroyAlternateDesktop();
  303. // Make sure the desktop does not exist anymore.
  304. desk = ::OpenDesktop(desktop_name.c_str(), 0, false, DESKTOP_ENUMERATE);
  305. EXPECT_FALSE(desk);
  306. }
  307. // Launches the app in the sandbox and ask it to wait in an
  308. // infinite loop. Waits for 2 seconds and then check if the
  309. // winstation associated with the app thread is not the same as the
  310. // current desktop.
  311. TEST(PolicyTargetTest, WinstaPolicy) {
  312. BrokerServices* broker = GetBroker();
  313. // Precreate the desktop.
  314. broker->CreatePolicy()->CreateAlternateDesktop(true);
  315. ASSERT_TRUE(broker);
  316. // Get the path to the sandboxed app.
  317. wchar_t prog_name[MAX_PATH];
  318. GetModuleFileNameW(nullptr, prog_name, MAX_PATH);
  319. std::wstring arguments(L"\"");
  320. arguments += prog_name;
  321. arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
  322. // Launch the app.
  323. ResultCode result = SBOX_ALL_OK;
  324. ResultCode warning_result = SBOX_ALL_OK;
  325. base::win::ScopedProcessInformation target;
  326. auto policy = broker->CreatePolicy();
  327. policy->SetAlternateDesktop(true);
  328. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  329. PROCESS_INFORMATION temp_process_info = {};
  330. DWORD last_error = ERROR_SUCCESS;
  331. // Keep the desktop name for later.
  332. std::wstring desktop_name = policy->GetAlternateDesktop();
  333. result =
  334. broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
  335. &warning_result, &last_error, &temp_process_info);
  336. EXPECT_EQ(SBOX_ALL_OK, result);
  337. if (result == SBOX_ALL_OK)
  338. target.Set(temp_process_info);
  339. EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
  340. EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
  341. ::WaitForSingleObject(target.process_handle(), 2000));
  342. EXPECT_NE(::GetThreadDesktop(target.thread_id()),
  343. ::GetThreadDesktop(::GetCurrentThreadId()));
  344. ASSERT_FALSE(desktop_name.empty());
  345. // Make sure there is a backslash, for the window station name.
  346. EXPECT_NE(desktop_name.find_first_of(L'\\'), std::wstring::npos);
  347. // Isolate the desktop name.
  348. desktop_name = desktop_name.substr(desktop_name.find_first_of(L'\\') + 1);
  349. HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, false, DESKTOP_ENUMERATE);
  350. // This should fail if the desktop is really on another window station.
  351. EXPECT_FALSE(desk);
  352. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  353. ::WaitForSingleObject(target.process_handle(), INFINITE);
  354. // Close the desktop handle.
  355. broker->CreatePolicy()->DestroyAlternateDesktop();
  356. }
  357. // Creates multiple policies, with alternate desktops on both local and
  358. // alternate winstations.
  359. TEST(PolicyTargetTest, BothLocalAndAlternateWinstationDesktop) {
  360. BrokerServices* broker = GetBroker();
  361. auto policy1 = broker->CreatePolicy();
  362. auto policy2 = broker->CreatePolicy();
  363. auto policy3 = broker->CreatePolicy();
  364. ResultCode result;
  365. result = policy1->SetAlternateDesktop(false);
  366. EXPECT_EQ(SBOX_ALL_OK, result);
  367. result = policy2->SetAlternateDesktop(true);
  368. EXPECT_EQ(SBOX_ALL_OK, result);
  369. result = policy3->SetAlternateDesktop(false);
  370. EXPECT_EQ(SBOX_ALL_OK, result);
  371. std::wstring policy1_desktop_name = policy1->GetAlternateDesktop();
  372. std::wstring policy2_desktop_name = policy2->GetAlternateDesktop();
  373. // Extract only the "desktop name" portion of
  374. // "{winstation name}\\{desktop name}"
  375. EXPECT_NE(policy1_desktop_name.substr(
  376. policy1_desktop_name.find_first_of(L'\\') + 1),
  377. policy2_desktop_name.substr(
  378. policy2_desktop_name.find_first_of(L'\\') + 1));
  379. policy1->DestroyAlternateDesktop();
  380. policy2->DestroyAlternateDesktop();
  381. policy3->DestroyAlternateDesktop();
  382. }
  383. // Launches the app in the sandbox and share a handle with it. The app should
  384. // be able to use the handle.
  385. TEST(PolicyTargetTest, ShareHandleTest) {
  386. BrokerServices* broker = GetBroker();
  387. ASSERT_TRUE(broker);
  388. base::StringPiece contents = "Hello World";
  389. base::WritableSharedMemoryRegion writable_region =
  390. base::WritableSharedMemoryRegion::Create(contents.size());
  391. ASSERT_TRUE(writable_region.IsValid());
  392. base::WritableSharedMemoryMapping writable_mapping = writable_region.Map();
  393. ASSERT_TRUE(writable_mapping.IsValid());
  394. memcpy(writable_mapping.memory(), contents.data(), contents.size());
  395. // Get the path to the sandboxed app.
  396. wchar_t prog_name[MAX_PATH];
  397. GetModuleFileNameW(nullptr, prog_name, MAX_PATH);
  398. base::ReadOnlySharedMemoryRegion read_only_region =
  399. base::WritableSharedMemoryRegion::ConvertToReadOnly(
  400. std::move(writable_region));
  401. ASSERT_TRUE(read_only_region.IsValid());
  402. auto policy = broker->CreatePolicy();
  403. policy->AddHandleToShare(read_only_region.GetPlatformHandle());
  404. std::wstring arguments(L"\"");
  405. arguments += prog_name;
  406. arguments += L"\" -child 0 shared_memory_handle ";
  407. arguments += base::AsWString(base::NumberToString16(
  408. base::win::HandleToUint32(read_only_region.GetPlatformHandle())));
  409. // Launch the app.
  410. ResultCode result = SBOX_ALL_OK;
  411. ResultCode warning_result = SBOX_ALL_OK;
  412. base::win::ScopedProcessInformation target;
  413. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  414. PROCESS_INFORMATION temp_process_info = {};
  415. DWORD last_error = ERROR_SUCCESS;
  416. result =
  417. broker->SpawnTarget(prog_name, arguments.c_str(), std::move(policy),
  418. &warning_result, &last_error, &temp_process_info);
  419. EXPECT_EQ(SBOX_ALL_OK, result);
  420. if (result == SBOX_ALL_OK)
  421. target.Set(temp_process_info);
  422. EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
  423. EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
  424. ::WaitForSingleObject(target.process_handle(), 2000));
  425. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  426. ::WaitForSingleObject(target.process_handle(), INFINITE);
  427. }
  428. // Dummy target that just reports that's it spawned correctly.
  429. SBOX_TESTS_COMMAND int PolicyTargetTest_SetEffectiveToken(int argc,
  430. wchar_t** argv) {
  431. return SBOX_TEST_SUCCEEDED;
  432. }
  433. // Test whether after using SetEffectiveToken spawning a target works as
  434. // expected.
  435. TEST(PolicyTargetTest, SetEffectiveToken) {
  436. TestRunner runner;
  437. HANDLE token;
  438. // Get current process token.
  439. EXPECT_TRUE(
  440. ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
  441. // Setup token guard.
  442. base::win::ScopedHandle token_guard(token);
  443. // Set token and run target.
  444. runner.GetPolicy()->SetEffectiveToken(token_guard.Get());
  445. EXPECT_EQ(SBOX_TEST_SUCCEEDED,
  446. runner.RunTest(L"PolicyTargetTest_SetEffectiveToken"));
  447. }
  448. // Test if shared policies can be created by the broker.
  449. TEST(SharedTargetConfig, BrokerConfigManagement) {
  450. BrokerServices* broker = GetBroker();
  451. ASSERT_TRUE(broker);
  452. // Policies with empty names should not be fixed.
  453. auto policy = broker->CreatePolicy("");
  454. EXPECT_FALSE(policy->GetConfig()->IsConfigured());
  455. // Normally a policy is frozen (if necessary) by the broker when it is passed
  456. // to SpawnTarget.
  457. BrokerServicesBase::FreezeTargetConfigForTesting(policy->GetConfig());
  458. EXPECT_TRUE(policy->GetConfig()->IsConfigured());
  459. auto policy_two = broker->CreatePolicy("");
  460. EXPECT_FALSE(policy_two->GetConfig()->IsConfigured());
  461. // Policies with no name should not be fixed.
  462. policy = broker->CreatePolicy();
  463. EXPECT_FALSE(policy->GetConfig()->IsConfigured());
  464. BrokerServicesBase::FreezeTargetConfigForTesting(policy->GetConfig());
  465. policy_two = broker->CreatePolicy();
  466. EXPECT_FALSE(policy_two->GetConfig()->IsConfigured());
  467. // Named policy should not be fixed the first time.
  468. policy = broker->CreatePolicy("key-one");
  469. EXPECT_FALSE(policy->GetConfig()->IsConfigured());
  470. BrokerServicesBase::FreezeTargetConfigForTesting(policy->GetConfig());
  471. // Policy should be fixed the second time.
  472. policy = broker->CreatePolicy("key-one");
  473. EXPECT_TRUE(policy->GetConfig()->IsConfigured());
  474. // Even if all policies with the same key are deleted.
  475. policy.reset();
  476. policy = broker->CreatePolicy("key-one");
  477. EXPECT_TRUE(policy->GetConfig()->IsConfigured());
  478. // A different name should not be fixed the first time.
  479. policy_two = broker->CreatePolicy("key-two");
  480. EXPECT_FALSE(policy_two->GetConfig()->IsConfigured());
  481. BrokerServicesBase::FreezeTargetConfigForTesting(policy_two->GetConfig());
  482. // But should be the second time.
  483. policy_two = broker->CreatePolicy("key-two");
  484. EXPECT_TRUE(policy_two->GetConfig()->IsConfigured());
  485. }
  486. } // namespace sandbox