[go: nahoru, domu]

blob: b2d7d595ca0bdd477e97b159f68128eaa023a485 [file] [log] [blame]
rvargas@chromium.org6c6c2cc2012-05-31 05:04:181// Copyright (c) 2012 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
5#include "base/win/scoped_handle.h"
6
avi3131ce822015-12-24 04:58:497#include <stddef.h>
8
rvargas86d7c902014-09-04 22:58:099#include <unordered_map>
tonygcf244d12014-08-27 00:14:1310
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1811#include "base/debug/alias.h"
wfh0359d7d2016-03-03 21:36:1312#include "base/debug/stack_trace.h"
rvargas86d7c902014-09-04 22:58:0913#include "base/hash.h"
rvargas86d7c902014-09-04 22:58:0914#include "base/logging.h"
avi3131ce822015-12-24 04:58:4915#include "base/macros.h"
rvargas86d7c902014-09-04 22:58:0916#include "base/synchronization/lock_impl.h"
siggi2ca94bde2016-03-09 13:23:1917#include "base/threading/thread_local.h"
sebmarchand82ef02042016-06-08 15:56:3218#include "base/win/base_features.h"
thakisd62f54472016-04-04 02:21:1019#include "base/win/current_module.h"
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1820
rvargas8545e0e72015-04-09 01:40:5021extern "C" {
22__declspec(dllexport) void* GetHandleVerifier();
23typedef void* (*GetHandleVerifierFn)();
24}
wfh8f20e832016-03-12 02:09:5925
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1826namespace {
rvargas86d7c902014-09-04 22:58:0927
28struct HandleHash {
29 size_t operator()(const HANDLE& handle) const {
30 char buffer[sizeof(handle)];
31 memcpy(buffer, &handle, sizeof(handle));
32 return base::Hash(buffer, sizeof(buffer));
33 }
34};
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1835
36struct Info {
37 const void* owner;
rvargas@chromium.org30e170a2012-06-07 05:32:3438 const void* pc1;
39 const void* pc2;
wfh0359d7d2016-03-03 21:36:1340 base::debug::StackTrace stack;
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1841 DWORD thread_id;
42};
rvargas86d7c902014-09-04 22:58:0943typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1844
scottmg6ece5ae2017-02-01 18:25:1945// GetLock() protects the handle map and setting g_active_verifier within this
wfh678736a2016-03-11 08:41:0446// module.
rvargas86d7c902014-09-04 22:58:0947typedef base::internal::LockImpl NativeLock;
scottmg6ece5ae2017-02-01 18:25:1948NativeLock* GetLock() {
vmpstr843b41a2017-03-01 21:15:0349 static auto* native_lock = new NativeLock();
scottmg6ece5ae2017-02-01 18:25:1950 return native_lock;
51}
rvargas86d7c902014-09-04 22:58:0952
53// Simple automatic locking using a native critical section so it supports
54// recursive locking.
55class AutoNativeLock {
56 public:
57 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) {
58 lock_.Lock();
59 }
60
61 ~AutoNativeLock() {
62 lock_.Unlock();
63 }
64
65 private:
66 NativeLock& lock_;
67 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
68};
rvargas@chromium.org6c6c2cc2012-05-31 05:04:1869
rvargas8545e0e72015-04-09 01:40:5070// Implements the actual object that is verifying handles for this process.
71// The active instance is shared across the module boundary but there is no
72// way to delete this object from the wrong side of it (or any side, actually).
73class ActiveVerifier {
74 public:
scottmg6ece5ae2017-02-01 18:25:1975 explicit ActiveVerifier(bool enabled) : enabled_(enabled), lock_(GetLock()) {}
rvargas8545e0e72015-04-09 01:40:5076
77 // Retrieves the current verifier.
78 static ActiveVerifier* Get();
79
80 // The methods required by HandleTraits. They are virtual because we need to
81 // forward the call execution to another module, instead of letting the
82 // compiler call the version that is linked in the current module.
83 virtual bool CloseHandle(HANDLE handle);
84 virtual void StartTracking(HANDLE handle, const void* owner,
85 const void* pc1, const void* pc2);
86 virtual void StopTracking(HANDLE handle, const void* owner,
87 const void* pc1, const void* pc2);
88 virtual void Disable();
89 virtual void OnHandleBeingClosed(HANDLE handle);
wfh8f20e832016-03-12 02:09:5990 virtual HMODULE GetModule() const;
rvargas8545e0e72015-04-09 01:40:5091
92 private:
93 ~ActiveVerifier(); // Not implemented.
94
95 static void InstallVerifier();
96
wfh1f9673d2016-03-09 00:33:0297 base::debug::StackTrace creation_stack_;
rvargas8545e0e72015-04-09 01:40:5098 bool enabled_;
siggi2ca94bde2016-03-09 13:23:1999 base::ThreadLocalBoolean closing_;
rvargas8545e0e72015-04-09 01:40:50100 NativeLock* lock_;
101 HandleMap map_;
102 DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
103};
104ActiveVerifier* g_active_verifier = NULL;
105
106// static
107ActiveVerifier* ActiveVerifier::Get() {
108 if (!g_active_verifier)
109 ActiveVerifier::InstallVerifier();
110
111 return g_active_verifier;
112}
113
wfh678736a2016-03-11 08:41:04114bool CloseHandleWrapper(HANDLE handle) {
115 if (!::CloseHandle(handle))
116 CHECK(false); // CloseHandle failed.
117 return true;
118}
119
scottmg6ece5ae2017-02-01 18:25:19120// Assigns the g_active_verifier global within the GetLock() lock.
wfh678736a2016-03-11 08:41:04121// If |existing_verifier| is non-null then |enabled| is ignored.
122void ThreadSafeAssignOrCreateActiveVerifier(ActiveVerifier* existing_verifier,
123 bool enabled) {
scottmg6ece5ae2017-02-01 18:25:19124 AutoNativeLock lock(*GetLock());
wfh678736a2016-03-11 08:41:04125 // Another thread in this module might be trying to assign the global
126 // verifier, so check that within the lock here.
127 if (g_active_verifier)
128 return;
129 g_active_verifier =
130 existing_verifier ? existing_verifier : new ActiveVerifier(enabled);
131}
132
rvargas8545e0e72015-04-09 01:40:50133// static
134void ActiveVerifier::InstallVerifier() {
sebmarchand82ef02042016-06-08 15:56:32135#if BUILDFLAG(SINGLE_MODULE_MODE_HANDLE_VERIFIER)
wfh678736a2016-03-11 08:41:04136 // Component build has one Active Verifier per module.
137 ThreadSafeAssignOrCreateActiveVerifier(nullptr, true);
rvargas8545e0e72015-04-09 01:40:50138#else
139 // If you are reading this, wondering why your process seems deadlocked, take
140 // a look at your DllMain code and remove things that should not be done
141 // there, like doing whatever gave you that nice windows handle you are trying
142 // to store in a ScopedHandle.
143 HMODULE main_module = ::GetModuleHandle(NULL);
144 GetHandleVerifierFn get_handle_verifier =
145 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
146 main_module, "GetHandleVerifier"));
147
wfh678736a2016-03-11 08:41:04148 // This should only happen if running in a DLL is linked with base but the
149 // hosting EXE is not. In this case, create an ActiveVerifier for the current
150 // module but leave it disabled.
rvargas8545e0e72015-04-09 01:40:50151 if (!get_handle_verifier) {
wfh678736a2016-03-11 08:41:04152 ThreadSafeAssignOrCreateActiveVerifier(nullptr, false);
rvargas8545e0e72015-04-09 01:40:50153 return;
154 }
155
wfh678736a2016-03-11 08:41:04156 // Check if in the main module.
157 if (get_handle_verifier == GetHandleVerifier) {
158 ThreadSafeAssignOrCreateActiveVerifier(nullptr, true);
159 return;
160 }
161
162 ActiveVerifier* main_module_verifier =
rvargas8545e0e72015-04-09 01:40:50163 reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
164
wfh678736a2016-03-11 08:41:04165 // Main module should always on-demand create a verifier.
166 DCHECK(main_module_verifier);
167
168 ThreadSafeAssignOrCreateActiveVerifier(main_module_verifier, false);
rvargas8545e0e72015-04-09 01:40:50169#endif
170}
171
172bool ActiveVerifier::CloseHandle(HANDLE handle) {
173 if (!enabled_)
174 return CloseHandleWrapper(handle);
175
siggi2ca94bde2016-03-09 13:23:19176 closing_.Set(true);
rvargas8545e0e72015-04-09 01:40:50177 CloseHandleWrapper(handle);
siggi2ca94bde2016-03-09 13:23:19178 closing_.Set(false);
rvargas8545e0e72015-04-09 01:40:50179
180 return true;
181}
182
183void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
184 const void* pc1, const void* pc2) {
185 if (!enabled_)
186 return;
187
188 // Grab the thread id before the lock.
189 DWORD thread_id = GetCurrentThreadId();
190
191 AutoNativeLock lock(*lock_);
192
wfh0359d7d2016-03-03 21:36:13193 Info handle_info = { owner, pc1, pc2, base::debug::StackTrace(), thread_id };
rvargas8545e0e72015-04-09 01:40:50194 std::pair<HANDLE, Info> item(handle, handle_info);
195 std::pair<HandleMap::iterator, bool> result = map_.insert(item);
196 if (!result.second) {
197 Info other = result.first->second;
198 base::debug::Alias(&other);
wfh1f9673d2016-03-09 00:33:02199 base::debug::Alias(&creation_stack_);
wfh48017362016-03-08 22:37:57200 CHECK(false); // Attempt to start tracking already tracked handle.
rvargas8545e0e72015-04-09 01:40:50201 }
202}
203
204void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
205 const void* pc1, const void* pc2) {
206 if (!enabled_)
207 return;
shrikantc928d342015-05-12 22:28:58208
rvargas8545e0e72015-04-09 01:40:50209 AutoNativeLock lock(*lock_);
210 HandleMap::iterator i = map_.find(handle);
wfh1f9673d2016-03-09 00:33:02211 if (i == map_.end()) {
212 base::debug::Alias(&creation_stack_);
wfh48017362016-03-08 22:37:57213 CHECK(false); // Attempting to close an untracked handle.
wfh1f9673d2016-03-09 00:33:02214 }
rvargas8545e0e72015-04-09 01:40:50215
216 Info other = i->second;
217 if (other.owner != owner) {
218 base::debug::Alias(&other);
wfh1f9673d2016-03-09 00:33:02219 base::debug::Alias(&creation_stack_);
wfh48017362016-03-08 22:37:57220 CHECK(false); // Attempting to close a handle not owned by opener.
rvargas8545e0e72015-04-09 01:40:50221 }
222
223 map_.erase(i);
224}
225
226void ActiveVerifier::Disable() {
227 enabled_ = false;
228}
229
230void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
wfh2b30ce392016-01-06 18:30:07231 if (!enabled_)
232 return;
233
siggi2ca94bde2016-03-09 13:23:19234 if (closing_.Get())
rvargas8545e0e72015-04-09 01:40:50235 return;
236
siggi2ca94bde2016-03-09 13:23:19237 AutoNativeLock lock(*lock_);
rvargas8545e0e72015-04-09 01:40:50238 HandleMap::iterator i = map_.find(handle);
239 if (i == map_.end())
240 return;
241
242 Info other = i->second;
243 base::debug::Alias(&other);
wfh1f9673d2016-03-09 00:33:02244 base::debug::Alias(&creation_stack_);
wfh48017362016-03-08 22:37:57245 CHECK(false); // CloseHandle called on tracked handle.
rvargas8545e0e72015-04-09 01:40:50246}
247
wfh8f20e832016-03-12 02:09:59248HMODULE ActiveVerifier::GetModule() const {
thakisd62f54472016-04-04 02:21:10249 return CURRENT_MODULE();
wfh8f20e832016-03-12 02:09:59250}
251
rvargas@chromium.org6c6c2cc2012-05-31 05:04:18252} // namespace
rvargas8545e0e72015-04-09 01:40:50253
254void* GetHandleVerifier() {
wfh678736a2016-03-11 08:41:04255 return ActiveVerifier::Get();
rvargas8545e0e72015-04-09 01:40:50256}
rvargas@chromium.org6c6c2cc2012-05-31 05:04:18257
258namespace base {
259namespace win {
260
261// Static.
rvargas86d7c902014-09-04 22:58:09262bool HandleTraits::CloseHandle(HANDLE handle) {
rvargas8545e0e72015-04-09 01:40:50263 return ActiveVerifier::Get()->CloseHandle(handle);
rvargas86d7c902014-09-04 22:58:09264}
265
266// Static.
rvargas@chromium.org6c6c2cc2012-05-31 05:04:18267void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
rvargas@chromium.org30e170a2012-06-07 05:32:34268 const void* pc1, const void* pc2) {
rvargas8545e0e72015-04-09 01:40:50269 return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2);
rvargas@chromium.org6c6c2cc2012-05-31 05:04:18270}
271
272// Static.
273void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
rvargas@chromium.org30e170a2012-06-07 05:32:34274 const void* pc1, const void* pc2) {
rvargas8545e0e72015-04-09 01:40:50275 return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2);
rvargas1a4d07b2014-08-26 19:45:42276}
277
rvargas86d7c902014-09-04 22:58:09278void DisableHandleVerifier() {
rvargas8545e0e72015-04-09 01:40:50279 return ActiveVerifier::Get()->Disable();
rvargas86d7c902014-09-04 22:58:09280}
281
282void OnHandleBeingClosed(HANDLE handle) {
rvargas8545e0e72015-04-09 01:40:50283 return ActiveVerifier::Get()->OnHandleBeingClosed(handle);
rvargas86d7c902014-09-04 22:58:09284}
285
wfh8f20e832016-03-12 02:09:59286HMODULE GetHandleVerifierModuleForTesting() {
287 return g_active_verifier->GetModule();
288}
289
rvargas@chromium.org6c6c2cc2012-05-31 05:04:18290} // namespace win
291} // namespace base