diff options
Diffstat (limited to 'debian/patches-rt/0265-sched-completion-Fix-a-lockup-in-wait_for_completion.patch')
-rw-r--r-- | debian/patches-rt/0265-sched-completion-Fix-a-lockup-in-wait_for_completion.patch | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/debian/patches-rt/0265-sched-completion-Fix-a-lockup-in-wait_for_completion.patch b/debian/patches-rt/0265-sched-completion-Fix-a-lockup-in-wait_for_completion.patch new file mode 100644 index 000000000..bf5c14343 --- /dev/null +++ b/debian/patches-rt/0265-sched-completion-Fix-a-lockup-in-wait_for_completion.patch @@ -0,0 +1,69 @@ +From 055b27065070862af1438159975c51c824ed6db1 Mon Sep 17 00:00:00 2001 +From: Corey Minyard <cminyard@mvista.com> +Date: Thu, 9 May 2019 14:33:20 -0500 +Subject: [PATCH 265/347] sched/completion: Fix a lockup in + wait_for_completion() +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.246-rt110.tar.xz + +Consider following race: + + T0 T1 T2 + wait_for_completion() + do_wait_for_common() + __prepare_to_swait() + schedule() + complete() + x->done++ (0 -> 1) + raw_spin_lock_irqsave() + swake_up_locked() wait_for_completion() + wake_up_process(T0) + list_del_init() + raw_spin_unlock_irqrestore() + raw_spin_lock_irq(&x->wait.lock) + raw_spin_lock_irq(&x->wait.lock) x->done != UINT_MAX, 1 -> 0 + raw_spin_unlock_irq(&x->wait.lock) + return 1 + while (!x->done && timeout), + continue loop, not enqueued + on &x->wait + +Basically, the problem is that the original wait queues used in +completions did not remove the item from the queue in the wakeup +function, but swake_up_locked() does. + +Fix it by adding the thread to the wait queue inside the do loop. +The design of swait detects if it is already in the list and doesn't +do the list add again. + +Cc: stable-rt@vger.kernel.org +Fixes: a04ff6b4ec4ee7e ("completion: Use simple wait queues") +Signed-off-by: Corey Minyard <cminyard@mvista.com> +Acked-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +[bigeasy: shorten commit message ] +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/sched/completion.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c +index 755a58084978..49c14137988e 100644 +--- a/kernel/sched/completion.c ++++ b/kernel/sched/completion.c +@@ -72,12 +72,12 @@ do_wait_for_common(struct completion *x, + if (!x->done) { + DECLARE_SWAITQUEUE(wait); + +- __prepare_to_swait(&x->wait, &wait); + do { + if (signal_pending_state(state, current)) { + timeout = -ERESTARTSYS; + break; + } ++ __prepare_to_swait(&x->wait, &wait); + __set_current_state(state); + raw_spin_unlock_irq(&x->wait.lock); + timeout = action(timeout); +-- +2.36.1 + |