1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/lock_impl.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <string>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include "base/debug/activity_tracker.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/posix/safe_strerror.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/synchronization_buildflags.h"
15*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker namespace base {
18*635a8641SAndroid Build Coastguard Worker namespace internal {
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker namespace {
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
AdditionalHintForSystemErrorCode(int error_code)23*635a8641SAndroid Build Coastguard Worker const char* AdditionalHintForSystemErrorCode(int error_code) {
24*635a8641SAndroid Build Coastguard Worker switch (error_code) {
25*635a8641SAndroid Build Coastguard Worker case EINVAL:
26*635a8641SAndroid Build Coastguard Worker return "Hint: This is often related to a use-after-free.";
27*635a8641SAndroid Build Coastguard Worker default:
28*635a8641SAndroid Build Coastguard Worker return "";
29*635a8641SAndroid Build Coastguard Worker }
30*635a8641SAndroid Build Coastguard Worker }
31*635a8641SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON()
32*635a8641SAndroid Build Coastguard Worker
SystemErrorCodeToString(int error_code)33*635a8641SAndroid Build Coastguard Worker std::string SystemErrorCodeToString(int error_code) {
34*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
35*635a8641SAndroid Build Coastguard Worker return base::safe_strerror(error_code) + ". " +
36*635a8641SAndroid Build Coastguard Worker AdditionalHintForSystemErrorCode(error_code);
37*635a8641SAndroid Build Coastguard Worker #else // DCHECK_IS_ON()
38*635a8641SAndroid Build Coastguard Worker return std::string();
39*635a8641SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON()
40*635a8641SAndroid Build Coastguard Worker }
41*635a8641SAndroid Build Coastguard Worker
42*635a8641SAndroid Build Coastguard Worker } // namespace
43*635a8641SAndroid Build Coastguard Worker
44*635a8641SAndroid Build Coastguard Worker // Determines which platforms can consider using priority inheritance locks. Use
45*635a8641SAndroid Build Coastguard Worker // this define for platform code that may not compile if priority inheritance
46*635a8641SAndroid Build Coastguard Worker // locks aren't available. For this platform code,
47*635a8641SAndroid Build Coastguard Worker // PRIORITY_INHERITANCE_LOCKS_POSSIBLE() is a necessary but insufficient check.
48*635a8641SAndroid Build Coastguard Worker // Lock::PriorityInheritanceAvailable still must be checked as the code may
49*635a8641SAndroid Build Coastguard Worker // compile but the underlying platform still may not correctly support priority
50*635a8641SAndroid Build Coastguard Worker // inheritance locks.
51*635a8641SAndroid Build Coastguard Worker #if defined(OS_NACL) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
52*635a8641SAndroid Build Coastguard Worker #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0
53*635a8641SAndroid Build Coastguard Worker #else
54*635a8641SAndroid Build Coastguard Worker #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1
55*635a8641SAndroid Build Coastguard Worker #endif
56*635a8641SAndroid Build Coastguard Worker
LockImpl()57*635a8641SAndroid Build Coastguard Worker LockImpl::LockImpl() {
58*635a8641SAndroid Build Coastguard Worker pthread_mutexattr_t mta;
59*635a8641SAndroid Build Coastguard Worker int rv = pthread_mutexattr_init(&mta);
60*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
61*635a8641SAndroid Build Coastguard Worker #if PRIORITY_INHERITANCE_LOCKS_POSSIBLE()
62*635a8641SAndroid Build Coastguard Worker if (PriorityInheritanceAvailable()) {
63*635a8641SAndroid Build Coastguard Worker rv = pthread_mutexattr_setprotocol(&mta, PTHREAD_PRIO_INHERIT);
64*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker #endif
67*635a8641SAndroid Build Coastguard Worker #ifndef NDEBUG
68*635a8641SAndroid Build Coastguard Worker // In debug, setup attributes for lock error checking.
69*635a8641SAndroid Build Coastguard Worker rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
70*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
71*635a8641SAndroid Build Coastguard Worker #endif
72*635a8641SAndroid Build Coastguard Worker rv = pthread_mutex_init(&native_handle_, &mta);
73*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
74*635a8641SAndroid Build Coastguard Worker rv = pthread_mutexattr_destroy(&mta);
75*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
76*635a8641SAndroid Build Coastguard Worker }
77*635a8641SAndroid Build Coastguard Worker
~LockImpl()78*635a8641SAndroid Build Coastguard Worker LockImpl::~LockImpl() {
79*635a8641SAndroid Build Coastguard Worker int rv = pthread_mutex_destroy(&native_handle_);
80*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
81*635a8641SAndroid Build Coastguard Worker }
82*635a8641SAndroid Build Coastguard Worker
Try()83*635a8641SAndroid Build Coastguard Worker bool LockImpl::Try() {
84*635a8641SAndroid Build Coastguard Worker int rv = pthread_mutex_trylock(&native_handle_);
85*635a8641SAndroid Build Coastguard Worker DCHECK(rv == 0 || rv == EBUSY) << ". " << SystemErrorCodeToString(rv);
86*635a8641SAndroid Build Coastguard Worker return rv == 0;
87*635a8641SAndroid Build Coastguard Worker }
88*635a8641SAndroid Build Coastguard Worker
Lock()89*635a8641SAndroid Build Coastguard Worker void LockImpl::Lock() {
90*635a8641SAndroid Build Coastguard Worker // The ScopedLockAcquireActivity below is relatively expensive and so its
91*635a8641SAndroid Build Coastguard Worker // actions can become significant due to the very large number of locks
92*635a8641SAndroid Build Coastguard Worker // that tend to be used throughout the build. To avoid this cost in the
93*635a8641SAndroid Build Coastguard Worker // vast majority of the calls, simply "try" the lock first and only do the
94*635a8641SAndroid Build Coastguard Worker // (tracked) blocking call if that fails. Since "try" itself is a system
95*635a8641SAndroid Build Coastguard Worker // call, and thus also somewhat expensive, don't bother with it unless
96*635a8641SAndroid Build Coastguard Worker // tracking is actually enabled.
97*635a8641SAndroid Build Coastguard Worker if (base::debug::GlobalActivityTracker::IsEnabled())
98*635a8641SAndroid Build Coastguard Worker if (Try())
99*635a8641SAndroid Build Coastguard Worker return;
100*635a8641SAndroid Build Coastguard Worker
101*635a8641SAndroid Build Coastguard Worker base::debug::ScopedLockAcquireActivity lock_activity(this);
102*635a8641SAndroid Build Coastguard Worker int rv = pthread_mutex_lock(&native_handle_);
103*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
106*635a8641SAndroid Build Coastguard Worker // static
PriorityInheritanceAvailable()107*635a8641SAndroid Build Coastguard Worker bool LockImpl::PriorityInheritanceAvailable() {
108*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_MUTEX_PRIORITY_INHERITANCE)
109*635a8641SAndroid Build Coastguard Worker return true;
110*635a8641SAndroid Build Coastguard Worker #elif PRIORITY_INHERITANCE_LOCKS_POSSIBLE() && defined(OS_MACOSX)
111*635a8641SAndroid Build Coastguard Worker return true;
112*635a8641SAndroid Build Coastguard Worker #else
113*635a8641SAndroid Build Coastguard Worker // Security concerns prevent the use of priority inheritance mutexes on Linux.
114*635a8641SAndroid Build Coastguard Worker // * CVE-2010-0622 - Linux < 2.6.33-rc7, wake_futex_pi possible DoS.
115*635a8641SAndroid Build Coastguard Worker // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0622
116*635a8641SAndroid Build Coastguard Worker // * CVE-2012-6647 - Linux < 3.5.1, futex_wait_requeue_pi possible DoS.
117*635a8641SAndroid Build Coastguard Worker // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6647
118*635a8641SAndroid Build Coastguard Worker // * CVE-2014-3153 - Linux <= 3.14.5, futex_requeue, privilege escalation.
119*635a8641SAndroid Build Coastguard Worker // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3153
120*635a8641SAndroid Build Coastguard Worker //
121*635a8641SAndroid Build Coastguard Worker // If the above were all addressed, we still need a runtime check to deal with
122*635a8641SAndroid Build Coastguard Worker // the bug below.
123*635a8641SAndroid Build Coastguard Worker // * glibc Bug 14652: https://sourceware.org/bugzilla/show_bug.cgi?id=14652
124*635a8641SAndroid Build Coastguard Worker // Fixed in glibc 2.17.
125*635a8641SAndroid Build Coastguard Worker // Priority inheritance mutexes may deadlock with condition variables
126*635a8641SAndroid Build Coastguard Worker // during reacquisition of the mutex after the condition variable is
127*635a8641SAndroid Build Coastguard Worker // signalled.
128*635a8641SAndroid Build Coastguard Worker return false;
129*635a8641SAndroid Build Coastguard Worker #endif
130*635a8641SAndroid Build Coastguard Worker }
131*635a8641SAndroid Build Coastguard Worker
132*635a8641SAndroid Build Coastguard Worker } // namespace internal
133*635a8641SAndroid Build Coastguard Worker } // namespace base
134