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