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