security/sandbox/win/src/handle_closer_agent.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.

michael@0 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "sandbox/win/src/handle_closer_agent.h"
michael@0 6
michael@0 7 #include "base/logging.h"
michael@0 8 #include "sandbox/win/src/nt_internals.h"
michael@0 9 #include "sandbox/win/src/win_utils.h"
michael@0 10
michael@0 11 namespace {
michael@0 12
michael@0 13 // Returns type infomation for an NT object. This routine is expected to be
michael@0 14 // called for invalid handles so it catches STATUS_INVALID_HANDLE exceptions
michael@0 15 // that can be generated when handle tracing is enabled.
michael@0 16 NTSTATUS QueryObjectTypeInformation(HANDLE handle,
michael@0 17 void* buffer,
michael@0 18 ULONG* size) {
michael@0 19 static NtQueryObject QueryObject = NULL;
michael@0 20 if (!QueryObject)
michael@0 21 ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
michael@0 22
michael@0 23 NTSTATUS status = STATUS_UNSUCCESSFUL;
michael@0 24 __try {
michael@0 25 status = QueryObject(handle, ObjectTypeInformation, buffer, *size, size);
michael@0 26 } __except(GetExceptionCode() == STATUS_INVALID_HANDLE ?
michael@0 27 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
michael@0 28 status = STATUS_INVALID_HANDLE;
michael@0 29 }
michael@0 30 return status;
michael@0 31 }
michael@0 32
michael@0 33 } // namespace
michael@0 34
michael@0 35 namespace sandbox {
michael@0 36
michael@0 37 // Memory buffer mapped from the parent, with the list of handles.
michael@0 38 SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close = NULL;
michael@0 39
michael@0 40 bool HandleCloserAgent::NeedsHandlesClosed() {
michael@0 41 return g_handles_to_close != NULL;
michael@0 42 }
michael@0 43
michael@0 44 // Reads g_handles_to_close and creates the lookup map.
michael@0 45 void HandleCloserAgent::InitializeHandlesToClose() {
michael@0 46 CHECK(g_handles_to_close != NULL);
michael@0 47
michael@0 48 // Grab the header.
michael@0 49 HandleListEntry* entry = g_handles_to_close->handle_entries;
michael@0 50 for (size_t i = 0; i < g_handles_to_close->num_handle_types; ++i) {
michael@0 51 // Set the type name.
michael@0 52 char16* input = entry->handle_type;
michael@0 53 HandleMap::mapped_type& handle_names = handles_to_close_[input];
michael@0 54 input = reinterpret_cast<char16*>(reinterpret_cast<char*>(entry)
michael@0 55 + entry->offset_to_names);
michael@0 56 // Grab all the handle names.
michael@0 57 for (size_t j = 0; j < entry->name_count; ++j) {
michael@0 58 std::pair<HandleMap::mapped_type::iterator, bool> name
michael@0 59 = handle_names.insert(input);
michael@0 60 CHECK(name.second);
michael@0 61 input += name.first->size() + 1;
michael@0 62 }
michael@0 63
michael@0 64 // Move on to the next entry.
michael@0 65 entry = reinterpret_cast<HandleListEntry*>(reinterpret_cast<char*>(entry)
michael@0 66 + entry->record_bytes);
michael@0 67
michael@0 68 DCHECK(reinterpret_cast<char16*>(entry) >= input);
michael@0 69 DCHECK(reinterpret_cast<char16*>(entry) - input <
michael@0 70 sizeof(size_t) / sizeof(char16));
michael@0 71 }
michael@0 72
michael@0 73 // Clean up the memory we copied over.
michael@0 74 ::VirtualFree(g_handles_to_close, 0, MEM_RELEASE);
michael@0 75 g_handles_to_close = NULL;
michael@0 76 }
michael@0 77
michael@0 78 bool HandleCloserAgent::CloseHandles() {
michael@0 79 DWORD handle_count = UINT_MAX;
michael@0 80 const int kInvalidHandleThreshold = 100;
michael@0 81 const size_t kHandleOffset = sizeof(HANDLE);
michael@0 82
michael@0 83 if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
michael@0 84 return false;
michael@0 85
michael@0 86 // Set up buffers for the type info and the name.
michael@0 87 std::vector<BYTE> type_info_buffer(sizeof(OBJECT_TYPE_INFORMATION) +
michael@0 88 32 * sizeof(wchar_t));
michael@0 89 OBJECT_TYPE_INFORMATION* type_info =
michael@0 90 reinterpret_cast<OBJECT_TYPE_INFORMATION*>(&(type_info_buffer[0]));
michael@0 91 string16 handle_name;
michael@0 92 HANDLE handle = NULL;
michael@0 93 int invalid_count = 0;
michael@0 94
michael@0 95 // Keep incrementing until we hit the number of handles reported by
michael@0 96 // GetProcessHandleCount(). If we hit a very long sequence of invalid
michael@0 97 // handles we assume that we've run past the end of the table.
michael@0 98 while (handle_count && invalid_count < kInvalidHandleThreshold) {
michael@0 99 reinterpret_cast<size_t&>(handle) += kHandleOffset;
michael@0 100 NTSTATUS rc;
michael@0 101
michael@0 102 // Get the type name, reusing the buffer.
michael@0 103 ULONG size = static_cast<ULONG>(type_info_buffer.size());
michael@0 104 rc = QueryObjectTypeInformation(handle, type_info, &size);
michael@0 105 while (rc == STATUS_INFO_LENGTH_MISMATCH ||
michael@0 106 rc == STATUS_BUFFER_OVERFLOW) {
michael@0 107 type_info_buffer.resize(size + sizeof(wchar_t));
michael@0 108 type_info = reinterpret_cast<OBJECT_TYPE_INFORMATION*>(
michael@0 109 &(type_info_buffer[0]));
michael@0 110 rc = QueryObjectTypeInformation(handle, type_info, &size);
michael@0 111 // Leave padding for the nul terminator.
michael@0 112 if (NT_SUCCESS(rc) && size == type_info_buffer.size())
michael@0 113 rc = STATUS_INFO_LENGTH_MISMATCH;
michael@0 114 }
michael@0 115 if (!NT_SUCCESS(rc) || !type_info->Name.Buffer) {
michael@0 116 ++invalid_count;
michael@0 117 continue;
michael@0 118 }
michael@0 119
michael@0 120 --handle_count;
michael@0 121 type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0';
michael@0 122
michael@0 123 // Check if we're looking for this type of handle.
michael@0 124 HandleMap::iterator result =
michael@0 125 handles_to_close_.find(type_info->Name.Buffer);
michael@0 126 if (result != handles_to_close_.end()) {
michael@0 127 HandleMap::mapped_type& names = result->second;
michael@0 128 // Empty set means close all handles of this type; otherwise check name.
michael@0 129 if (!names.empty()) {
michael@0 130 // Move on to the next handle if this name doesn't match.
michael@0 131 if (!GetHandleName(handle, &handle_name) || !names.count(handle_name))
michael@0 132 continue;
michael@0 133 }
michael@0 134
michael@0 135 if (!::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0))
michael@0 136 return false;
michael@0 137 if (!::CloseHandle(handle))
michael@0 138 return false;
michael@0 139 }
michael@0 140 }
michael@0 141
michael@0 142 return true;
michael@0 143 }
michael@0 144
michael@0 145 } // namespace sandbox

mercurial