PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/sandbox/win/src/policy_target_test.cc

https://gitlab.com/jonnialva90/iridium-browser
C++ | 412 lines | 281 code | 81 blank | 50 comment | 37 complexity | c3f3f657cea9e780752e0d1aa31712de MD5 | raw file
  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/shared_memory.h"
  5. #include "base/strings/string_number_conversions.h"
  6. #include "base/strings/string_piece.h"
  7. #include "base/win/scoped_process_information.h"
  8. #include "base/win/windows_version.h"
  9. #include "sandbox/win/src/sandbox.h"
  10. #include "sandbox/win/src/sandbox_factory.h"
  11. #include "sandbox/win/src/sandbox_utils.h"
  12. #include "sandbox/win/src/target_services.h"
  13. #include "sandbox/win/tests/common/controller.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. namespace sandbox {
  16. #define BINDNTDLL(name) \
  17. name ## Function name = reinterpret_cast<name ## Function>( \
  18. ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
  19. // Reverts to self and verify that SetInformationToken was faked. Returns
  20. // SBOX_TEST_SUCCEEDED if faked and SBOX_TEST_FAILED if not faked.
  21. SBOX_TESTS_COMMAND int PolicyTargetTest_token(int argc, wchar_t **argv) {
  22. HANDLE thread_token;
  23. // Get the thread token, using impersonation.
  24. if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
  25. TOKEN_DUPLICATE, FALSE, &thread_token))
  26. return ::GetLastError();
  27. ::RevertToSelf();
  28. ::CloseHandle(thread_token);
  29. int ret = SBOX_TEST_FAILED;
  30. if (::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  31. FALSE, &thread_token)) {
  32. ret = SBOX_TEST_SUCCEEDED;
  33. ::CloseHandle(thread_token);
  34. }
  35. return ret;
  36. }
  37. // Stores the high privilege token on a static variable, change impersonation
  38. // again to that one and verify that we are not interfering anymore with
  39. // RevertToSelf.
  40. SBOX_TESTS_COMMAND int PolicyTargetTest_steal(int argc, wchar_t **argv) {
  41. static HANDLE thread_token;
  42. if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
  43. if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
  44. TOKEN_DUPLICATE, FALSE, &thread_token))
  45. return ::GetLastError();
  46. } else {
  47. if (!::SetThreadToken(NULL, thread_token))
  48. return ::GetLastError();
  49. // See if we fake the call again.
  50. int ret = PolicyTargetTest_token(argc, argv);
  51. ::CloseHandle(thread_token);
  52. return ret;
  53. }
  54. return 0;
  55. }
  56. // Opens the thread token with and without impersonation.
  57. SBOX_TESTS_COMMAND int PolicyTargetTest_token2(int argc, wchar_t **argv) {
  58. HANDLE thread_token;
  59. // Get the thread token, using impersonation.
  60. if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
  61. TOKEN_DUPLICATE, FALSE, &thread_token))
  62. return ::GetLastError();
  63. ::CloseHandle(thread_token);
  64. // Get the thread token, without impersonation.
  65. if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  66. TRUE, &thread_token))
  67. return ::GetLastError();
  68. ::CloseHandle(thread_token);
  69. return SBOX_TEST_SUCCEEDED;
  70. }
  71. // Opens the thread token with and without impersonation, using
  72. // NtOpenThreadTokenEX.
  73. SBOX_TESTS_COMMAND int PolicyTargetTest_token3(int argc, wchar_t **argv) {
  74. BINDNTDLL(NtOpenThreadTokenEx);
  75. if (!NtOpenThreadTokenEx)
  76. return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
  77. HANDLE thread_token;
  78. // Get the thread token, using impersonation.
  79. NTSTATUS status = NtOpenThreadTokenEx(GetCurrentThread(),
  80. TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  81. FALSE, 0, &thread_token);
  82. if (status == STATUS_NO_TOKEN)
  83. return ERROR_NO_TOKEN;
  84. if (!NT_SUCCESS(status))
  85. return SBOX_TEST_FAILED;
  86. ::CloseHandle(thread_token);
  87. // Get the thread token, without impersonation.
  88. status = NtOpenThreadTokenEx(GetCurrentThread(),
  89. TOKEN_IMPERSONATE | TOKEN_DUPLICATE, TRUE, 0,
  90. &thread_token);
  91. if (!NT_SUCCESS(status))
  92. return SBOX_TEST_FAILED;
  93. ::CloseHandle(thread_token);
  94. return SBOX_TEST_SUCCEEDED;
  95. }
  96. // Tests that we can open the current thread.
  97. SBOX_TESTS_COMMAND int PolicyTargetTest_thread(int argc, wchar_t **argv) {
  98. DWORD thread_id = ::GetCurrentThreadId();
  99. HANDLE thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id);
  100. if (!thread)
  101. return ::GetLastError();
  102. if (!::CloseHandle(thread))
  103. return ::GetLastError();
  104. return SBOX_TEST_SUCCEEDED;
  105. }
  106. // New thread entry point: do nothing.
  107. DWORD WINAPI PolicyTargetTest_thread_main(void* param) {
  108. ::Sleep(INFINITE);
  109. return 0;
  110. }
  111. // Tests that we can create a new thread, and open it.
  112. SBOX_TESTS_COMMAND int PolicyTargetTest_thread2(int argc, wchar_t **argv) {
  113. // Use default values to create a new thread.
  114. DWORD thread_id;
  115. HANDLE thread = ::CreateThread(NULL, 0, &PolicyTargetTest_thread_main, 0, 0,
  116. &thread_id);
  117. if (!thread)
  118. return ::GetLastError();
  119. if (!::CloseHandle(thread))
  120. return ::GetLastError();
  121. thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id);
  122. if (!thread)
  123. return ::GetLastError();
  124. if (!::CloseHandle(thread))
  125. return ::GetLastError();
  126. return SBOX_TEST_SUCCEEDED;
  127. }
  128. // Tests that we can call CreateProcess.
  129. SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t **argv) {
  130. // Use default values to create a new process.
  131. STARTUPINFO startup_info = {0};
  132. startup_info.cb = sizeof(startup_info);
  133. PROCESS_INFORMATION temp_process_info = {};
  134. // Note: CreateProcessW() can write to its lpCommandLine, don't pass a
  135. // raw string literal.
  136. base::string16 writable_cmdline_str(L"foo.exe");
  137. if (!::CreateProcessW(L"foo.exe", &writable_cmdline_str[0], NULL, NULL, FALSE,
  138. 0, NULL, NULL, &startup_info, &temp_process_info))
  139. return SBOX_TEST_SUCCEEDED;
  140. base::win::ScopedProcessInformation process_info(temp_process_info);
  141. return SBOX_TEST_FAILED;
  142. }
  143. TEST(PolicyTargetTest, SetInformationThread) {
  144. TestRunner runner;
  145. if (base::win::GetVersion() >= base::win::VERSION_XP) {
  146. runner.SetTestState(BEFORE_REVERT);
  147. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
  148. }
  149. runner.SetTestState(AFTER_REVERT);
  150. EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token"));
  151. runner.SetTestState(EVERY_STATE);
  152. if (base::win::GetVersion() >= base::win::VERSION_XP)
  153. EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"PolicyTargetTest_steal"));
  154. }
  155. TEST(PolicyTargetTest, OpenThreadToken) {
  156. TestRunner runner;
  157. if (base::win::GetVersion() >= base::win::VERSION_XP) {
  158. runner.SetTestState(BEFORE_REVERT);
  159. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
  160. }
  161. runner.SetTestState(AFTER_REVERT);
  162. EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token2"));
  163. }
  164. TEST(PolicyTargetTest, OpenThreadTokenEx) {
  165. TestRunner runner;
  166. if (base::win::GetVersion() < base::win::VERSION_XP)
  167. return;
  168. runner.SetTestState(BEFORE_REVERT);
  169. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
  170. runner.SetTestState(AFTER_REVERT);
  171. EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3"));
  172. }
  173. TEST(PolicyTargetTest, OpenThread) {
  174. TestRunner runner;
  175. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread")) <<
  176. "Opens the current thread";
  177. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread2")) <<
  178. "Creates a new thread and opens it";
  179. }
  180. TEST(PolicyTargetTest, OpenProcess) {
  181. TestRunner runner;
  182. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_process")) <<
  183. "Opens a process";
  184. }
  185. // Launches the app in the sandbox and ask it to wait in an
  186. // infinite loop. Waits for 2 seconds and then check if the
  187. // desktop associated with the app thread is not the same as the
  188. // current desktop.
  189. TEST(PolicyTargetTest, DesktopPolicy) {
  190. BrokerServices* broker = GetBroker();
  191. // Precreate the desktop.
  192. TargetPolicy* temp_policy = broker->CreatePolicy();
  193. temp_policy->CreateAlternateDesktop(false);
  194. temp_policy->Release();
  195. ASSERT_TRUE(broker != NULL);
  196. // Get the path to the sandboxed app.
  197. wchar_t prog_name[MAX_PATH];
  198. GetModuleFileNameW(NULL, prog_name, MAX_PATH);
  199. base::string16 arguments(L"\"");
  200. arguments += prog_name;
  201. arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
  202. // Launch the app.
  203. ResultCode result = SBOX_ALL_OK;
  204. base::win::ScopedProcessInformation target;
  205. TargetPolicy* policy = broker->CreatePolicy();
  206. policy->SetAlternateDesktop(false);
  207. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  208. PROCESS_INFORMATION temp_process_info = {};
  209. result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
  210. &temp_process_info);
  211. base::string16 desktop_name = policy->GetAlternateDesktop();
  212. policy->Release();
  213. EXPECT_EQ(SBOX_ALL_OK, result);
  214. if (result == SBOX_ALL_OK)
  215. target.Set(temp_process_info);
  216. EXPECT_EQ(1, ::ResumeThread(target.thread_handle()));
  217. EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(target.process_handle(), 2000));
  218. EXPECT_NE(::GetThreadDesktop(target.thread_id()),
  219. ::GetThreadDesktop(::GetCurrentThreadId()));
  220. HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
  221. EXPECT_TRUE(NULL != desk);
  222. EXPECT_TRUE(::CloseDesktop(desk));
  223. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  224. ::WaitForSingleObject(target.process_handle(), INFINITE);
  225. // Close the desktop handle.
  226. temp_policy = broker->CreatePolicy();
  227. temp_policy->DestroyAlternateDesktop();
  228. temp_policy->Release();
  229. // Make sure the desktop does not exist anymore.
  230. desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
  231. EXPECT_TRUE(NULL == desk);
  232. }
  233. // Launches the app in the sandbox and ask it to wait in an
  234. // infinite loop. Waits for 2 seconds and then check if the
  235. // winstation associated with the app thread is not the same as the
  236. // current desktop.
  237. TEST(PolicyTargetTest, WinstaPolicy) {
  238. BrokerServices* broker = GetBroker();
  239. // Precreate the desktop.
  240. TargetPolicy* temp_policy = broker->CreatePolicy();
  241. temp_policy->CreateAlternateDesktop(true);
  242. temp_policy->Release();
  243. ASSERT_TRUE(broker != NULL);
  244. // Get the path to the sandboxed app.
  245. wchar_t prog_name[MAX_PATH];
  246. GetModuleFileNameW(NULL, prog_name, MAX_PATH);
  247. base::string16 arguments(L"\"");
  248. arguments += prog_name;
  249. arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
  250. // Launch the app.
  251. ResultCode result = SBOX_ALL_OK;
  252. base::win::ScopedProcessInformation target;
  253. TargetPolicy* policy = broker->CreatePolicy();
  254. policy->SetAlternateDesktop(true);
  255. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  256. PROCESS_INFORMATION temp_process_info = {};
  257. result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
  258. &temp_process_info);
  259. base::string16 desktop_name = policy->GetAlternateDesktop();
  260. policy->Release();
  261. EXPECT_EQ(SBOX_ALL_OK, result);
  262. if (result == SBOX_ALL_OK)
  263. target.Set(temp_process_info);
  264. EXPECT_EQ(1, ::ResumeThread(target.thread_handle()));
  265. EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(target.process_handle(), 2000));
  266. EXPECT_NE(::GetThreadDesktop(target.thread_id()),
  267. ::GetThreadDesktop(::GetCurrentThreadId()));
  268. ASSERT_FALSE(desktop_name.empty());
  269. // Make sure there is a backslash, for the window station name.
  270. EXPECT_NE(desktop_name.find_first_of(L'\\'), base::string16::npos);
  271. // Isolate the desktop name.
  272. desktop_name = desktop_name.substr(desktop_name.find_first_of(L'\\') + 1);
  273. HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
  274. // This should fail if the desktop is really on another window station.
  275. EXPECT_FALSE(NULL != desk);
  276. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  277. ::WaitForSingleObject(target.process_handle(), INFINITE);
  278. // Close the desktop handle.
  279. temp_policy = broker->CreatePolicy();
  280. temp_policy->DestroyAlternateDesktop();
  281. temp_policy->Release();
  282. }
  283. // Launches the app in the sandbox and share a handle with it. The app should
  284. // be able to use the handle.
  285. TEST(PolicyTargetTest, ShareHandleTest) {
  286. // The way we share handles via STARTUPINFOEX does not work on XP.
  287. if (base::win::GetVersion() < base::win::VERSION_VISTA)
  288. return;
  289. BrokerServices* broker = GetBroker();
  290. ASSERT_TRUE(broker != NULL);
  291. base::StringPiece contents = "Hello World";
  292. std::string name = "TestSharedMemory";
  293. base::SharedMemoryCreateOptions options;
  294. options.size = contents.size();
  295. options.share_read_only = true;
  296. options.name_deprecated = &name;
  297. base::SharedMemory writable_shmem;
  298. ASSERT_TRUE(writable_shmem.Create(options));
  299. ASSERT_TRUE(writable_shmem.Map(options.size));
  300. memcpy(writable_shmem.memory(), contents.data(), contents.size());
  301. base::SharedMemory read_only_view;
  302. ASSERT_TRUE(read_only_view.Open(name, true));
  303. // Get the path to the sandboxed app.
  304. wchar_t prog_name[MAX_PATH];
  305. GetModuleFileNameW(NULL, prog_name, MAX_PATH);
  306. TargetPolicy* policy = broker->CreatePolicy();
  307. void* shared_handle =
  308. policy->AddHandleToShare(read_only_view.handle().GetHandle());
  309. base::string16 arguments(L"\"");
  310. arguments += prog_name;
  311. arguments += L"\" -child 0 shared_memory_handle ";
  312. arguments += base::UintToString16(
  313. reinterpret_cast<unsigned int>(shared_handle));
  314. // Launch the app.
  315. ResultCode result = SBOX_ALL_OK;
  316. base::win::ScopedProcessInformation target;
  317. policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
  318. PROCESS_INFORMATION temp_process_info = {};
  319. result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
  320. &temp_process_info);
  321. policy->Release();
  322. EXPECT_EQ(SBOX_ALL_OK, result);
  323. if (result == SBOX_ALL_OK)
  324. target.Set(temp_process_info);
  325. EXPECT_EQ(1, ::ResumeThread(target.thread_handle()));
  326. EXPECT_EQ(WAIT_TIMEOUT,
  327. ::WaitForSingleObject(target.process_handle(), 2000));
  328. EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
  329. ::WaitForSingleObject(target.process_handle(), INFINITE);
  330. }
  331. } // namespace sandbox