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

Commit 940a9eea authored by Andrei Emeltchenko's avatar Andrei Emeltchenko Committed by Gustavo F. Padovan
Browse files

Bluetooth: timer check sk is not owned before freeing



In timer context we might delete l2cap channel used by krfcommd.
The check makes sure that sk is not owned. If sk is owned we
restart timer for HZ/5.

Signed-off-by: default avatarAndrei Emeltchenko <andrei.emeltchenko@nokia.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent a49184c2
Loading
Loading
Loading
Loading
+20 −12
Original line number Original line Diff line number Diff line
@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);


/* ---- L2CAP timers ---- */
/* ---- L2CAP timers ---- */
static void l2cap_sock_set_timer(struct sock *sk, long timeout)
{
	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
}

static void l2cap_sock_clear_timer(struct sock *sk)
{
	BT_DBG("sock %p state %d", sk, sk->sk_state);
	sk_stop_timer(sk, &sk->sk_timer);
}

static void l2cap_sock_timeout(unsigned long arg)
static void l2cap_sock_timeout(unsigned long arg)
{
{
	struct sock *sk = (struct sock *) arg;
	struct sock *sk = (struct sock *) arg;
@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)


	bh_lock_sock(sk);
	bh_lock_sock(sk);


	if (sock_owned_by_user(sk)) {
		/* sk is owned by user. Try again later */
		l2cap_sock_set_timer(sk, HZ / 5);
		bh_unlock_sock(sk);
		sock_put(sk);
		return;
	}

	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
		reason = ECONNREFUSED;
		reason = ECONNREFUSED;
	else if (sk->sk_state == BT_CONNECT &&
	else if (sk->sk_state == BT_CONNECT &&
@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg)
	sock_put(sk);
	sock_put(sk);
}
}


static void l2cap_sock_set_timer(struct sock *sk, long timeout)
{
	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
}

static void l2cap_sock_clear_timer(struct sock *sk)
{
	BT_DBG("sock %p state %d", sk, sk->sk_state);
	sk_stop_timer(sk, &sk->sk_timer);
}

/* ---- L2CAP channels ---- */
/* ---- L2CAP channels ---- */
static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
{
{