]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.35.9/futex-fix-errors-in-nested-key-ref-counting.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 2.6.35.9 / futex-fix-errors-in-nested-key-ref-counting.patch
1 From 7ada876a8703f23befbb20a7465a702ee39b1704 Mon Sep 17 00:00:00 2001
2 From: Darren Hart <dvhart@linux.intel.com>
3 Date: Sun, 17 Oct 2010 08:35:04 -0700
4 Subject: futex: Fix errors in nested key ref-counting
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Darren Hart <dvhart@linux.intel.com>
10
11 commit 7ada876a8703f23befbb20a7465a702ee39b1704 upstream.
12
13 futex_wait() is leaking key references due to futex_wait_setup()
14 acquiring an additional reference via the queue_lock() routine. The
15 nested key ref-counting has been masking bugs and complicating code
16 analysis. queue_lock() is only called with a previously ref-counted
17 key, so remove the additional ref-counting from the queue_(un)lock()
18 functions.
19
20 Also futex_wait_requeue_pi() drops one key reference too many in
21 unqueue_me_pi(). Remove the key reference handling from
22 unqueue_me_pi(). This was paired with a queue_lock() in
23 futex_lock_pi(), so the count remains unchanged.
24
25 Document remaining nested key ref-counting sites.
26
27 Signed-off-by: Darren Hart <dvhart@linux.intel.com>
28 Reported-and-tested-by: Matthieu Fertré<matthieu.fertre@kerlabs.com>
29 Reported-by: Louis Rilling<louis.rilling@kerlabs.com>
30 Cc: Peter Zijlstra <peterz@infradead.org>
31 Cc: Eric Dumazet <eric.dumazet@gmail.com>
32 Cc: John Kacur <jkacur@redhat.com>
33 Cc: Rusty Russell <rusty@rustcorp.com.au>
34 LKML-Reference: <4CBB17A8.70401@linux.intel.com>
35 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
36 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
37
38 ---
39 kernel/futex.c | 31 ++++++++++++++++---------------
40 1 file changed, 16 insertions(+), 15 deletions(-)
41
42 --- a/kernel/futex.c
43 +++ b/kernel/futex.c
44 @@ -1363,7 +1363,6 @@ static inline struct futex_hash_bucket *
45 {
46 struct futex_hash_bucket *hb;
47
48 - get_futex_key_refs(&q->key);
49 hb = hash_futex(&q->key);
50 q->lock_ptr = &hb->lock;
51
52 @@ -1375,7 +1374,6 @@ static inline void
53 queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
54 {
55 spin_unlock(&hb->lock);
56 - drop_futex_key_refs(&q->key);
57 }
58
59 /**
60 @@ -1480,8 +1478,6 @@ static void unqueue_me_pi(struct futex_q
61 q->pi_state = NULL;
62
63 spin_unlock(q->lock_ptr);
64 -
65 - drop_futex_key_refs(&q->key);
66 }
67
68 /*
69 @@ -1812,7 +1808,10 @@ static int futex_wait(u32 __user *uaddr,
70 }
71
72 retry:
73 - /* Prepare to wait on uaddr. */
74 + /*
75 + * Prepare to wait on uaddr. On success, holds hb lock and increments
76 + * q.key refs.
77 + */
78 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
79 if (ret)
80 goto out;
81 @@ -1822,24 +1821,23 @@ retry:
82
83 /* If we were woken (and unqueued), we succeeded, whatever. */
84 ret = 0;
85 + /* unqueue_me() drops q.key ref */
86 if (!unqueue_me(&q))
87 - goto out_put_key;
88 + goto out;
89 ret = -ETIMEDOUT;
90 if (to && !to->task)
91 - goto out_put_key;
92 + goto out;
93
94 /*
95 * We expect signal_pending(current), but we might be the
96 * victim of a spurious wakeup as well.
97 */
98 - if (!signal_pending(current)) {
99 - put_futex_key(fshared, &q.key);
100 + if (!signal_pending(current))
101 goto retry;
102 - }
103
104 ret = -ERESTARTSYS;
105 if (!abs_time)
106 - goto out_put_key;
107 + goto out;
108
109 restart = &current_thread_info()->restart_block;
110 restart->fn = futex_wait_restart;
111 @@ -1856,8 +1854,6 @@ retry:
112
113 ret = -ERESTART_RESTARTBLOCK;
114
115 -out_put_key:
116 - put_futex_key(fshared, &q.key);
117 out:
118 if (to) {
119 hrtimer_cancel(&to->timer);
120 @@ -2236,7 +2232,10 @@ static int futex_wait_requeue_pi(u32 __u
121 q.rt_waiter = &rt_waiter;
122 q.requeue_pi_key = &key2;
123
124 - /* Prepare to wait on uaddr. */
125 + /*
126 + * Prepare to wait on uaddr. On success, increments q.key (key1) ref
127 + * count.
128 + */
129 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
130 if (ret)
131 goto out_key2;
132 @@ -2254,7 +2253,9 @@ static int futex_wait_requeue_pi(u32 __u
133 * In order for us to be here, we know our q.key == key2, and since
134 * we took the hb->lock above, we also know that futex_requeue() has
135 * completed and we no longer have to concern ourselves with a wakeup
136 - * race with the atomic proxy lock acquition by the requeue code.
137 + * race with the atomic proxy lock acquisition by the requeue code. The
138 + * futex_requeue dropped our key1 reference and incremented our key2
139 + * reference count.
140 */
141
142 /* Check if the requeue code acquired the second futex for us. */