Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: base/win/scoped_handle.cc

Issue 1045513004: Integrate the handle verifier from multiple modules (DLLs) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: grt review Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/win/scoped_handle.h" 5 #include "base/win/scoped_handle.h"
6 6
7 #include <unordered_map> 7 #include <unordered_map>
8 8
9 #include "base/debug/alias.h" 9 #include "base/debug/alias.h"
10 #include "base/environment.h"
10 #include "base/hash.h" 11 #include "base/hash.h"
11 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/synchronization/lock_impl.h" 14 #include "base/synchronization/lock_impl.h"
14 15
16 extern "C" {
17 __declspec(dllexport) void* GetHandleVerifier();
Will Harris 2015/04/01 17:44:24 won't this function end up being exported from all
rvargas (doing something else) 2015/04/01 18:23:53 sorta, kind of yes... I mean, I'm fine with every
18 typedef void* (*GetHandleVerifierFn)();
19 }
20
15 namespace { 21 namespace {
16 22
17 struct HandleHash { 23 struct HandleHash {
18 size_t operator()(const HANDLE& handle) const { 24 size_t operator()(const HANDLE& handle) const {
19 char buffer[sizeof(handle)]; 25 char buffer[sizeof(handle)];
20 memcpy(buffer, &handle, sizeof(handle)); 26 memcpy(buffer, &handle, sizeof(handle));
21 return base::Hash(buffer, sizeof(buffer)); 27 return base::Hash(buffer, sizeof(buffer));
22 } 28 }
23 }; 29 };
24 30
25 struct Info { 31 struct Info {
26 const void* owner; 32 const void* owner;
27 const void* pc1; 33 const void* pc1;
28 const void* pc2; 34 const void* pc2;
29 DWORD thread_id; 35 DWORD thread_id;
30 }; 36 };
31 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; 37 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
32 38
33 // g_lock protects g_handle_map and g_closing. 39 // g_lock protects the handle map and setting g_active_verifier.
34 typedef base::internal::LockImpl NativeLock; 40 typedef base::internal::LockImpl NativeLock;
35 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; 41 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
36 base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER;
37 bool g_closing = false;
38
39 // g_verifier_enabled is not protected by g_lock because that would require
40 // using the lock (hence, synchornizing multiple threads) even when the
41 // verifier is not in use. Note that this variable is initialized to track all
42 // handles, and it should only move to the disabled state, and never back to
43 // enabled, because that would crash when seeing handles created while the
44 // verifier was disabled. This also implies that it is OK if the value change is
45 // not propagated immediately to all CPUs (as would happen with a lock).
46 bool g_verifier_enabled = true;
47 42
48 bool CloseHandleWrapper(HANDLE handle) { 43 bool CloseHandleWrapper(HANDLE handle) {
49 if (!::CloseHandle(handle)) 44 if (!::CloseHandle(handle))
50 CHECK(false); 45 CHECK(false);
51 return true; 46 return true;
52 } 47 }
53 48
54 // Simple automatic locking using a native critical section so it supports 49 // Simple automatic locking using a native critical section so it supports
55 // recursive locking. 50 // recursive locking.
56 class AutoNativeLock { 51 class AutoNativeLock {
57 public: 52 public:
58 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { 53 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) {
59 lock_.Lock(); 54 lock_.Lock();
60 } 55 }
61 56
62 ~AutoNativeLock() { 57 ~AutoNativeLock() {
63 lock_.Unlock(); 58 lock_.Unlock();
64 } 59 }
65 60
66 private: 61 private:
67 NativeLock& lock_; 62 NativeLock& lock_;
68 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); 63 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
69 }; 64 };
70 65
66 // Implements the actual object that is verifying handles for this process.
67 // The active instance is shared across the module boundary but there is no
68 // way to delete this object from the wrong side of it (or any side, actually).
69 class ActiveVerifier {
70 public:
71 explicit ActiveVerifier(bool enabled)
72 : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) {
73 }
74
75 static void InstallVerifier();
76
77 // The methods required by HandleTraits. They are virtual because we need to
78 // forward the call execution to another module, instead of letting the
79 // compiler call the version that is linked in the current module.
80 virtual bool CloseHandle(HANDLE handle);
81 virtual void StartTracking(HANDLE handle, const void* owner,
82 const void* pc1, const void* pc2);
83 virtual void StopTracking(HANDLE handle, const void* owner,
84 const void* pc1, const void* pc2);
85 virtual void Disable();
86 virtual void OnHandleBeingClosed(HANDLE handle);
87
88 private:
89 ~ActiveVerifier(); // Not implemented.
90
91 bool enabled_;
92 bool closing_;
93 NativeLock* lock_;
94 HandleMap map_;
95 DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
96 };
97 ActiveVerifier* g_active_verifier = NULL;
98
99 // static
100 void ActiveVerifier::InstallVerifier() {
101 #if defined(COMPONENT_BUILD)
102 AutoNativeLock lock(g_lock.Get());
103 g_active_verifier = new ActiveVerifier(true);
104 #else
105 HMODULE main_module = ::GetModuleHandle(NULL);
Will Harris 2015/04/01 17:44:24 to confirm you want to call the exe's version of G
rvargas (doing something else) 2015/04/01 18:23:53 Correct. I'm just being extremely cautious about e
Will Harris 2015/04/02 18:11:15 is it not possible for two modules to both create
rvargas (doing something else) 2015/04/02 18:25:23 Correct. The lock here (118) is meant to protect
106 GetHandleVerifierFn get_handle_verifier =
107 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
108 main_module, "GetHandleVerifier"));
109
110 if (!get_handle_verifier) {
111 g_active_verifier = new ActiveVerifier(false);
112 return;
113 }
114
115 ActiveVerifier* verifier =
116 reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
117
118 AutoNativeLock lock(g_lock.Get());
119 g_active_verifier = verifier ? verifier : new ActiveVerifier(true);
120 #endif
121 }
122
123 bool ActiveVerifier::CloseHandle(HANDLE handle) {
124 if (!enabled_)
125 return CloseHandleWrapper(handle);
126
127 AutoNativeLock lock(*lock_);
128 closing_ = true;
129 CloseHandleWrapper(handle);
130 closing_ = false;
131
132 return true;
133 }
134
135 void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
136 const void* pc1, const void* pc2) {
137 if (!enabled_)
138 return;
139
140 // Grab the thread id before the lock.
141 DWORD thread_id = GetCurrentThreadId();
142
143 AutoNativeLock lock(*lock_);
144
145 Info handle_info = { owner, pc1, pc2, thread_id };
146 std::pair<HANDLE, Info> item(handle, handle_info);
147 std::pair<HandleMap::iterator, bool> result = map_.insert(item);
148 if (!result.second) {
149 Info other = result.first->second;
150 base::debug::Alias(&other);
151 CHECK(false);
152 }
153 }
154
155 void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
156 const void* pc1, const void* pc2) {
157 if (!enabled_)
158 return;
159
160 AutoNativeLock lock(*lock_);
161 HandleMap::iterator i = map_.find(handle);
162 if (i == map_.end())
163 CHECK(false);
164
165 Info other = i->second;
166 if (other.owner != owner) {
167 base::debug::Alias(&other);
168 CHECK(false);
169 }
170
171 map_.erase(i);
172 }
173
174 void ActiveVerifier::Disable() {
175 enabled_ = false;
176 }
177
178 void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
179 AutoNativeLock lock(*lock_);
180 if (closing_)
181 return;
182
183 HandleMap::iterator i = map_.find(handle);
184 if (i == map_.end())
185 return;
186
187 Info other = i->second;
188 base::debug::Alias(&other);
189 CHECK(false);
190 }
191
71 } // namespace 192 } // namespace
72 193
194 void* GetHandleVerifier() {
195 return g_active_verifier;
196 }
197
73 namespace base { 198 namespace base {
74 namespace win { 199 namespace win {
75 200
76 // Static. 201 // Static.
77 bool HandleTraits::CloseHandle(HANDLE handle) { 202 bool HandleTraits::CloseHandle(HANDLE handle) {
78 if (!g_verifier_enabled) 203 if (!g_active_verifier)
79 return CloseHandleWrapper(handle); 204 ActiveVerifier::InstallVerifier();
80 205
81 AutoNativeLock lock(g_lock.Get()); 206 return g_active_verifier->CloseHandle(handle);
82 g_closing = true;
83 CloseHandleWrapper(handle);
84 g_closing = false;
85
86 return true;
87 } 207 }
88 208
89 // Static. 209 // Static.
90 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, 210 void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
91 const void* pc1, const void* pc2) { 211 const void* pc1, const void* pc2) {
92 if (!g_verifier_enabled) 212 if (!g_active_verifier)
93 return; 213 ActiveVerifier::InstallVerifier();
94 214
95 // Grab the thread id before the lock. 215 return g_active_verifier->StartTracking(handle, owner, pc1, pc2);
cpu_(ooo_6.6-7.5) 2015/04/02 20:49:10 so we always do the pattern of 212-123 How about
rvargas (doing something else) 2015/04/02 21:26:31 Done.
96 DWORD thread_id = GetCurrentThreadId();
97
98 AutoNativeLock lock(g_lock.Get());
99
100 Info handle_info = { owner, pc1, pc2, thread_id };
101 std::pair<HANDLE, Info> item(handle, handle_info);
102 std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item);
103 if (!result.second) {
104 Info other = result.first->second;
105 debug::Alias(&other);
106 CHECK(false);
107 }
108 } 216 }
109 217
110 // Static. 218 // Static.
111 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, 219 void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
112 const void* pc1, const void* pc2) { 220 const void* pc1, const void* pc2) {
113 if (!g_verifier_enabled) 221 if (!g_active_verifier)
114 return; 222 ActiveVerifier::InstallVerifier();
115 223
116 AutoNativeLock lock(g_lock.Get()); 224 return g_active_verifier->StopTracking(handle, owner, pc1, pc2);
117 HandleMap::iterator i = g_handle_map.Get().find(handle);
118 if (i == g_handle_map.Get().end())
119 CHECK(false);
120
121 Info other = i->second;
122 if (other.owner != owner) {
123 debug::Alias(&other);
124 CHECK(false);
125 }
126
127 g_handle_map.Get().erase(i);
128 } 225 }
129 226
130 void DisableHandleVerifier() { 227 void DisableHandleVerifier() {
131 g_verifier_enabled = false; 228 if (!g_active_verifier)
229 ActiveVerifier::InstallVerifier();
230
231 return g_active_verifier->Disable();
132 } 232 }
133 233
134 void OnHandleBeingClosed(HANDLE handle) { 234 void OnHandleBeingClosed(HANDLE handle) {
135 AutoNativeLock lock(g_lock.Get()); 235 if (!g_active_verifier)
136 if (g_closing) 236 ActiveVerifier::InstallVerifier();
137 return;
138 237
139 HandleMap::iterator i = g_handle_map.Get().find(handle); 238 return g_active_verifier->OnHandleBeingClosed(handle);
140 if (i == g_handle_map.Get().end())
141 return;
142
143 Info other = i->second;
144 debug::Alias(&other);
145 CHECK(false);
146 } 239 }
147 240
148 } // namespace win 241 } // namespace win
149 } // namespace base 242 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698