Patch "Bluetooth: hidp: fix possible might sleep error in hidp_session_thread" has been added to the 4.12-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
Bluetooth: hidp: fix possible might sleep error in hidp_session_thread
to the 4.12-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
bluetooth-hidp-fix-possible-might-sleep-error-in-hidp_session_thread.patch
and it can be found in the queue-4.12 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
5da8e47d849d3d37b14129f038782a095b9ad049Mon Sep 17 00:00:00 2001
From: Jeffy Chen <[email protected]>
Date: Tue, 27 Jun 2017 17:34:44 +0800
Subject: Bluetooth: hidp: fix possible might sleep error in hidp_session_thread
From: Jeffy Chen <[email protected]>
commit 5da8e47d849d3d37b14129f038782a095b9ad049 upstream.
It looks like hidp_session_thread has same pattern as the issue reported in old rfcomm:
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
if (condition)
break;
// may call might_sleep here
schedule();
}
__set_current_state(TASK_RUNNING);Which fixed at:
dfb2fae Bluetooth: Fix nested sleeps
So let's fix it at the same way, also follow the suggestion of:
https://lwn.net/Articles/628628/
--- net/bluetooth/hidp/core.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-)
net/bluetooth/hidp/core.c +22 -11
@@ -36,6 +36,7 @@#define VERSION "1.2"static DECLARE_RWSEM (hidp_session_sem); +static DECLARE_WAIT_QUEUE_HEAD (hidp_session_wq);static LIST_HEAD (hidp_session_list);static unsigned char hidp_keycode[256 ] = {
@@ -1068,12 +1069,12 @@ static int hidp_session_start_sync(struc* Wake up session thread and notify it to stop. This is asynchronous and * returns immediately. Call this whenever a runtime error occurs and you want * the session to stop. -* Note: wake_up_process() performs any necessary memory-barriers for us. +* Note: wake_up_interruptible() performs any necessary memory-barriers for us. */ static void hidp_session_terminate (struct hidp_session *session) {atomic_inc (&session->terminate); -wake_up_process (session->task); +wake_up_interruptible (&hidp_session_wq); }/*
@@ -1180,7 +1181,9 @@ static void hidp_session_run(struct hidpstruct sock *ctrl_sk = session->ctrl_sock->sk;struct sock *intr_sk = session->intr_sock->sk;struct sk_buff *skb; +DEFINE_WAIT_FUNC (wait, woken_wake_function); +add_wait_queue (&hidp_session_wq, &wait);for (;;) {/* * This thread can be woken up two ways:
@@ -1188,12 +1191,10 @@ static void hidp_session_run(struct hidp* session->terminate flag and wakes this thread up. * - Via modifying the socket state of ctrl/intr_sock. This * thread is woken up by ->sk_state_changed(). -* -* Note: set_current_state() performs any necessary -* memory-barriers for us. */ -set_current_state (TASK_INTERRUPTIBLE ); +/* Ensure session->terminate is updated */ +smp_mb__before_atomic ();if (atomic_read (&session->terminate))break ;
@@ -1227,11 +1228,22 @@ static void hidp_session_run(struct hidphidp_process_transmit (session, &session->ctrl_transmit, session->ctrl_sock); -schedule (); +wait_woken (&wait,TASK_INTERRUPTIBLE ,MAX_SCHEDULE_TIMEOUT ); } +remove_wait_queue (&hidp_session_wq, &wait);atomic_inc (&session->terminate); -set_current_state (TASK_RUNNING ); + +/* Ensure session->terminate is updated */ +smp_mb__after_atomic (); +} + +static int hidp_session_wake_function (wait_queue_t *wait, +unsigned int mode, +int sync,void *key) +{ +wake_up_interruptible (&hidp_session_wq); +return false; }/*
@@ -1244,7 +1256,8 @@ static void hidp_session_run(struct hidpstatic int hidp_session_thread (void *arg) {struct hidp_session *session = arg; -wait_queue_t ctrl_wait, intr_wait; +DEFINE_WAIT_FUNC (ctrl_wait, hidp_session_wake_function); +DEFINE_WAIT_FUNC (intr_wait, hidp_session_wake_function);BT_DBG ("session %p" , session);
@@ -1254,8 +1267,6 @@ static int hidp_session_thread(void *argset_user_nice (current,-15 );hidp_set_timer (session); -init_waitqueue_entry (&ctrl_wait, current); -init_waitqueue_entry (&intr_wait, current);add_wait_queue (sk_sleep (session->ctrl_sock->sk), &ctrl_wait);add_wait_queue (sk_sleep (session->intr_sock->sk), &intr_wait);/* This memory barrier is paired with wq_has_sleeper(). See
Patches currently in stable-queue which might be from [email protected] are
queue-4.12/bluetooth-cmtp-fix-possible-might-sleep-error-in-cmtp_session.patch queue-4.12/bluetooth-hidp-fix-possible-might-sleep-error-in-hidp_session_thread.patch queue-4.12/bluetooth-bnep-fix-possible-might-sleep-error-in-bnep_session.patch