handle_closer_test.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Copyright (c) 2011 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 <limits.h>
  5. #include <stddef.h>
  6. #include "base/strings/string_util_win.h"
  7. #include "base/strings/stringprintf.h"
  8. #include "base/win/scoped_handle.h"
  9. #include "sandbox/win/src/handle_closer_agent.h"
  10. #include "sandbox/win/src/nt_internals.h"
  11. #include "sandbox/win/src/sandbox.h"
  12. #include "sandbox/win/src/sandbox_factory.h"
  13. #include "sandbox/win/src/target_services.h"
  14. #include "sandbox/win/src/win_utils.h"
  15. #include "sandbox/win/tests/common/controller.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace {
  18. const wchar_t* kFileExtensions[] = {L".1", L".2", L".3", L".4"};
  19. // Returns a handle to a unique marker file that can be retrieved between runs.
  20. HANDLE GetMarkerFile(const wchar_t* extension) {
  21. wchar_t path_buffer[MAX_PATH + 1];
  22. CHECK(::GetTempPath(MAX_PATH, path_buffer));
  23. std::wstring marker_path = path_buffer;
  24. marker_path += L"\\sbox_marker_";
  25. // Generate a unique value from the exe's size and timestamp.
  26. CHECK(::GetModuleFileName(nullptr, path_buffer, MAX_PATH));
  27. base::win::ScopedHandle module(
  28. ::CreateFile(path_buffer, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr,
  29. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
  30. CHECK(module.IsValid());
  31. FILETIME timestamp;
  32. CHECK(::GetFileTime(module.Get(), &timestamp, nullptr, nullptr));
  33. marker_path +=
  34. base::StringPrintf(L"%08x%08x%08x", ::GetFileSize(module.Get(), nullptr),
  35. timestamp.dwLowDateTime, timestamp.dwHighDateTime);
  36. marker_path += extension;
  37. // Make the file delete-on-close so cleanup is automatic.
  38. return CreateFile(marker_path.c_str(), FILE_ALL_ACCESS,
  39. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  40. nullptr, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, nullptr);
  41. }
  42. // Used by the thread pool tests.
  43. HANDLE finish_event;
  44. const int kWaitCount = 20;
  45. } // namespace
  46. namespace sandbox {
  47. // Checks for the presence of a list of files (in object path form).
  48. // Format: CheckForFileHandle (Y|N) \path\to\file1 [\path\to\file2 ...]
  49. // - Y or N depending if the file should exist or not.
  50. SBOX_TESTS_COMMAND int CheckForFileHandles(int argc, wchar_t** argv) {
  51. if (argc < 2)
  52. return SBOX_TEST_FAILED_TO_RUN_TEST;
  53. bool should_find = argv[0][0] == L'Y';
  54. if (argv[0][1] != L'\0' || (!should_find && argv[0][0] != L'N'))
  55. return SBOX_TEST_FAILED_TO_RUN_TEST;
  56. static int state = BEFORE_INIT;
  57. switch (state++) {
  58. case BEFORE_INIT:
  59. // Create a unique marker file that is open while the test is running.
  60. // The handles leak, but it will be closed by the test or on exit.
  61. for (const wchar_t* kExtension : kFileExtensions)
  62. CHECK_NE(GetMarkerFile(kExtension), INVALID_HANDLE_VALUE);
  63. return SBOX_TEST_SUCCEEDED;
  64. case AFTER_REVERT: {
  65. // Brute force the handle table to find what we're looking for.
  66. DWORD handle_count = UINT_MAX;
  67. const int kInvalidHandleThreshold = 100;
  68. const size_t kHandleOffset = 4; // Handles are always a multiple of 4.
  69. HANDLE handle = nullptr;
  70. int invalid_count = 0;
  71. std::wstring handle_name;
  72. if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
  73. return SBOX_TEST_FAILED_TO_RUN_TEST;
  74. while (handle_count && invalid_count < kInvalidHandleThreshold) {
  75. reinterpret_cast<size_t&>(handle) += kHandleOffset;
  76. if (GetPathFromHandle(handle, &handle_name)) {
  77. for (int i = 1; i < argc; ++i) {
  78. if (handle_name == argv[i])
  79. return should_find ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED;
  80. }
  81. --handle_count;
  82. } else {
  83. ++invalid_count;
  84. }
  85. }
  86. return should_find ? SBOX_TEST_FAILED : SBOX_TEST_SUCCEEDED;
  87. }
  88. default: // Do nothing.
  89. break;
  90. }
  91. return SBOX_TEST_SUCCEEDED;
  92. }
  93. // Checks that supplied handle is an Event and it's not waitable.
  94. // Format: CheckForEventHandles
  95. SBOX_TESTS_COMMAND int CheckForEventHandles(int argc, wchar_t** argv) {
  96. static int state = BEFORE_INIT;
  97. static std::vector<HANDLE> to_check;
  98. switch (state++) {
  99. case BEFORE_INIT:
  100. // Create a unique marker file that is open while the test is running.
  101. for (const wchar_t* kExtension : kFileExtensions) {
  102. HANDLE handle = GetMarkerFile(kExtension);
  103. CHECK_NE(handle, INVALID_HANDLE_VALUE);
  104. to_check.push_back(handle);
  105. }
  106. return SBOX_TEST_SUCCEEDED;
  107. case AFTER_REVERT:
  108. for (HANDLE handle : to_check) {
  109. std::wstring type_name;
  110. CHECK(GetTypeNameFromHandle(handle, &type_name));
  111. CHECK(base::EqualsCaseInsensitiveASCII(type_name, L"Event"));
  112. // Should not be able to wait.
  113. CHECK_EQ(WaitForSingleObject(handle, INFINITE), WAIT_FAILED);
  114. // Should be able to close.
  115. CHECK(::CloseHandle(handle));
  116. }
  117. return SBOX_TEST_SUCCEEDED;
  118. default: // Do nothing.
  119. break;
  120. }
  121. return SBOX_TEST_SUCCEEDED;
  122. }
  123. TEST(HandleCloserTest, CheckForMarkerFiles) {
  124. TestRunner runner;
  125. runner.SetTimeout(2000);
  126. runner.SetTestState(EVERY_STATE);
  127. std::wstring command = std::wstring(L"CheckForFileHandles Y");
  128. for (const wchar_t* kExtension : kFileExtensions) {
  129. std::wstring handle_name;
  130. base::win::ScopedHandle marker(GetMarkerFile(kExtension));
  131. CHECK(marker.IsValid());
  132. CHECK(GetPathFromHandle(marker.Get(), &handle_name));
  133. command += (L" ");
  134. command += handle_name;
  135. }
  136. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command.c_str()))
  137. << "Failed: " << command;
  138. }
  139. TEST(HandleCloserTest, CloseMarkerFiles) {
  140. TestRunner runner;
  141. runner.SetTimeout(2000);
  142. runner.SetTestState(EVERY_STATE);
  143. sandbox::TargetPolicy* policy = runner.GetPolicy();
  144. std::wstring command = std::wstring(L"CheckForFileHandles N");
  145. for (const wchar_t* kExtension : kFileExtensions) {
  146. std::wstring handle_name;
  147. base::win::ScopedHandle marker(GetMarkerFile(kExtension));
  148. CHECK(marker.IsValid());
  149. CHECK(GetPathFromHandle(marker.Get(), &handle_name));
  150. CHECK_EQ(policy->AddKernelObjectToClose(L"File", handle_name.c_str()),
  151. SBOX_ALL_OK);
  152. command += (L" ");
  153. command += handle_name;
  154. }
  155. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command.c_str()))
  156. << "Failed: " << command;
  157. }
  158. TEST(HandleCloserTest, CheckStuffedHandle) {
  159. TestRunner runner;
  160. runner.SetTimeout(2000);
  161. runner.SetTestState(EVERY_STATE);
  162. sandbox::TargetPolicy* policy = runner.GetPolicy();
  163. for (const wchar_t* kExtension : kFileExtensions) {
  164. std::wstring handle_name;
  165. base::win::ScopedHandle marker(GetMarkerFile(kExtension));
  166. CHECK(marker.IsValid());
  167. CHECK(GetPathFromHandle(marker.Get(), &handle_name));
  168. CHECK_EQ(policy->AddKernelObjectToClose(L"File", handle_name.c_str()),
  169. SBOX_ALL_OK);
  170. }
  171. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckForEventHandles"));
  172. }
  173. void WINAPI ThreadPoolTask(void* event, BOOLEAN timeout) {
  174. static volatile LONG waiters_remaining = kWaitCount;
  175. CHECK(!timeout);
  176. CHECK(::CloseHandle(event));
  177. if (::InterlockedDecrement(&waiters_remaining) == 0)
  178. CHECK(::SetEvent(finish_event));
  179. }
  180. // Run a thread pool inside a sandbox without a CSRSS connection.
  181. SBOX_TESTS_COMMAND int RunThreadPool(int argc, wchar_t** argv) {
  182. HANDLE wait_list[20];
  183. finish_event = ::CreateEvent(nullptr, true, false, nullptr);
  184. CHECK(finish_event);
  185. // Set up a bunch of waiters.
  186. HANDLE pool = nullptr;
  187. for (int i = 0; i < kWaitCount; ++i) {
  188. HANDLE event = ::CreateEvent(nullptr, true, false, nullptr);
  189. CHECK(event);
  190. CHECK(::RegisterWaitForSingleObject(&pool, event, ThreadPoolTask, event,
  191. INFINITE, WT_EXECUTEONLYONCE));
  192. wait_list[i] = event;
  193. }
  194. // Signal all the waiters.
  195. for (int i = 0; i < kWaitCount; ++i)
  196. CHECK(::SetEvent(wait_list[i]));
  197. CHECK_EQ(::WaitForSingleObject(finish_event, INFINITE), WAIT_OBJECT_0);
  198. CHECK(::CloseHandle(finish_event));
  199. return SBOX_TEST_SUCCEEDED;
  200. }
  201. TEST(HandleCloserTest, RunThreadPool) {
  202. TestRunner runner;
  203. runner.SetTimeout(2000);
  204. runner.SetTestState(AFTER_REVERT);
  205. // Sandbox policy will determine which platforms to disconnect CSRSS and when
  206. // to close the CSRSS handle.
  207. EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"RunThreadPool"));
  208. }
  209. } // namespace sandbox