1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 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/synchronization/lock_impl.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <ostream>
8*6777b538SAndroid Build Coastguard Worker #include <string>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/posix/safe_strerror.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/synchronization_buildflags.h"
14*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker namespace internal {
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace {
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
AdditionalHintForSystemErrorCode(int error_code)22*6777b538SAndroid Build Coastguard Worker const char* AdditionalHintForSystemErrorCode(int error_code) {
23*6777b538SAndroid Build Coastguard Worker switch (error_code) {
24*6777b538SAndroid Build Coastguard Worker case EINVAL:
25*6777b538SAndroid Build Coastguard Worker return "Hint: This is often related to a use-after-free.";
26*6777b538SAndroid Build Coastguard Worker default:
27*6777b538SAndroid Build Coastguard Worker return "";
28*6777b538SAndroid Build Coastguard Worker }
29*6777b538SAndroid Build Coastguard Worker }
30*6777b538SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON()
31*6777b538SAndroid Build Coastguard Worker
SystemErrorCodeToString(int error_code)32*6777b538SAndroid Build Coastguard Worker std::string SystemErrorCodeToString(int error_code) {
33*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
34*6777b538SAndroid Build Coastguard Worker return base::safe_strerror(error_code) + ". " +
35*6777b538SAndroid Build Coastguard Worker AdditionalHintForSystemErrorCode(error_code);
36*6777b538SAndroid Build Coastguard Worker #else // DCHECK_IS_ON()
37*6777b538SAndroid Build Coastguard Worker return std::string();
38*6777b538SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON()
39*6777b538SAndroid Build Coastguard Worker }
40*6777b538SAndroid Build Coastguard Worker
41*6777b538SAndroid Build Coastguard Worker } // namespace
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
44*6777b538SAndroid Build Coastguard Worker // These are out-of-line so that the .h file doesn't have to include ostream.
dcheck_trylock_result(int rv)45*6777b538SAndroid Build Coastguard Worker void dcheck_trylock_result(int rv) {
46*6777b538SAndroid Build Coastguard Worker DCHECK(rv == 0 || rv == EBUSY)
47*6777b538SAndroid Build Coastguard Worker << ". " << base::internal::SystemErrorCodeToString(rv);
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker
dcheck_unlock_result(int rv)50*6777b538SAndroid Build Coastguard Worker void dcheck_unlock_result(int rv) {
51*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << strerror(rv);
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker #endif
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker // Determines which platforms can consider using priority inheritance locks. Use
56*6777b538SAndroid Build Coastguard Worker // this define for platform code that may not compile if priority inheritance
57*6777b538SAndroid Build Coastguard Worker // locks aren't available. For this platform code,
58*6777b538SAndroid Build Coastguard Worker // PRIORITY_INHERITANCE_LOCKS_POSSIBLE() is a necessary but insufficient check.
59*6777b538SAndroid Build Coastguard Worker // Lock::PriorityInheritanceAvailable still must be checked as the code may
60*6777b538SAndroid Build Coastguard Worker // compile but the underlying platform still may not correctly support priority
61*6777b538SAndroid Build Coastguard Worker // inheritance locks.
62*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_NACL) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
63*6777b538SAndroid Build Coastguard Worker #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0
64*6777b538SAndroid Build Coastguard Worker #else
65*6777b538SAndroid Build Coastguard Worker #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1
66*6777b538SAndroid Build Coastguard Worker #endif
67*6777b538SAndroid Build Coastguard Worker
LockImpl()68*6777b538SAndroid Build Coastguard Worker LockImpl::LockImpl() {
69*6777b538SAndroid Build Coastguard Worker pthread_mutexattr_t mta;
70*6777b538SAndroid Build Coastguard Worker int rv = pthread_mutexattr_init(&mta);
71*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
72*6777b538SAndroid Build Coastguard Worker #if PRIORITY_INHERITANCE_LOCKS_POSSIBLE()
73*6777b538SAndroid Build Coastguard Worker if (PriorityInheritanceAvailable()) {
74*6777b538SAndroid Build Coastguard Worker rv = pthread_mutexattr_setprotocol(&mta, PTHREAD_PRIO_INHERIT);
75*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker #endif
78*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
79*6777b538SAndroid Build Coastguard Worker // In debug, setup attributes for lock error checking.
80*6777b538SAndroid Build Coastguard Worker rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
81*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
82*6777b538SAndroid Build Coastguard Worker #endif
83*6777b538SAndroid Build Coastguard Worker rv = pthread_mutex_init(&native_handle_, &mta);
84*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
85*6777b538SAndroid Build Coastguard Worker rv = pthread_mutexattr_destroy(&mta);
86*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
~LockImpl()89*6777b538SAndroid Build Coastguard Worker LockImpl::~LockImpl() {
90*6777b538SAndroid Build Coastguard Worker int rv = pthread_mutex_destroy(&native_handle_);
91*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
LockInternal()94*6777b538SAndroid Build Coastguard Worker void LockImpl::LockInternal() {
95*6777b538SAndroid Build Coastguard Worker int rv = pthread_mutex_lock(&native_handle_);
96*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(rv, 0) << ". " << SystemErrorCodeToString(rv);
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker // static
PriorityInheritanceAvailable()100*6777b538SAndroid Build Coastguard Worker bool LockImpl::PriorityInheritanceAvailable() {
101*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_MUTEX_PRIORITY_INHERITANCE)
102*6777b538SAndroid Build Coastguard Worker return true;
103*6777b538SAndroid Build Coastguard Worker #elif PRIORITY_INHERITANCE_LOCKS_POSSIBLE() && BUILDFLAG(IS_APPLE)
104*6777b538SAndroid Build Coastguard Worker return true;
105*6777b538SAndroid Build Coastguard Worker #else
106*6777b538SAndroid Build Coastguard Worker // Security concerns prevent the use of priority inheritance mutexes on Linux.
107*6777b538SAndroid Build Coastguard Worker // * CVE-2010-0622 - Linux < 2.6.33-rc7, wake_futex_pi possible DoS.
108*6777b538SAndroid Build Coastguard Worker // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0622
109*6777b538SAndroid Build Coastguard Worker // * CVE-2012-6647 - Linux < 3.5.1, futex_wait_requeue_pi possible DoS.
110*6777b538SAndroid Build Coastguard Worker // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6647
111*6777b538SAndroid Build Coastguard Worker // * CVE-2014-3153 - Linux <= 3.14.5, futex_requeue, privilege escalation.
112*6777b538SAndroid Build Coastguard Worker // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3153
113*6777b538SAndroid Build Coastguard Worker //
114*6777b538SAndroid Build Coastguard Worker // If the above were all addressed, we still need a runtime check to deal with
115*6777b538SAndroid Build Coastguard Worker // the bug below.
116*6777b538SAndroid Build Coastguard Worker // * glibc Bug 14652: https://sourceware.org/bugzilla/show_bug.cgi?id=14652
117*6777b538SAndroid Build Coastguard Worker // Fixed in glibc 2.17.
118*6777b538SAndroid Build Coastguard Worker // Priority inheritance mutexes may deadlock with condition variables
119*6777b538SAndroid Build Coastguard Worker // during reacquisition of the mutex after the condition variable is
120*6777b538SAndroid Build Coastguard Worker // signalled.
121*6777b538SAndroid Build Coastguard Worker return false;
122*6777b538SAndroid Build Coastguard Worker #endif
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker } // namespace internal
126*6777b538SAndroid Build Coastguard Worker } // namespace base
127