scoped_handle_verifier.cc (9243B)
1 // Copyright 2018 The Chromium Authors 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_verifier.h" 6 7 #include <windows.h> 8 9 #include <stddef.h> 10 11 #include <unordered_map> 12 #include <utility> 13 14 #include "base/auto_reset.h" 15 #include "base/compiler_specific.h" 16 #include "base/debug/alias.h" 17 #include "base/debug/stack_trace.h" 18 #include "base/memory/raw_ref.h" 19 #include "base/synchronization/lock_impl.h" 20 #include "base/trace_event/base_tracing.h" 21 #include "base/win/base_win_buildflags.h" 22 #include "base/win/current_module.h" 23 #include "base/win/scoped_handle.h" 24 #include "third_party/abseil-cpp/absl/base/attributes.h" 25 26 extern "C" { 27 __declspec(dllexport) void* GetHandleVerifier(); 28 29 void* GetHandleVerifier() { 30 return base::win::internal::ScopedHandleVerifier::Get(); 31 } 32 } // extern C 33 34 namespace base { 35 namespace win { 36 namespace internal { 37 38 namespace { 39 40 ScopedHandleVerifier* g_active_verifier = nullptr; 41 ABSL_CONST_INIT thread_local bool closing = false; 42 using GetHandleVerifierFn = void* (*)(); 43 using HandleMap = 44 std::unordered_map<HANDLE, ScopedHandleVerifierInfo, HandleHash>; 45 using NativeLock = base::internal::LockImpl; 46 47 NOINLINE void ReportErrorOnScopedHandleOperation( 48 const debug::StackTrace& creation_stack, 49 HandleOperation operation) { 50 auto creation_stack_copy = creation_stack; 51 debug::Alias(&creation_stack_copy); 52 debug::Alias(&operation); 53 CHECK(false) << operation; 54 __builtin_unreachable(); 55 } 56 57 NOINLINE void ReportErrorOnScopedHandleOperation( 58 const debug::StackTrace& creation_stack, 59 const ScopedHandleVerifierInfo& other, 60 HandleOperation operation) { 61 auto other_stack_copy = *other.stack; 62 debug::Alias(&other_stack_copy); 63 auto creation_stack_copy = creation_stack; 64 debug::Alias(&creation_stack_copy); 65 debug::Alias(&operation); 66 CHECK(false) << operation; 67 __builtin_unreachable(); 68 } 69 70 } // namespace 71 72 // Simple automatic locking using a native critical section so it supports 73 // recursive locking. 74 class AutoNativeLock { 75 public: 76 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { lock_->Lock(); } 77 78 AutoNativeLock(const AutoNativeLock&) = delete; 79 AutoNativeLock& operator=(const AutoNativeLock&) = delete; 80 81 ~AutoNativeLock() { lock_->Unlock(); } 82 83 private: 84 const raw_ref<NativeLock> lock_; 85 }; 86 87 ScopedHandleVerifierInfo::ScopedHandleVerifierInfo( 88 const void* owner, 89 const void* pc1, 90 const void* pc2, 91 std::unique_ptr<debug::StackTrace> stack, 92 DWORD thread_id) 93 : owner(owner), 94 pc1(pc1), 95 pc2(pc2), 96 stack(std::move(stack)), 97 thread_id(thread_id) {} 98 99 ScopedHandleVerifierInfo::~ScopedHandleVerifierInfo() = default; 100 101 ScopedHandleVerifierInfo::ScopedHandleVerifierInfo( 102 ScopedHandleVerifierInfo&&) noexcept = default; 103 ScopedHandleVerifierInfo& ScopedHandleVerifierInfo::operator=( 104 ScopedHandleVerifierInfo&&) noexcept = default; 105 106 ScopedHandleVerifier::ScopedHandleVerifier(bool enabled) 107 : enabled_(enabled), lock_(GetLock()) {} 108 109 // static 110 ScopedHandleVerifier* ScopedHandleVerifier::Get() { 111 if (!g_active_verifier) 112 ScopedHandleVerifier::InstallVerifier(); 113 114 return g_active_verifier; 115 } 116 117 bool CloseHandleWrapper(HANDLE handle) { 118 if (!::CloseHandle(handle)) 119 // Making this DCHECK on non-Nighly as we are hitting this frequently, 120 // looks like we are closing handles twice somehow. See bug 1564899. 121 #if defined(NIGHTLY_BUILD) 122 CHECK(false) << "CloseHandle failed"; 123 #else 124 DCHECK(false) << "CloseHandle failed"; 125 #endif 126 return true; 127 } 128 129 // Assigns the g_active_verifier global within the ScopedHandleVerifier lock. 130 // If |existing_verifier| is non-null then |enabled| is ignored. 131 // static 132 void ScopedHandleVerifier::ThreadSafeAssignOrCreateScopedHandleVerifier( 133 ScopedHandleVerifier* existing_verifier, 134 bool enabled) { 135 AutoNativeLock lock(*GetLock()); 136 // Another thread in this module might be trying to assign the global 137 // verifier, so check that within the lock here. 138 if (g_active_verifier) 139 return; 140 g_active_verifier = 141 existing_verifier ? existing_verifier : new ScopedHandleVerifier(enabled); 142 } 143 144 // static 145 void ScopedHandleVerifier::InstallVerifier() { 146 #if BUILDFLAG(SINGLE_MODULE_MODE_HANDLE_VERIFIER) 147 // Component build has one Active Verifier per module. 148 ThreadSafeAssignOrCreateScopedHandleVerifier(nullptr, true); 149 #else 150 // If you are reading this, wondering why your process seems deadlocked, take 151 // a look at your DllMain code and remove things that should not be done 152 // there, like doing whatever gave you that nice windows handle you are trying 153 // to store in a ScopedHandle. 154 HMODULE main_module = ::GetModuleHandle(NULL); 155 GetHandleVerifierFn get_handle_verifier = 156 reinterpret_cast<GetHandleVerifierFn>( 157 ::GetProcAddress(main_module, "GetHandleVerifier")); 158 159 // This should only happen if running in a DLL is linked with base but the 160 // hosting EXE is not. In this case, create a ScopedHandleVerifier for the 161 // current module but leave it disabled. 162 if (!get_handle_verifier) { 163 ThreadSafeAssignOrCreateScopedHandleVerifier(nullptr, false); 164 return; 165 } 166 167 // Check if in the main module. 168 if (get_handle_verifier == GetHandleVerifier) { 169 ThreadSafeAssignOrCreateScopedHandleVerifier(nullptr, true); 170 return; 171 } 172 173 ScopedHandleVerifier* main_module_verifier = 174 reinterpret_cast<ScopedHandleVerifier*>(get_handle_verifier()); 175 176 // Main module should always on-demand create a verifier. 177 DCHECK(main_module_verifier); 178 179 ThreadSafeAssignOrCreateScopedHandleVerifier(main_module_verifier, false); 180 #endif 181 } 182 183 bool ScopedHandleVerifier::CloseHandle(HANDLE handle) { 184 if (!enabled_) 185 return CloseHandleWrapper(handle); 186 187 const AutoReset<bool> resetter(&closing, true); 188 CloseHandleWrapper(handle); 189 190 return true; 191 } 192 193 // static 194 NativeLock* ScopedHandleVerifier::GetLock() { 195 static auto* native_lock = new NativeLock(); 196 return native_lock; 197 } 198 199 void ScopedHandleVerifier::StartTracking(HANDLE handle, 200 const void* owner, 201 const void* pc1, 202 const void* pc2) { 203 if (enabled_) 204 StartTrackingImpl(handle, owner, pc1, pc2); 205 } 206 207 void ScopedHandleVerifier::StopTracking(HANDLE handle, 208 const void* owner, 209 const void* pc1, 210 const void* pc2) { 211 if (enabled_) 212 StopTrackingImpl(handle, owner, pc1, pc2); 213 } 214 215 void ScopedHandleVerifier::Disable() { 216 enabled_ = false; 217 } 218 219 void ScopedHandleVerifier::OnHandleBeingClosed(HANDLE handle, 220 HandleOperation operation) { 221 if (enabled_) 222 OnHandleBeingClosedImpl(handle, operation); 223 } 224 225 HMODULE ScopedHandleVerifier::GetModule() const { 226 return CURRENT_MODULE(); 227 } 228 229 NOINLINE void ScopedHandleVerifier::StartTrackingImpl(HANDLE handle, 230 const void* owner, 231 const void* pc1, 232 const void* pc2) { 233 // Grab the thread id before the lock. 234 DWORD thread_id = GetCurrentThreadId(); 235 236 // Grab the thread stacktrace before the lock. 237 auto stacktrace = std::make_unique<debug::StackTrace>(); 238 239 AutoNativeLock lock(*lock_); 240 std::pair<HandleMap::iterator, bool> result = map_.emplace( 241 handle, ScopedHandleVerifierInfo{owner, pc1, pc2, std::move(stacktrace), 242 thread_id}); 243 if (!result.second) { 244 // Attempt to start tracking already tracked handle. 245 ReportErrorOnScopedHandleOperation(creation_stack_, result.first->second, 246 HandleOperation::kHandleAlreadyTracked); 247 } 248 } 249 250 NOINLINE void ScopedHandleVerifier::StopTrackingImpl(HANDLE handle, 251 const void* owner, 252 const void* pc1, 253 const void* pc2) { 254 AutoNativeLock lock(*lock_); 255 HandleMap::iterator i = map_.find(handle); 256 if (i == map_.end()) { 257 // Attempting to close an untracked handle. 258 ReportErrorOnScopedHandleOperation(creation_stack_, 259 HandleOperation::kCloseHandleNotTracked); 260 } 261 262 if (i->second.owner != owner) { 263 // Attempting to close a handle not owned by opener. 264 ReportErrorOnScopedHandleOperation(creation_stack_, i->second, 265 HandleOperation::kCloseHandleNotOwner); 266 } 267 268 map_.erase(i); 269 } 270 271 NOINLINE void ScopedHandleVerifier::OnHandleBeingClosedImpl( 272 HANDLE handle, 273 HandleOperation operation) { 274 if (closing) { 275 return; 276 } 277 278 AutoNativeLock lock(*lock_); 279 HandleMap::iterator i = map_.find(handle); 280 if (i != map_.end()) { 281 // CloseHandle called on tracked handle. 282 ReportErrorOnScopedHandleOperation(creation_stack_, i->second, operation); 283 } 284 } 285 286 HMODULE GetHandleVerifierModuleForTesting() { 287 return g_active_verifier->GetModule(); 288 } 289 290 } // namespace internal 291 } // namespace win 292 } // namespace base