Commit 8ffb9290 authored by Gustavo Padovan's avatar Gustavo Padovan Committed by Marcel Holtmann

Bluetooth: Remove parent socket usage from l2cap_core.c

The parent socket is not used inside the L2CAP core anymore. We only lock
it to indirect access through the new_connection() callback. The hold of
the socket lock was moved to the new_connection() callback.

Inside L2CAP core the channel lock is now used in l2cap_le_conn_ready()
and l2cap_conn_ready() to protect the execution of these two functions
during the handling of new incoming connections.

This change remove the socket lock usage from L2CAP core while keeping
the code safe against race conditions.
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent f93fa273
...@@ -1362,7 +1362,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, ...@@ -1362,7 +1362,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
static void l2cap_le_conn_ready(struct l2cap_conn *conn) static void l2cap_le_conn_ready(struct l2cap_conn *conn)
{ {
struct hci_conn *hcon = conn->hcon; struct hci_conn *hcon = conn->hcon;
struct sock *parent;
struct l2cap_chan *chan, *pchan; struct l2cap_chan *chan, *pchan;
u8 dst_type; u8 dst_type;
...@@ -1384,9 +1383,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) ...@@ -1384,9 +1383,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
return; return;
parent = pchan->sk; l2cap_chan_lock(pchan);
lock_sock(parent);
chan = pchan->ops->new_connection(pchan); chan = pchan->ops->new_connection(pchan);
if (!chan) if (!chan)
...@@ -1402,7 +1399,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) ...@@ -1402,7 +1399,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
__l2cap_chan_add(conn, chan); __l2cap_chan_add(conn, chan);
clean: clean:
release_sock(parent); l2cap_chan_unlock(pchan);
} }
static void l2cap_conn_ready(struct l2cap_conn *conn) static void l2cap_conn_ready(struct l2cap_conn *conn)
...@@ -3705,7 +3702,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3705,7 +3702,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
struct l2cap_conn_rsp rsp; struct l2cap_conn_rsp rsp;
struct l2cap_chan *chan = NULL, *pchan; struct l2cap_chan *chan = NULL, *pchan;
struct sock *parent;
int result, status = L2CAP_CS_NO_INFO; int result, status = L2CAP_CS_NO_INFO;
u16 dcid = 0, scid = __le16_to_cpu(req->scid); u16 dcid = 0, scid = __le16_to_cpu(req->scid);
...@@ -3721,10 +3717,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3721,10 +3717,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
goto sendresp; goto sendresp;
} }
parent = pchan->sk;
mutex_lock(&conn->chan_lock); mutex_lock(&conn->chan_lock);
lock_sock(parent); l2cap_chan_lock(pchan);
/* Check if the ACL is secure enough (if not SDP) */ /* Check if the ACL is secure enough (if not SDP) */
if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
...@@ -3800,7 +3794,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3800,7 +3794,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
} }
response: response:
release_sock(parent); l2cap_chan_unlock(pchan);
mutex_unlock(&conn->chan_lock); mutex_unlock(&conn->chan_lock);
sendresp: sendresp:
......
...@@ -1042,6 +1042,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) ...@@ -1042,6 +1042,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
{ {
struct sock *sk, *parent = chan->data; struct sock *sk, *parent = chan->data;
lock_sock(parent);
/* Check for backlog size */ /* Check for backlog size */
if (sk_acceptq_is_full(parent)) { if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog); BT_DBG("backlog full %d", parent->sk_ack_backlog);
...@@ -1059,6 +1061,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) ...@@ -1059,6 +1061,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
bt_accept_enqueue(parent, sk); bt_accept_enqueue(parent, sk);
release_sock(parent);
return l2cap_pi(sk)->chan; return l2cap_pi(sk)->chan;
} }
......
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