diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /security/sandbox/chromium/base/win/scoped_handle.cc | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'security/sandbox/chromium/base/win/scoped_handle.cc')
-rw-r--r-- | security/sandbox/chromium/base/win/scoped_handle.cc | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/win/scoped_handle.cc b/security/sandbox/chromium/base/win/scoped_handle.cc new file mode 100644 index 000000000..9c21603a0 --- /dev/null +++ b/security/sandbox/chromium/base/win/scoped_handle.cc @@ -0,0 +1,248 @@ +// Copyright (c) 2012 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 "base/win/scoped_handle.h" + +#include <stddef.h> + +#include <unordered_map> + +#include "base/debug/alias.h" +#include "base/hash.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/synchronization/lock_impl.h" + +extern "C" { +__declspec(dllexport) void* GetHandleVerifier(); +typedef void* (*GetHandleVerifierFn)(); +} + +namespace { + +struct HandleHash { + size_t operator()(const HANDLE& handle) const { + char buffer[sizeof(handle)]; + memcpy(buffer, &handle, sizeof(handle)); + return base::Hash(buffer, sizeof(buffer)); + } +}; + +struct Info { + const void* owner; + const void* pc1; + const void* pc2; + DWORD thread_id; +}; +typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; + +// g_lock protects the handle map and setting g_active_verifier. +typedef base::internal::LockImpl NativeLock; +base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; + +bool CloseHandleWrapper(HANDLE handle) { + if (!::CloseHandle(handle)) + CHECK(false); + return true; +} + +// Simple automatic locking using a native critical section so it supports +// recursive locking. +class AutoNativeLock { + public: + explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { + lock_.Lock(); + } + + ~AutoNativeLock() { + lock_.Unlock(); + } + + private: + NativeLock& lock_; + DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); +}; + +// Implements the actual object that is verifying handles for this process. +// The active instance is shared across the module boundary but there is no +// way to delete this object from the wrong side of it (or any side, actually). +class ActiveVerifier { + public: + explicit ActiveVerifier(bool enabled) + : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) { + } + + // Retrieves the current verifier. + static ActiveVerifier* Get(); + + // The methods required by HandleTraits. They are virtual because we need to + // forward the call execution to another module, instead of letting the + // compiler call the version that is linked in the current module. + virtual bool CloseHandle(HANDLE handle); + virtual void StartTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2); + virtual void StopTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2); + virtual void Disable(); + virtual void OnHandleBeingClosed(HANDLE handle); + + private: + ~ActiveVerifier(); // Not implemented. + + static void InstallVerifier(); + + bool enabled_; + bool closing_; + NativeLock* lock_; + HandleMap map_; + DISALLOW_COPY_AND_ASSIGN(ActiveVerifier); +}; +ActiveVerifier* g_active_verifier = NULL; + +// static +ActiveVerifier* ActiveVerifier::Get() { + if (!g_active_verifier) + ActiveVerifier::InstallVerifier(); + + return g_active_verifier; +} + +// static +void ActiveVerifier::InstallVerifier() { +#if defined(COMPONENT_BUILD) + AutoNativeLock lock(g_lock.Get()); + g_active_verifier = new ActiveVerifier(true); +#else + // If you are reading this, wondering why your process seems deadlocked, take + // a look at your DllMain code and remove things that should not be done + // there, like doing whatever gave you that nice windows handle you are trying + // to store in a ScopedHandle. + HMODULE main_module = ::GetModuleHandle(NULL); + GetHandleVerifierFn get_handle_verifier = + reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( + main_module, "GetHandleVerifier")); + + if (!get_handle_verifier) { + g_active_verifier = new ActiveVerifier(false); + return; + } + + ActiveVerifier* verifier = + reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); + + // This lock only protects against races in this module, which is fine. + AutoNativeLock lock(g_lock.Get()); + g_active_verifier = verifier ? verifier : new ActiveVerifier(true); +#endif +} + +bool ActiveVerifier::CloseHandle(HANDLE handle) { + if (!enabled_) + return CloseHandleWrapper(handle); + + AutoNativeLock lock(*lock_); + closing_ = true; + CloseHandleWrapper(handle); + closing_ = false; + + return true; +} + +void ActiveVerifier::StartTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2) { + if (!enabled_) + return; + + // Grab the thread id before the lock. + DWORD thread_id = GetCurrentThreadId(); + + AutoNativeLock lock(*lock_); + + Info handle_info = { owner, pc1, pc2, thread_id }; + std::pair<HANDLE, Info> item(handle, handle_info); + std::pair<HandleMap::iterator, bool> result = map_.insert(item); + if (!result.second) { + Info other = result.first->second; + base::debug::Alias(&other); + CHECK(false); + } +} + +void ActiveVerifier::StopTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2) { + if (!enabled_) + return; + + AutoNativeLock lock(*lock_); + HandleMap::iterator i = map_.find(handle); + if (i == map_.end()) + CHECK(false); + + Info other = i->second; + if (other.owner != owner) { + base::debug::Alias(&other); + CHECK(false); + } + + map_.erase(i); +} + +void ActiveVerifier::Disable() { + enabled_ = false; +} + +void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) { + if (!enabled_) + return; + + AutoNativeLock lock(*lock_); + if (closing_) + return; + + HandleMap::iterator i = map_.find(handle); + if (i == map_.end()) + return; + + Info other = i->second; + base::debug::Alias(&other); + CHECK(false); +} + +} // namespace + +void* GetHandleVerifier() { + return g_active_verifier; +} + +namespace base { +namespace win { + +// Static. +bool HandleTraits::CloseHandle(HANDLE handle) { + return ActiveVerifier::Get()->CloseHandle(handle); +} + +// Static. +void VerifierTraits::StartTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2) { + return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2); +} + +// Static. +void VerifierTraits::StopTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2) { + return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2); +} + +void DisableHandleVerifier() { + return ActiveVerifier::Get()->Disable(); +} + +void OnHandleBeingClosed(HANDLE handle) { + return ActiveVerifier::Get()->OnHandleBeingClosed(handle); +} + +} // namespace win +} // namespace base |