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: Andrei Emeltchenko <andrei.emeltchenko@nokia.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
This commit is contained in:
parent
a49184c229
commit
940a9eea80
|
@ -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);
|
||||
|
||||
/* ---- 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)
|
||||
{
|
||||
struct sock *sk = (struct sock *) arg;
|
||||
|
@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)
|
|||
|
||||
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)
|
||||
reason = ECONNREFUSED;
|
||||
else if (sk->sk_state == BT_CONNECT &&
|
||||
|
@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg)
|
|||
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 ---- */
|
||||
static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue