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