]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.14.105/futex-fix-possible-missed-wakeup.patch
Linux 4.14.105
[thirdparty/kernel/stable-queue.git] / releases / 4.14.105 / futex-fix-possible-missed-wakeup.patch
CommitLineData
9aa60b56
SL
1From 55a9c23935eff6b602ffb80552d3ddf0dafcd6d7 Mon Sep 17 00:00:00 2001
2From: Peter Zijlstra <peterz@infradead.org>
3Date: Thu, 29 Nov 2018 14:44:49 +0100
4Subject: futex: Fix (possible) missed wakeup
5
6[ Upstream commit b061c38bef43406df8e73c5be06cbfacad5ee6ad ]
7
8We must not rely on wake_q_add() to delay the wakeup; in particular
9commit:
10
11 1d0dcb3ad9d3 ("futex: Implement lockless wakeups")
12
13moved wake_q_add() before smp_store_release(&q->lock_ptr, NULL), which
14could result in futex_wait() waking before observing ->lock_ptr ==
15NULL and going back to sleep again.
16
17Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
18Cc: Linus Torvalds <torvalds@linux-foundation.org>
19Cc: Peter Zijlstra <peterz@infradead.org>
20Cc: Thomas Gleixner <tglx@linutronix.de>
21Fixes: 1d0dcb3ad9d3 ("futex: Implement lockless wakeups")
22Signed-off-by: Ingo Molnar <mingo@kernel.org>
23Signed-off-by: Sasha Levin <sashal@kernel.org>
24---
25 kernel/futex.c | 13 ++++++++-----
26 1 file changed, 8 insertions(+), 5 deletions(-)
27
28diff --git a/kernel/futex.c b/kernel/futex.c
29index 29d708d0b3d19..22f83064abb35 100644
30--- a/kernel/futex.c
31+++ b/kernel/futex.c
32@@ -1462,11 +1462,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
33 if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
34 return;
35
36- /*
37- * Queue the task for later wakeup for after we've released
38- * the hb->lock. wake_q_add() grabs reference to p.
39- */
40- wake_q_add(wake_q, p);
41+ get_task_struct(p);
42 __unqueue_futex(q);
43 /*
44 * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
45@@ -1476,6 +1472,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
46 * plist_del in __unqueue_futex().
47 */
48 smp_store_release(&q->lock_ptr, NULL);
49+
50+ /*
51+ * Queue the task for later wakeup for after we've released
52+ * the hb->lock. wake_q_add() grabs reference to p.
53+ */
54+ wake_q_add(wake_q, p);
55+ put_task_struct(p);
56 }
57
58 /*
59--
602.19.1
61