Skip to content

Commit

Permalink
Bluetooth: Fix race condition with L2CAP information request
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marcel Holtmann committed Feb 27, 2009
1 parent 657e17b commit 984947d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
3 changes: 2 additions & 1 deletion include/net/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ struct l2cap_conn {
};

#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x02
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08

/* ----- L2CAP channel and socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
Expand Down
17 changes: 14 additions & 3 deletions net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ static void l2cap_do_start(struct sock *sk)
struct l2cap_conn *conn = l2cap_pi(sk)->conn;

if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
return;

if (l2cap_check_security(sk)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
Expand Down Expand Up @@ -455,6 +458,8 @@ static void l2cap_info_timeout(unsigned long arg)

conn->info_ident = 0;

conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;

l2cap_conn_start(conn);
}

Expand Down Expand Up @@ -1787,6 +1792,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
cmd->ident == conn->info_ident) {
conn->info_ident = 0;
del_timer(&conn->info_timer);

conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;

l2cap_conn_start(conn);
}

Expand Down Expand Up @@ -1857,7 +1865,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd

l2cap_pi(sk)->ident = cmd->ident;

if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
if (l2cap_check_security(sk)) {
if (bt_sk(sk)->defer_setup) {
sk->sk_state = BT_CONNECT2;
Expand Down Expand Up @@ -2176,10 +2184,13 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm

del_timer(&conn->info_timer);

if (type == L2CAP_IT_FEAT_MASK)
if (type == L2CAP_IT_FEAT_MASK) {
conn->feat_mask = get_unaligned_le32(rsp->data);

l2cap_conn_start(conn);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;

l2cap_conn_start(conn);
}

return 0;
}
Expand Down

0 comments on commit 984947d

Please sign in to comment.