Commit a63b03e2d2477586440741677ecac45bcf28d7b1

Authored by Chris Wilson
Committed by Ingo Molnar
1 parent 11c8f01b42

mutex: Always clear owner field upon mutex_unlock()

Currently if DEBUG_MUTEXES is enabled, the mutex->owner field is only
cleared iff debug_locks is active. This exposes a race to other users of
the field where the mutex->owner may be still set to a stale value,
potentially upsetting mutex_spin_on_owner() among others.

References: https://bugs.freedesktop.org/show_bug.cgi?id=87955
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Davidlohr Bueso <dave@stgolabs.net>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/1420540175-30204-1-git-send-email-chris@chris-wilson.co.uk
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

kernel/locking/mutex-debug.c
1 /* 1 /*
2 * kernel/mutex-debug.c 2 * kernel/mutex-debug.c
3 * 3 *
4 * Debugging code for mutexes 4 * Debugging code for mutexes
5 * 5 *
6 * Started by Ingo Molnar: 6 * Started by Ingo Molnar:
7 * 7 *
8 * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> 8 * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
9 * 9 *
10 * lock debugging, locking tree, deadlock detection started by: 10 * lock debugging, locking tree, deadlock detection started by:
11 * 11 *
12 * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey 12 * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey
13 * Released under the General Public License (GPL). 13 * Released under the General Public License (GPL).
14 */ 14 */
15 #include <linux/mutex.h> 15 #include <linux/mutex.h>
16 #include <linux/delay.h> 16 #include <linux/delay.h>
17 #include <linux/export.h> 17 #include <linux/export.h>
18 #include <linux/poison.h> 18 #include <linux/poison.h>
19 #include <linux/sched.h> 19 #include <linux/sched.h>
20 #include <linux/spinlock.h> 20 #include <linux/spinlock.h>
21 #include <linux/kallsyms.h> 21 #include <linux/kallsyms.h>
22 #include <linux/interrupt.h> 22 #include <linux/interrupt.h>
23 #include <linux/debug_locks.h> 23 #include <linux/debug_locks.h>
24 24
25 #include "mutex-debug.h" 25 #include "mutex-debug.h"
26 26
27 /* 27 /*
28 * Must be called with lock->wait_lock held. 28 * Must be called with lock->wait_lock held.
29 */ 29 */
30 void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter) 30 void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter)
31 { 31 {
32 memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter)); 32 memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter));
33 waiter->magic = waiter; 33 waiter->magic = waiter;
34 INIT_LIST_HEAD(&waiter->list); 34 INIT_LIST_HEAD(&waiter->list);
35 } 35 }
36 36
37 void debug_mutex_wake_waiter(struct mutex *lock, struct mutex_waiter *waiter) 37 void debug_mutex_wake_waiter(struct mutex *lock, struct mutex_waiter *waiter)
38 { 38 {
39 SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock)); 39 SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock));
40 DEBUG_LOCKS_WARN_ON(list_empty(&lock->wait_list)); 40 DEBUG_LOCKS_WARN_ON(list_empty(&lock->wait_list));
41 DEBUG_LOCKS_WARN_ON(waiter->magic != waiter); 41 DEBUG_LOCKS_WARN_ON(waiter->magic != waiter);
42 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); 42 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
43 } 43 }
44 44
45 void debug_mutex_free_waiter(struct mutex_waiter *waiter) 45 void debug_mutex_free_waiter(struct mutex_waiter *waiter)
46 { 46 {
47 DEBUG_LOCKS_WARN_ON(!list_empty(&waiter->list)); 47 DEBUG_LOCKS_WARN_ON(!list_empty(&waiter->list));
48 memset(waiter, MUTEX_DEBUG_FREE, sizeof(*waiter)); 48 memset(waiter, MUTEX_DEBUG_FREE, sizeof(*waiter));
49 } 49 }
50 50
51 void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, 51 void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
52 struct thread_info *ti) 52 struct thread_info *ti)
53 { 53 {
54 SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock)); 54 SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock));
55 55
56 /* Mark the current thread as blocked on the lock: */ 56 /* Mark the current thread as blocked on the lock: */
57 ti->task->blocked_on = waiter; 57 ti->task->blocked_on = waiter;
58 } 58 }
59 59
60 void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, 60 void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
61 struct thread_info *ti) 61 struct thread_info *ti)
62 { 62 {
63 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); 63 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
64 DEBUG_LOCKS_WARN_ON(waiter->task != ti->task); 64 DEBUG_LOCKS_WARN_ON(waiter->task != ti->task);
65 DEBUG_LOCKS_WARN_ON(ti->task->blocked_on != waiter); 65 DEBUG_LOCKS_WARN_ON(ti->task->blocked_on != waiter);
66 ti->task->blocked_on = NULL; 66 ti->task->blocked_on = NULL;
67 67
68 list_del_init(&waiter->list); 68 list_del_init(&waiter->list);
69 waiter->task = NULL; 69 waiter->task = NULL;
70 } 70 }
71 71
72 void debug_mutex_unlock(struct mutex *lock) 72 void debug_mutex_unlock(struct mutex *lock)
73 { 73 {
74 if (likely(debug_locks)) { 74 if (likely(debug_locks)) {
75 DEBUG_LOCKS_WARN_ON(lock->magic != lock); 75 DEBUG_LOCKS_WARN_ON(lock->magic != lock);
76 76
77 if (!lock->owner) 77 if (!lock->owner)
78 DEBUG_LOCKS_WARN_ON(!lock->owner); 78 DEBUG_LOCKS_WARN_ON(!lock->owner);
79 else 79 else
80 DEBUG_LOCKS_WARN_ON(lock->owner != current); 80 DEBUG_LOCKS_WARN_ON(lock->owner != current);
81 81
82 DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next); 82 DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
83 mutex_clear_owner(lock);
84 } 83 }
85 84
86 /* 85 /*
87 * __mutex_slowpath_needs_to_unlock() is explicitly 0 for debug 86 * __mutex_slowpath_needs_to_unlock() is explicitly 0 for debug
88 * mutexes so that we can do it here after we've verified state. 87 * mutexes so that we can do it here after we've verified state.
89 */ 88 */
89 mutex_clear_owner(lock);
90 atomic_set(&lock->count, 1); 90 atomic_set(&lock->count, 1);
91 } 91 }
92 92
93 void debug_mutex_init(struct mutex *lock, const char *name, 93 void debug_mutex_init(struct mutex *lock, const char *name,
94 struct lock_class_key *key) 94 struct lock_class_key *key)
95 { 95 {
96 #ifdef CONFIG_DEBUG_LOCK_ALLOC 96 #ifdef CONFIG_DEBUG_LOCK_ALLOC
97 /* 97 /*
98 * Make sure we are not reinitializing a held lock: 98 * Make sure we are not reinitializing a held lock:
99 */ 99 */
100 debug_check_no_locks_freed((void *)lock, sizeof(*lock)); 100 debug_check_no_locks_freed((void *)lock, sizeof(*lock));
101 lockdep_init_map(&lock->dep_map, name, key, 0); 101 lockdep_init_map(&lock->dep_map, name, key, 0);
102 #endif 102 #endif
103 lock->magic = lock; 103 lock->magic = lock;
104 } 104 }
105 105
106 /*** 106 /***
107 * mutex_destroy - mark a mutex unusable 107 * mutex_destroy - mark a mutex unusable
108 * @lock: the mutex to be destroyed 108 * @lock: the mutex to be destroyed
109 * 109 *
110 * This function marks the mutex uninitialized, and any subsequent 110 * This function marks the mutex uninitialized, and any subsequent
111 * use of the mutex is forbidden. The mutex must not be locked when 111 * use of the mutex is forbidden. The mutex must not be locked when
112 * this function is called. 112 * this function is called.
113 */ 113 */
114 void mutex_destroy(struct mutex *lock) 114 void mutex_destroy(struct mutex *lock)
115 { 115 {
116 DEBUG_LOCKS_WARN_ON(mutex_is_locked(lock)); 116 DEBUG_LOCKS_WARN_ON(mutex_is_locked(lock));
117 lock->magic = NULL; 117 lock->magic = NULL;
118 } 118 }
119 119
120 EXPORT_SYMBOL_GPL(mutex_destroy); 120 EXPORT_SYMBOL_GPL(mutex_destroy);