aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-10-21 12:21:39 -0400
committerMarcel Holtmann <marcel@holtmann.org>2013-10-21 15:58:17 -0400
commitacdcabf532908fbefbea294fcad2e3989d1dc036 (patch)
tree96498c6e4b766277d643621891cacdf3ecb6d346 /net/bluetooth
parent0f2c6153746f270cf28559aa81a4da27847bd395 (diff)
Bluetooth: Hold socket in defer callback in L2CAP socket
In both places that we use the defer callback the socket lock is held for a indirect sk access inside __l2cap_change_state() and chan->ops->defer(), all the rest of the code between lock_sock() and release_sock() is already protected by the channel lock and won't be affected by this change. We now use l2cap_change_state(), the locked version of the change state function, and the defer callback does the locking itself now. This does not affect other uses of the defer callback. Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap_core.c15
-rw-r--r--net/bluetooth/l2cap_sock.c8
2 files changed, 9 insertions, 14 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4141545c620a..049e1c81d771 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1299,20 +1299,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
1299 rsp.dcid = cpu_to_le16(chan->scid); 1299 rsp.dcid = cpu_to_le16(chan->scid);
1300 1300
1301 if (l2cap_chan_check_security(chan)) { 1301 if (l2cap_chan_check_security(chan)) {
1302 struct sock *sk = chan->sk;
1303
1304 lock_sock(sk);
1305 if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 1302 if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1306 rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1303 rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1307 rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); 1304 rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
1308 chan->ops->defer(chan); 1305 chan->ops->defer(chan);
1309 1306
1310 } else { 1307 } else {
1311 __l2cap_state_change(chan, BT_CONFIG); 1308 l2cap_state_change(chan, BT_CONFIG);
1312 rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); 1309 rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1313 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); 1310 rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
1314 } 1311 }
1315 release_sock(sk);
1316 } else { 1312 } else {
1317 rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); 1313 rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1318 rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 1314 rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
@@ -6643,31 +6639,26 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
6643 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 6639 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
6644 } 6640 }
6645 } else if (chan->state == BT_CONNECT2) { 6641 } else if (chan->state == BT_CONNECT2) {
6646 struct sock *sk = chan->sk;
6647 struct l2cap_conn_rsp rsp; 6642 struct l2cap_conn_rsp rsp;
6648 __u16 res, stat; 6643 __u16 res, stat;
6649 6644
6650 lock_sock(sk);
6651
6652 if (!status) { 6645 if (!status) {
6653 if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 6646 if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
6654 res = L2CAP_CR_PEND; 6647 res = L2CAP_CR_PEND;
6655 stat = L2CAP_CS_AUTHOR_PEND; 6648 stat = L2CAP_CS_AUTHOR_PEND;
6656 chan->ops->defer(chan); 6649 chan->ops->defer(chan);
6657 } else { 6650 } else {
6658 __l2cap_state_change(chan, BT_CONFIG); 6651 l2cap_state_change(chan, BT_CONFIG);
6659 res = L2CAP_CR_SUCCESS; 6652 res = L2CAP_CR_SUCCESS;
6660 stat = L2CAP_CS_NO_INFO; 6653 stat = L2CAP_CS_NO_INFO;
6661 } 6654 }
6662 } else { 6655 } else {
6663 __l2cap_state_change(chan, BT_DISCONN); 6656 l2cap_state_change(chan, BT_DISCONN);
6664 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 6657 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
6665 res = L2CAP_CR_SEC_BLOCK; 6658 res = L2CAP_CR_SEC_BLOCK;
6666 stat = L2CAP_CS_NO_INFO; 6659 stat = L2CAP_CS_NO_INFO;
6667 } 6660 }
6668 6661
6669 release_sock(sk);
6670
6671 rsp.scid = cpu_to_le16(chan->dcid); 6662 rsp.scid = cpu_to_le16(chan->dcid);
6672 rsp.dcid = cpu_to_le16(chan->scid); 6663 rsp.dcid = cpu_to_le16(chan->scid);
6673 rsp.result = cpu_to_le16(res); 6664 rsp.result = cpu_to_le16(res);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index a0b31db1246e..e55999228c8a 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1195,11 +1195,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
1195 1195
1196static void l2cap_sock_defer_cb(struct l2cap_chan *chan) 1196static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
1197{ 1197{
1198 struct sock *sk = chan->data; 1198 struct sock *parent, *sk = chan->data;
1199 struct sock *parent = bt_sk(sk)->parent; 1199
1200 lock_sock(sk);
1200 1201
1202 parent = bt_sk(sk)->parent;
1201 if (parent) 1203 if (parent)
1202 parent->sk_data_ready(parent, 0); 1204 parent->sk_data_ready(parent, 0);
1205
1206 release_sock(sk);
1203} 1207}
1204 1208
1205static void l2cap_sock_resume_cb(struct l2cap_chan *chan) 1209static void l2cap_sock_resume_cb(struct l2cap_chan *chan)