lock_impl_posix.cc (3402B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 #include "base/lock_impl.h" 8 9 #include <errno.h> 10 #include <string.h> 11 12 #include "base/logging.h" 13 #include "base/lock.h" 14 15 namespace base { 16 namespace internal { 17 18 // Determines which platforms can consider using priority inheritance locks. Use 19 // this define for platform code that may not compile if priority inheritance 20 // locks aren't available. For this platform code, 21 // PRIORITY_INHERITANCE_LOCKS_POSSIBLE() is a necessary but insufficient check. 22 // Lock::PriorityInheritanceAvailable still must be checked as the code may 23 // compile but the underlying platform still may not correctly support priority 24 // inheritance locks. 25 #if defined(ANDROID) 26 # define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0 27 #else 28 # define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1 29 #endif 30 31 LockImpl::LockImpl() { 32 pthread_mutexattr_t mta; 33 int rv = pthread_mutexattr_init(&mta); 34 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 35 #if PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 36 if (PriorityInheritanceAvailable()) { 37 rv = pthread_mutexattr_setprotocol(&mta, PTHREAD_PRIO_INHERIT); 38 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 39 } 40 #endif 41 #ifndef NDEBUG 42 // In debug, setup attributes for lock error checking. 43 rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); 44 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 45 #endif 46 rv = pthread_mutex_init(&native_handle_, &mta); 47 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 48 rv = pthread_mutexattr_destroy(&mta); 49 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 50 } 51 52 LockImpl::~LockImpl() { 53 int rv = pthread_mutex_destroy(&native_handle_); 54 DCHECK_EQ(rv, 0) << ". " << strerror(rv); 55 } 56 57 bool LockImpl::Try() { 58 int rv = pthread_mutex_trylock(&native_handle_); 59 DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); 60 return rv == 0; 61 } 62 63 void LockImpl::Lock() { 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(XP_DARWIN) 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