Commit a6a5568c authored by Mat Martineau's avatar Mat Martineau Committed by Gustavo Padovan

Bluetooth: Lock the L2CAP channel when sending

The ERTM and streaming mode transmit queue must only be accessed while
the L2CAP channel lock is held.  Locking the channel before calling
l2cap_chan_send ensures that multiple threads cannot simultaneously
manipulate the queue when sending and receiving concurrently.

L2CAP channel locking had previously moved to the l2cap_chan struct
instead of the associated socket, so some of the old socket locking
can also be removed in this patch.
Signed-off-by: default avatarMat Martineau <mathewm@codeaurora.org>
Signed-off-by: default avatarGustavo Padovan <gustavo@padovan.org>
parent ef191ade
...@@ -257,12 +257,10 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, ...@@ -257,12 +257,10 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
{ {
struct sk_buff *skb; struct sk_buff *skb;
release_sock(sk);
if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) { if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) {
skb_reserve(skb, BT_SKB_RESERVE); skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0; bt_cb(skb)->incoming = 0;
} }
lock_sock(sk);
if (!skb && *err) if (!skb && *err)
return NULL; return NULL;
......
...@@ -720,16 +720,13 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms ...@@ -720,16 +720,13 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
if (msg->msg_flags & MSG_OOB) if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP; return -EOPNOTSUPP;
lock_sock(sk); if (sk->sk_state != BT_CONNECTED)
if (sk->sk_state != BT_CONNECTED) {
release_sock(sk);
return -ENOTCONN; return -ENOTCONN;
}
l2cap_chan_lock(chan);
err = l2cap_chan_send(chan, msg, len, sk->sk_priority); err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
l2cap_chan_unlock(chan);
release_sock(sk);
return err; return err;
} }
...@@ -940,7 +937,10 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, ...@@ -940,7 +937,10 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
l2cap_chan_unlock(chan);
skb = bt_skb_send_alloc(chan->sk, len, nb, &err); skb = bt_skb_send_alloc(chan->sk, len, nb, &err);
l2cap_chan_lock(chan);
if (!skb) if (!skb)
return ERR_PTR(err); return ERR_PTR(err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment