123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // Copyright (c) 2011 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "sandbox/win/src/handle_closer.h"
- #include <stddef.h>
- #include <memory>
- #include "base/check_op.h"
- #include "base/memory/free_deleter.h"
- #include "base/win/windows_version.h"
- #include "sandbox/win/src/win_utils.h"
- namespace {
- template <typename T>
- T RoundUpToWordSize(T v) {
- if (size_t mod = v % sizeof(size_t))
- v += sizeof(size_t) - mod;
- return v;
- }
- template <typename T>
- T* RoundUpToWordSize(T* v) {
- return reinterpret_cast<T*>(RoundUpToWordSize(reinterpret_cast<size_t>(v)));
- }
- } // namespace
- namespace sandbox {
- // Memory buffer mapped from the parent, with the list of handles.
- SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close;
- HandleCloser::HandleCloser() {}
- HandleCloser::~HandleCloser() {}
- ResultCode HandleCloser::AddHandle(const wchar_t* handle_type,
- const wchar_t* handle_name) {
- if (!handle_type)
- return SBOX_ERROR_BAD_PARAMS;
- std::wstring resolved_name;
- if (handle_name) {
- resolved_name = handle_name;
- if (handle_type == std::wstring(L"Key"))
- if (!ResolveRegistryName(resolved_name, &resolved_name))
- return SBOX_ERROR_BAD_PARAMS;
- }
- HandleMap::iterator names = handles_to_close_.find(handle_type);
- if (names == handles_to_close_.end()) { // We have no entries for this type.
- std::pair<HandleMap::iterator, bool> result = handles_to_close_.insert(
- HandleMap::value_type(handle_type, HandleMap::mapped_type()));
- names = result.first;
- if (handle_name)
- names->second.insert(resolved_name);
- } else if (!handle_name) { // Now we need to close all handles of this type.
- names->second.clear();
- } else if (!names->second.empty()) { // Add another name for this type.
- names->second.insert(resolved_name);
- } // If we're already closing all handles of type then we're done.
- return SBOX_ALL_OK;
- }
- size_t HandleCloser::GetBufferSize() {
- size_t bytes_total = offsetof(HandleCloserInfo, handle_entries);
- for (HandleMap::iterator i = handles_to_close_.begin();
- i != handles_to_close_.end(); ++i) {
- size_t bytes_entry = offsetof(HandleListEntry, handle_type) +
- (i->first.size() + 1) * sizeof(wchar_t);
- for (HandleMap::mapped_type::iterator j = i->second.begin();
- j != i->second.end(); ++j) {
- bytes_entry += ((*j).size() + 1) * sizeof(wchar_t);
- }
- // Round up to the nearest multiple of word size.
- bytes_entry = RoundUpToWordSize(bytes_entry);
- bytes_total += bytes_entry;
- }
- return bytes_total;
- }
- bool HandleCloser::InitializeTargetHandles(TargetProcess& target) {
- // Do nothing on an empty list (global pointer already initialized to
- // nullptr).
- if (handles_to_close_.empty())
- return true;
- size_t bytes_needed = GetBufferSize();
- std::unique_ptr<size_t[]> local_buffer(
- new size_t[bytes_needed / sizeof(size_t)]);
- if (!SetupHandleList(local_buffer.get(), bytes_needed))
- return false;
- void* remote_data;
- if (!CopyToChildMemory(target.Process(), local_buffer.get(), bytes_needed,
- &remote_data))
- return false;
- g_handles_to_close = reinterpret_cast<HandleCloserInfo*>(remote_data);
- ResultCode rc = target.TransferVariable(
- "g_handles_to_close", &g_handles_to_close, sizeof(g_handles_to_close));
- return (SBOX_ALL_OK == rc);
- }
- bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) {
- ::ZeroMemory(buffer, buffer_bytes);
- HandleCloserInfo* handle_info = reinterpret_cast<HandleCloserInfo*>(buffer);
- handle_info->record_bytes = buffer_bytes;
- handle_info->num_handle_types = handles_to_close_.size();
- wchar_t* output = reinterpret_cast<wchar_t*>(&handle_info->handle_entries[0]);
- wchar_t* end = reinterpret_cast<wchar_t*>(reinterpret_cast<char*>(buffer) +
- buffer_bytes);
- for (HandleMap::iterator i = handles_to_close_.begin();
- i != handles_to_close_.end(); ++i) {
- if (output >= end)
- return false;
- HandleListEntry* list_entry = reinterpret_cast<HandleListEntry*>(output);
- output = &list_entry->handle_type[0];
- // Copy the typename and set the offset and count.
- i->first.copy(output, i->first.size());
- *(output += i->first.size()) = L'\0';
- output++;
- list_entry->offset_to_names =
- reinterpret_cast<char*>(output) - reinterpret_cast<char*>(list_entry);
- list_entry->name_count = i->second.size();
- // Copy the handle names.
- for (HandleMap::mapped_type::iterator j = i->second.begin();
- j != i->second.end(); ++j) {
- output = std::copy((*j).begin(), (*j).end(), output) + 1;
- }
- // Round up to the nearest multiple of sizeof(size_t).
- output = RoundUpToWordSize(output);
- list_entry->record_bytes =
- reinterpret_cast<char*>(output) - reinterpret_cast<char*>(list_entry);
- }
- DCHECK_EQ(reinterpret_cast<size_t>(output), reinterpret_cast<size_t>(end));
- return output <= end;
- }
- } // namespace sandbox
|