Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1c7a447 authored by Jeffy Chen's avatar Jeffy Chen Committed by Greg Kroah-Hartman
Browse files

Bluetooth: bnep: fix possible might sleep error in bnep_session

commit 25717382c1dd0ddced2059053e3ca5088665f7a5 upstream.

It looks like bnep_session 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:
	dfb2fae7 Bluetooth: Fix nested sleeps

So let's fix it at the same way, also follow the suggestion of:
https://lwn.net/Articles/628628/



Signed-off-by: default avatarJeffy Chen <jeffy.chen@rock-chips.com>
Reviewed-by: default avatarBrian Norris <briannorris@chromium.org>
Reviewed-by: default avatarAL Yu-Chen Cho <acho@suse.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f9adf422
Loading
Loading
Loading
Loading
+5 −6
Original line number Original line Diff line number Diff line
@@ -484,16 +484,16 @@ static int bnep_session(void *arg)
	struct net_device *dev = s->dev;
	struct net_device *dev = s->dev;
	struct sock *sk = s->sock->sk;
	struct sock *sk = s->sock->sk;
	struct sk_buff *skb;
	struct sk_buff *skb;
	wait_queue_t wait;
	DEFINE_WAIT_FUNC(wait, woken_wake_function);


	BT_DBG("");
	BT_DBG("");


	set_user_nice(current, -15);
	set_user_nice(current, -15);


	init_waitqueue_entry(&wait, current);
	add_wait_queue(sk_sleep(sk), &wait);
	add_wait_queue(sk_sleep(sk), &wait);
	while (1) {
	while (1) {
		set_current_state(TASK_INTERRUPTIBLE);
		/* Ensure session->terminate is updated */
		smp_mb__before_atomic();


		if (atomic_read(&s->terminate))
		if (atomic_read(&s->terminate))
			break;
			break;
@@ -515,9 +515,8 @@ static int bnep_session(void *arg)
				break;
				break;
		netif_wake_queue(dev);
		netif_wake_queue(dev);


		schedule();
		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
	}
	}
	__set_current_state(TASK_RUNNING);
	remove_wait_queue(sk_sleep(sk), &wait);
	remove_wait_queue(sk_sleep(sk), &wait);


	/* Cleanup session */
	/* Cleanup session */
@@ -663,7 +662,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
	s = __bnep_get_session(req->dst);
	s = __bnep_get_session(req->dst);
	if (s) {
	if (s) {
		atomic_inc(&s->terminate);
		atomic_inc(&s->terminate);
		wake_up_process(s->task);
		wake_up_interruptible(sk_sleep(s->sock->sk));
	} else
	} else
		err = -ENOENT;
		err = -ENOENT;