diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 6db60946c627..c0fe74a6b45e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -47,6 +47,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern); static void l2cap_sock_cleanup_listen(struct sock *parent); +static DEFINE_MUTEX(chan_data_lock); bool l2cap_is_socket(struct socket *sock) { @@ -1239,6 +1240,9 @@ static void l2cap_sock_kill(struct sock *sk) BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state)); + mutex_lock(&chan_data_lock); + l2cap_pi(sk)->chan->data = NULL; + mutex_unlock(&chan_data_lock); /* Kill poor orphan */ l2cap_chan_put(l2cap_pi(sk)->chan); @@ -1481,10 +1485,18 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { - struct sock *sk = chan->data; - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sock *sk; + struct l2cap_pinfo *pi; int err; + mutex_lock(&chan_data_lock); + sk = chan->data; + if (!sk) { + mutex_unlock(&chan_data_lock); + return -ENXIO; + } + + pi = l2cap_pi(sk); lock_sock(sk); if (chan->mode == L2CAP_MODE_ERTM && !list_empty(&pi->rx_busy)) { @@ -1535,6 +1547,7 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) done: release_sock(sk); + mutex_unlock(&chan_data_lock); return err; }