aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-02-06 17:35:19 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:41 -0500
commit984947dc64f82bc6cafa4d84ba1a139718f634a8 (patch)
treef85e4b260034f5b5a20af7a63900ee7de06fa7ad /net/bluetooth/l2cap.c
parent657e17b03c80bec817975984d221bef716f83558 (diff)
Bluetooth: Fix race condition with L2CAP information request
When two L2CAP connections are requested quickly after the ACL link has been established there exists a window for a race condition where a connection request is sent before the information response has been received. Any connection request should only be sent after an exchange of the extended features mask has been finished. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r--net/bluetooth/l2cap.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 8a93dde4095b..07fdbc7dd54d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -320,6 +320,9 @@ static void l2cap_do_start(struct sock *sk)
320 struct l2cap_conn *conn = l2cap_pi(sk)->conn; 320 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
321 321
322 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 322 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
323 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
324 return;
325
323 if (l2cap_check_security(sk)) { 326 if (l2cap_check_security(sk)) {
324 struct l2cap_conn_req req; 327 struct l2cap_conn_req req;
325 req.scid = cpu_to_le16(l2cap_pi(sk)->scid); 328 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
@@ -455,6 +458,8 @@ static void l2cap_info_timeout(unsigned long arg)
455 458
456 conn->info_ident = 0; 459 conn->info_ident = 0;
457 460
461 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
462
458 l2cap_conn_start(conn); 463 l2cap_conn_start(conn);
459} 464}
460 465
@@ -1787,6 +1792,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
1787 cmd->ident == conn->info_ident) { 1792 cmd->ident == conn->info_ident) {
1788 conn->info_ident = 0; 1793 conn->info_ident = 0;
1789 del_timer(&conn->info_timer); 1794 del_timer(&conn->info_timer);
1795
1796 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
1797
1790 l2cap_conn_start(conn); 1798 l2cap_conn_start(conn);
1791 } 1799 }
1792 1800
@@ -1857,7 +1865,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
1857 1865
1858 l2cap_pi(sk)->ident = cmd->ident; 1866 l2cap_pi(sk)->ident = cmd->ident;
1859 1867
1860 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 1868 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
1861 if (l2cap_check_security(sk)) { 1869 if (l2cap_check_security(sk)) {
1862 if (bt_sk(sk)->defer_setup) { 1870 if (bt_sk(sk)->defer_setup) {
1863 sk->sk_state = BT_CONNECT2; 1871 sk->sk_state = BT_CONNECT2;
@@ -2176,10 +2184,13 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
2176 2184
2177 del_timer(&conn->info_timer); 2185 del_timer(&conn->info_timer);
2178 2186
2179 if (type == L2CAP_IT_FEAT_MASK) 2187 if (type == L2CAP_IT_FEAT_MASK) {
2180 conn->feat_mask = get_unaligned_le32(rsp->data); 2188 conn->feat_mask = get_unaligned_le32(rsp->data);
2181 2189
2182 l2cap_conn_start(conn); 2190 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2191
2192 l2cap_conn_start(conn);
2193 }
2183 2194
2184 return 0; 2195 return 0;
2185} 2196}