1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 <errno.h> 8 #include <string.h> 9 10 #include "base/debug/activity_tracker.h" 11 #include "base/logging.h" 12 #include "base/synchronization/lock.h" 13 14 namespace base { 15 namespace internal { 16 17 // Determines which platforms can consider using priority inheritance locks. Use 18 // this define for platform code that may not compile if priority inheritance 19 // locks aren't available. For this platform code, 20 // PRIORITY_INHERITANCE_LOCKS_POSSIBLE() is a necessary but insufficient check. 21 // Lock::PriorityInheritanceAvailable still must be checked as the code may 22 // compile but the underlying platform still may not correctly support priority 23 // inheritance locks. 24 #if defined(OS_NACL) || defined(OS_ANDROID) 25 #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0 26 #else 27 #define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1 28 #endif 29 30 LockImpl::LockImpl() { 31 pthread_mutexattr_t mta; 32 int rv = pthread_mutexattr_init(&mta); 33 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 34 #if PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 35 if (PriorityInheritanceAvailable()) { 36 rv = pthread_mutexattr_setprotocol(&mta, PTHREAD_PRIO_INHERIT); 37 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 38 } 39 #endif 40 #ifndef NDEBUG 41 // In debug, setup attributes for lock error checking. 42 rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); 43 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 44 #endif 45 rv = pthread_mutex_init(&native_handle_, &mta); 46 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 47 rv = pthread_mutexattr_destroy(&mta); 48 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 49 } 50 51 LockImpl::~LockImpl() { 52 int rv = pthread_mutex_destroy(&native_handle_); 53 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 54 } 55 56 bool LockImpl::Try() { 57 int rv = pthread_mutex_trylock(&native_handle_); 58 DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); 59 return rv == 0; 60 } 61 62 void LockImpl::Lock() { 63 base::debug::ScopedLockAcquireActivity lock_activity(this); 64 int rv = pthread_mutex_lock(&native_handle_); 65 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 66 } 67 68 void LockImpl::Unlock() { 69 int rv = pthread_mutex_unlock(&native_handle_); 70 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 71 } 72 73 // static 74 bool LockImpl::PriorityInheritanceAvailable() { 75 #if PRIORITY_INHERITANCE_LOCKS_POSSIBLE() && defined(OS_MACOSX) 76 return true; 77 #else 78 // Security concerns prevent the use of priority inheritance mutexes on Linux. 79 // * CVE-2010-0622 - wake_futex_pi unlocks incorrect, possible DoS. 80 // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0622 81 // * CVE-2012-6647 - Linux < 3.5.1, futex_wait_requeue_pi possible DoS. 82 // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6647 83 // * CVE-2014-3153 - Linux <= 3.14.5, futex_requeue, privilege escalation. 84 // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3153 85 // 86 // If the above were all addressed, we still need a runtime check to deal with 87 // the bug below. 88 // * glibc Bug 14652: https://sourceware.org/bugzilla/show_bug.cgi?id=14652 89 // Fixed in glibc 2.17. 90 // Priority inheritance mutexes may deadlock with condition variables 91 // during recacquisition of the mutex after the condition variable is 92 // signalled. 93 return false; 94 #endif 95 } 96 97 } // namespace internal 98 } // namespace base 99