security/sandbox/win/src/handle_closer.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
     5 #include "sandbox/win/src/handle_closer.h"
     7 #include "base/logging.h"
     8 #include "base/memory/scoped_ptr.h"
     9 #include "base/win/windows_version.h"
    10 #include "sandbox/win/src/interceptors.h"
    11 #include "sandbox/win/src/internal_types.h"
    12 #include "sandbox/win/src/nt_internals.h"
    13 #include "sandbox/win/src/process_thread_interception.h"
    14 #include "sandbox/win/src/win_utils.h"
    16 namespace {
    18 template<typename T> T RoundUpToWordSize(T v) {
    19   if (size_t mod = v % sizeof(size_t))
    20     v += sizeof(size_t) - mod;
    21   return v;
    22 }
    24 template<typename T> T* RoundUpToWordSize(T* v) {
    25   return reinterpret_cast<T*>(RoundUpToWordSize(reinterpret_cast<size_t>(v)));
    26 }
    28 }  // namespace
    30 namespace sandbox {
    32 // Memory buffer mapped from the parent, with the list of handles.
    33 SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close;
    35 HandleCloser::HandleCloser() {}
    37 ResultCode HandleCloser::AddHandle(const char16* handle_type,
    38                                    const char16* handle_name) {
    39   if (!handle_type)
    40     return SBOX_ERROR_BAD_PARAMS;
    42   HandleMap::iterator names = handles_to_close_.find(handle_type);
    43   if (names == handles_to_close_.end()) {  // We have no entries for this type.
    44     std::pair<HandleMap::iterator, bool> result = handles_to_close_.insert(
    45         HandleMap::value_type(handle_type, HandleMap::mapped_type()));
    46     names = result.first;
    47     if (handle_name)
    48       names->second.insert(handle_name);
    49   } else if (!handle_name) {  // Now we need to close all handles of this type.
    50     names->second.clear();
    51   } else if (!names->second.empty()) {  // Add another name for this type.
    52     names->second.insert(handle_name);
    53   }  // If we're already closing all handles of type then we're done.
    55   return SBOX_ALL_OK;
    56 }
    58 size_t HandleCloser::GetBufferSize() {
    59   size_t bytes_total = offsetof(HandleCloserInfo, handle_entries);
    61   for (HandleMap::iterator i = handles_to_close_.begin();
    62        i != handles_to_close_.end(); ++i) {
    63     size_t bytes_entry = offsetof(HandleListEntry, handle_type) +
    64         (i->first.size() + 1) * sizeof(char16);
    65     for (HandleMap::mapped_type::iterator j = i->second.begin();
    66          j != i->second.end(); ++j) {
    67       bytes_entry += ((*j).size() + 1) * sizeof(char16);
    68     }
    70     // Round up to the nearest multiple of word size.
    71     bytes_entry = RoundUpToWordSize(bytes_entry);
    72     bytes_total += bytes_entry;
    73   }
    75   return bytes_total;
    76 }
    78 bool HandleCloser::InitializeTargetHandles(TargetProcess* target) {
    79   // Do nothing on an empty list (global pointer already initialized to NULL).
    80   if (handles_to_close_.empty())
    81     return true;
    83   size_t bytes_needed = GetBufferSize();
    84   scoped_ptr<size_t[]> local_buffer(
    85       new size_t[bytes_needed / sizeof(size_t)]);
    87   if (!SetupHandleList(local_buffer.get(), bytes_needed))
    88     return false;
    90   HANDLE child = target->Process();
    92   // Allocate memory in the target process without specifying the address
    93   void* remote_data = ::VirtualAllocEx(child, NULL, bytes_needed,
    94                                        MEM_COMMIT, PAGE_READWRITE);
    95   if (NULL == remote_data)
    96     return false;
    98   // Copy the handle buffer over.
    99   SIZE_T bytes_written;
   100   BOOL result = ::WriteProcessMemory(child, remote_data, local_buffer.get(),
   101                                      bytes_needed, &bytes_written);
   102   if (!result || bytes_written != bytes_needed) {
   103     ::VirtualFreeEx(child, remote_data, 0, MEM_RELEASE);
   104     return false;
   105   }
   107   g_handles_to_close = reinterpret_cast<HandleCloserInfo*>(remote_data);
   109   ResultCode rc = target->TransferVariable("g_handles_to_close",
   110                                            &g_handles_to_close,
   111                                            sizeof(g_handles_to_close));
   113   return (SBOX_ALL_OK == rc);
   114 }
   116 bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) {
   117   ::ZeroMemory(buffer, buffer_bytes);
   118   HandleCloserInfo* handle_info = reinterpret_cast<HandleCloserInfo*>(buffer);
   119   handle_info->record_bytes = buffer_bytes;
   120   handle_info->num_handle_types = handles_to_close_.size();
   122   char16* output = reinterpret_cast<char16*>(&handle_info->handle_entries[0]);
   123   char16* end = reinterpret_cast<char16*>(
   124       reinterpret_cast<char*>(buffer) + buffer_bytes);
   125   for (HandleMap::iterator i = handles_to_close_.begin();
   126        i != handles_to_close_.end(); ++i) {
   127     if (output >= end)
   128       return false;
   129     HandleListEntry* list_entry = reinterpret_cast<HandleListEntry*>(output);
   130     output = &list_entry->handle_type[0];
   132     // Copy the typename and set the offset and count.
   133     i->first._Copy_s(output, i->first.size(), i->first.size());
   134     *(output += i->first.size()) = L'\0';
   135     output++;
   136     list_entry->offset_to_names = reinterpret_cast<char*>(output) -
   137         reinterpret_cast<char*>(list_entry);
   138     list_entry->name_count = i->second.size();
   140     // Copy the handle names.
   141     for (HandleMap::mapped_type::iterator j = i->second.begin();
   142          j != i->second.end(); ++j) {
   143       output = std::copy((*j).begin(), (*j).end(), output) + 1;
   144     }
   146     // Round up to the nearest multiple of sizeof(size_t).
   147     output = RoundUpToWordSize(output);
   148     list_entry->record_bytes = reinterpret_cast<char*>(output) -
   149         reinterpret_cast<char*>(list_entry);
   150   }
   152   DCHECK_EQ(reinterpret_cast<size_t>(output), reinterpret_cast<size_t>(end));
   153   return output <= end;
   154 }
   156 bool HandleCloser::SetupHandleInterceptions(InterceptionManager* manager) {
   157   // We need to intercept CreateThread if we're closing ALPC port clients.
   158   HandleMap::iterator names = handles_to_close_.find(L"ALPC Port");
   159   if (base::win::GetVersion() >= base::win::VERSION_VISTA &&
   160       names != handles_to_close_.end() &&
   161       (names->second.empty() || names->second.size() == 0)) {
   162     if (!INTERCEPT_EAT(manager, kKerneldllName, CreateThread,
   163                        CREATE_THREAD_ID, 28)) {
   164       return false;
   165     }
   166     if (!INTERCEPT_EAT(manager, kKerneldllName, GetUserDefaultLCID,
   167                        GET_USER_DEFAULT_LCID_ID, 4)) {
   168       return false;
   169     }
   171     return true;
   172   }
   174   return true;
   175 }
   177 bool GetHandleName(HANDLE handle, string16* handle_name) {
   178   static NtQueryObject QueryObject = NULL;
   179   if (!QueryObject)
   180     ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
   182   ULONG size = MAX_PATH;
   183   scoped_ptr<UNICODE_STRING, base::FreeDeleter> name;
   184   NTSTATUS result;
   186   do {
   187     name.reset(static_cast<UNICODE_STRING*>(malloc(size)));
   188     DCHECK(name.get());
   189     result = QueryObject(handle, ObjectNameInformation, name.get(),
   190                          size, &size);
   191   } while (result == STATUS_INFO_LENGTH_MISMATCH ||
   192            result == STATUS_BUFFER_OVERFLOW);
   194   if (NT_SUCCESS(result) && name->Buffer && name->Length)
   195     handle_name->assign(name->Buffer, name->Length / sizeof(wchar_t));
   196   else
   197     handle_name->clear();
   199   return NT_SUCCESS(result);
   200 }
   202 }  // namespace sandbox

mercurial