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(OS_NACL) || defined(OS_ANDROID)
26 # define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0
27 #else
28 # define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1
29 #endif
30
LockImpl()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
~LockImpl()52 LockImpl::~LockImpl() {
53 int rv = pthread_mutex_destroy(&native_handle_);
54 DCHECK_EQ(rv, 0) << ". " << strerror(rv);
55 }
56
Try()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
Lock()63 void LockImpl::Lock() {
64 int rv = pthread_mutex_lock(&native_handle_);
65 DCHECK_EQ(rv, 0) << ". " << strerror(rv);
66 }
67
Unlock()68 void LockImpl::Unlock() {
69 int rv = pthread_mutex_unlock(&native_handle_);
70 DCHECK_EQ(rv, 0) << ". " << strerror(rv);
71 }
72
73 // static
PriorityInheritanceAvailable()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