handle_closer.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 "sandbox/win/src/handle_closer.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include "base/check_op.h"
  8. #include "base/memory/free_deleter.h"
  9. #include "base/win/windows_version.h"
  10. #include "sandbox/win/src/win_utils.h"
  11. namespace {
  12. template <typename T>
  13. T RoundUpToWordSize(T v) {
  14. if (size_t mod = v % sizeof(size_t))
  15. v += sizeof(size_t) - mod;
  16. return v;
  17. }
  18. template <typename T>
  19. T* RoundUpToWordSize(T* v) {
  20. return reinterpret_cast<T*>(RoundUpToWordSize(reinterpret_cast<size_t>(v)));
  21. }
  22. } // namespace
  23. namespace sandbox {
  24. // Memory buffer mapped from the parent, with the list of handles.
  25. SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close;
  26. HandleCloser::HandleCloser() {}
  27. HandleCloser::~HandleCloser() {}
  28. ResultCode HandleCloser::AddHandle(const wchar_t* handle_type,
  29. const wchar_t* handle_name) {
  30. if (!handle_type)
  31. return SBOX_ERROR_BAD_PARAMS;
  32. std::wstring resolved_name;
  33. if (handle_name) {
  34. resolved_name = handle_name;
  35. if (handle_type == std::wstring(L"Key"))
  36. if (!ResolveRegistryName(resolved_name, &resolved_name))
  37. return SBOX_ERROR_BAD_PARAMS;
  38. }
  39. HandleMap::iterator names = handles_to_close_.find(handle_type);
  40. if (names == handles_to_close_.end()) { // We have no entries for this type.
  41. std::pair<HandleMap::iterator, bool> result = handles_to_close_.insert(
  42. HandleMap::value_type(handle_type, HandleMap::mapped_type()));
  43. names = result.first;
  44. if (handle_name)
  45. names->second.insert(resolved_name);
  46. } else if (!handle_name) { // Now we need to close all handles of this type.
  47. names->second.clear();
  48. } else if (!names->second.empty()) { // Add another name for this type.
  49. names->second.insert(resolved_name);
  50. } // If we're already closing all handles of type then we're done.
  51. return SBOX_ALL_OK;
  52. }
  53. size_t HandleCloser::GetBufferSize() {
  54. size_t bytes_total = offsetof(HandleCloserInfo, handle_entries);
  55. for (HandleMap::iterator i = handles_to_close_.begin();
  56. i != handles_to_close_.end(); ++i) {
  57. size_t bytes_entry = offsetof(HandleListEntry, handle_type) +
  58. (i->first.size() + 1) * sizeof(wchar_t);
  59. for (HandleMap::mapped_type::iterator j = i->second.begin();
  60. j != i->second.end(); ++j) {
  61. bytes_entry += ((*j).size() + 1) * sizeof(wchar_t);
  62. }
  63. // Round up to the nearest multiple of word size.
  64. bytes_entry = RoundUpToWordSize(bytes_entry);
  65. bytes_total += bytes_entry;
  66. }
  67. return bytes_total;
  68. }
  69. bool HandleCloser::InitializeTargetHandles(TargetProcess& target) {
  70. // Do nothing on an empty list (global pointer already initialized to
  71. // nullptr).
  72. if (handles_to_close_.empty())
  73. return true;
  74. size_t bytes_needed = GetBufferSize();
  75. std::unique_ptr<size_t[]> local_buffer(
  76. new size_t[bytes_needed / sizeof(size_t)]);
  77. if (!SetupHandleList(local_buffer.get(), bytes_needed))
  78. return false;
  79. void* remote_data;
  80. if (!CopyToChildMemory(target.Process(), local_buffer.get(), bytes_needed,
  81. &remote_data))
  82. return false;
  83. g_handles_to_close = reinterpret_cast<HandleCloserInfo*>(remote_data);
  84. ResultCode rc = target.TransferVariable(
  85. "g_handles_to_close", &g_handles_to_close, sizeof(g_handles_to_close));
  86. return (SBOX_ALL_OK == rc);
  87. }
  88. bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) {
  89. ::ZeroMemory(buffer, buffer_bytes);
  90. HandleCloserInfo* handle_info = reinterpret_cast<HandleCloserInfo*>(buffer);
  91. handle_info->record_bytes = buffer_bytes;
  92. handle_info->num_handle_types = handles_to_close_.size();
  93. wchar_t* output = reinterpret_cast<wchar_t*>(&handle_info->handle_entries[0]);
  94. wchar_t* end = reinterpret_cast<wchar_t*>(reinterpret_cast<char*>(buffer) +
  95. buffer_bytes);
  96. for (HandleMap::iterator i = handles_to_close_.begin();
  97. i != handles_to_close_.end(); ++i) {
  98. if (output >= end)
  99. return false;
  100. HandleListEntry* list_entry = reinterpret_cast<HandleListEntry*>(output);
  101. output = &list_entry->handle_type[0];
  102. // Copy the typename and set the offset and count.
  103. i->first.copy(output, i->first.size());
  104. *(output += i->first.size()) = L'\0';
  105. output++;
  106. list_entry->offset_to_names =
  107. reinterpret_cast<char*>(output) - reinterpret_cast<char*>(list_entry);
  108. list_entry->name_count = i->second.size();
  109. // Copy the handle names.
  110. for (HandleMap::mapped_type::iterator j = i->second.begin();
  111. j != i->second.end(); ++j) {
  112. output = std::copy((*j).begin(), (*j).end(), output) + 1;
  113. }
  114. // Round up to the nearest multiple of sizeof(size_t).
  115. output = RoundUpToWordSize(output);
  116. list_entry->record_bytes =
  117. reinterpret_cast<char*>(output) - reinterpret_cast<char*>(list_entry);
  118. }
  119. DCHECK_EQ(reinterpret_cast<size_t>(output), reinterpret_cast<size_t>(end));
  120. return output <= end;
  121. }
  122. } // namespace sandbox