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