diff options
author | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-10-21 12:21:39 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2013-10-21 15:58:17 -0400 |
commit | acdcabf532908fbefbea294fcad2e3989d1dc036 (patch) | |
tree | 96498c6e4b766277d643621891cacdf3ecb6d346 /net | |
parent | 0f2c6153746f270cf28559aa81a4da27847bd395 (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')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 15 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 8 |
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 | ||
1196 | static void l2cap_sock_defer_cb(struct l2cap_chan *chan) | 1196 | static 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 | ||
1205 | static void l2cap_sock_resume_cb(struct l2cap_chan *chan) | 1209 | static void l2cap_sock_resume_cb(struct l2cap_chan *chan) |