Commit 5d3de7df18077a0f508ae2c3e3f1866da65fdffd

Authored by Vinicius Costa Gomes
Committed by Gustavo F. Padovan
1 parent 94ac02726c

Bluetooth: Add support for SMP timeout

This patch adds support for disconnecting the link when SMP procedure
takes more than 30 seconds.

SMP begins when either the Pairing Request command is sent or the
Pairing Response is received, and it ends when the link is encrypted
(or terminated). Vol 3, Part H Section 3.4.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>

Showing 3 changed files with 60 additions and 30 deletions Side-by-side Diff

include/net/bluetooth/l2cap.h
... ... @@ -401,6 +401,8 @@
401 401 __u8 pcnf[16]; /* SMP Pairing Confirm */
402 402 __u8 tk[16]; /* SMP Temporary Key */
403 403  
  404 + struct timer_list security_timer;
  405 +
404 406 struct list_head chan_l;
405 407 rwlock_t chan_lock;
406 408 };
net/bluetooth/l2cap_core.c
... ... @@ -970,6 +970,45 @@
970 970 l2cap_conn_start(conn);
971 971 }
972 972  
  973 +static void l2cap_conn_del(struct hci_conn *hcon, int err)
  974 +{
  975 + struct l2cap_conn *conn = hcon->l2cap_data;
  976 + struct l2cap_chan *chan, *l;
  977 + struct sock *sk;
  978 +
  979 + if (!conn)
  980 + return;
  981 +
  982 + BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
  983 +
  984 + kfree_skb(conn->rx_skb);
  985 +
  986 + /* Kill channels */
  987 + list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
  988 + sk = chan->sk;
  989 + bh_lock_sock(sk);
  990 + l2cap_chan_del(chan, err);
  991 + bh_unlock_sock(sk);
  992 + chan->ops->close(chan->data);
  993 + }
  994 +
  995 + if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
  996 + del_timer_sync(&conn->info_timer);
  997 +
  998 + if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
  999 + del_timer(&conn->security_timer);
  1000 +
  1001 + hcon->l2cap_data = NULL;
  1002 + kfree(conn);
  1003 +}
  1004 +
  1005 +static void security_timeout(unsigned long arg)
  1006 +{
  1007 + struct l2cap_conn *conn = (void *) arg;
  1008 +
  1009 + l2cap_conn_del(conn->hcon, ETIMEDOUT);
  1010 +}
  1011 +
973 1012 static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
974 1013 {
975 1014 struct l2cap_conn *conn = hcon->l2cap_data;
... ... @@ -1001,7 +1040,10 @@
1001 1040  
1002 1041 INIT_LIST_HEAD(&conn->chan_l);
1003 1042  
1004   - if (hcon->type != LE_LINK)
  1043 + if (hcon->type == LE_LINK)
  1044 + setup_timer(&conn->security_timer, security_timeout,
  1045 + (unsigned long) conn);
  1046 + else
1005 1047 setup_timer(&conn->info_timer, l2cap_info_timeout,
1006 1048 (unsigned long) conn);
1007 1049  
... ... @@ -1010,35 +1052,6 @@
1010 1052 return conn;
1011 1053 }
1012 1054  
1013   -static void l2cap_conn_del(struct hci_conn *hcon, int err)
1014   -{
1015   - struct l2cap_conn *conn = hcon->l2cap_data;
1016   - struct l2cap_chan *chan, *l;
1017   - struct sock *sk;
1018   -
1019   - if (!conn)
1020   - return;
1021   -
1022   - BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1023   -
1024   - kfree_skb(conn->rx_skb);
1025   -
1026   - /* Kill channels */
1027   - list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1028   - sk = chan->sk;
1029   - bh_lock_sock(sk);
1030   - l2cap_chan_del(chan, err);
1031   - bh_unlock_sock(sk);
1032   - chan->ops->close(chan->data);
1033   - }
1034   -
1035   - if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1036   - del_timer_sync(&conn->info_timer);
1037   -
1038   - hcon->l2cap_data = NULL;
1039   - kfree(conn);
1040   -}
1041   -
1042 1055 static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
1043 1056 {
1044 1057 write_lock_bh(&conn->chan_lock);
... ... @@ -4182,6 +4195,7 @@
4182 4195 if (chan->scid == L2CAP_CID_LE_DATA) {
4183 4196 if (!status && encrypt) {
4184 4197 chan->sec_level = hcon->sec_level;
  4198 + del_timer(&conn->security_timer);
4185 4199 l2cap_chan_ready(sk);
4186 4200 }
4187 4201  
... ... @@ -27,6 +27,8 @@
27 27 #include <linux/crypto.h>
28 28 #include <crypto/b128ops.h>
29 29  
  30 +#define SMP_TIMEOUT 30000 /* 30 seconds */
  31 +
30 32 static inline void swap128(u8 src[16], u8 dst[16])
31 33 {
32 34 int i;
... ... @@ -228,6 +230,9 @@
228 230  
229 231 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp);
230 232  
  233 + mod_timer(&conn->security_timer, jiffies +
  234 + msecs_to_jiffies(SMP_TIMEOUT));
  235 +
231 236 return 0;
232 237 }
233 238  
... ... @@ -303,6 +308,9 @@
303 308 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
304 309 }
305 310  
  311 + mod_timer(&conn->security_timer, jiffies +
  312 + msecs_to_jiffies(SMP_TIMEOUT));
  313 +
306 314 return 0;
307 315 }
308 316  
... ... @@ -382,6 +390,9 @@
382 390  
383 391 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
384 392  
  393 + mod_timer(&conn->security_timer, jiffies +
  394 + msecs_to_jiffies(SMP_TIMEOUT));
  395 +
385 396 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
386 397  
387 398 return 0;
... ... @@ -414,6 +425,9 @@
414 425 build_pairing_cmd(conn, &cp, authreq);
415 426 conn->preq[0] = SMP_CMD_PAIRING_REQ;
416 427 memcpy(&conn->preq[1], &cp, sizeof(cp));
  428 +
  429 + mod_timer(&conn->security_timer, jiffies +
  430 + msecs_to_jiffies(SMP_TIMEOUT));
417 431  
418 432 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
419 433 } else {