aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-11-13 07:37:47 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-11-14 19:53:27 -0500
commit970d0f1b280372cfd46b6de5529d96f8448de943 (patch)
tree5c851219000bb94098fc2edca1561eaca617b170 /net
parent3e64b7bd8234b459134b3059919828122e2fd79f (diff)
Bluetooth: Convert LTK list to RCU
This patch set converts the hdev->long_term_keys list to use RCU to eliminate the need to use hci_dev_lock/unlock. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c42
-rw-r--r--net/bluetooth/hci_event.c4
-rw-r--r--net/bluetooth/smp.c10
3 files changed, 30 insertions, 26 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6c162c8809cf..c9495fb9f595 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -778,17 +778,15 @@ static const struct file_operations identity_resolving_keys_fops = {
778static int long_term_keys_show(struct seq_file *f, void *ptr) 778static int long_term_keys_show(struct seq_file *f, void *ptr)
779{ 779{
780 struct hci_dev *hdev = f->private; 780 struct hci_dev *hdev = f->private;
781 struct list_head *p, *n; 781 struct smp_ltk *ltk;
782 782
783 hci_dev_lock(hdev); 783 rcu_read_lock();
784 list_for_each_safe(p, n, &hdev->long_term_keys) { 784 list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
785 struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list);
786 seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n", 785 seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
787 &ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated, 786 &ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated,
788 ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv), 787 ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
789 __le64_to_cpu(ltk->rand), 16, ltk->val); 788 __le64_to_cpu(ltk->rand), 16, ltk->val);
790 } 789 rcu_read_unlock();
791 hci_dev_unlock(hdev);
792 790
793 return 0; 791 return 0;
794} 792}
@@ -3106,11 +3104,11 @@ void hci_link_keys_clear(struct hci_dev *hdev)
3106 3104
3107void hci_smp_ltks_clear(struct hci_dev *hdev) 3105void hci_smp_ltks_clear(struct hci_dev *hdev)
3108{ 3106{
3109 struct smp_ltk *k, *tmp; 3107 struct smp_ltk *k;
3110 3108
3111 list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) { 3109 list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
3112 list_del(&k->list); 3110 list_del_rcu(&k->list);
3113 kfree(k); 3111 kfree_rcu(k, rcu);
3114 } 3112 }
3115} 3113}
3116 3114
@@ -3184,15 +3182,18 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
3184{ 3182{
3185 struct smp_ltk *k; 3183 struct smp_ltk *k;
3186 3184
3187 list_for_each_entry(k, &hdev->long_term_keys, list) { 3185 rcu_read_lock();
3186 list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
3188 if (k->ediv != ediv || k->rand != rand) 3187 if (k->ediv != ediv || k->rand != rand)
3189 continue; 3188 continue;
3190 3189
3191 if (ltk_role(k->type) != role) 3190 if (ltk_role(k->type) != role)
3192 continue; 3191 continue;
3193 3192
3193 rcu_read_unlock();
3194 return k; 3194 return k;
3195 } 3195 }
3196 rcu_read_unlock();
3196 3197
3197 return NULL; 3198 return NULL;
3198} 3199}
@@ -3202,11 +3203,16 @@ struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
3202{ 3203{
3203 struct smp_ltk *k; 3204 struct smp_ltk *k;
3204 3205
3205 list_for_each_entry(k, &hdev->long_term_keys, list) 3206 rcu_read_lock();
3207 list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
3206 if (addr_type == k->bdaddr_type && 3208 if (addr_type == k->bdaddr_type &&
3207 bacmp(bdaddr, &k->bdaddr) == 0 && 3209 bacmp(bdaddr, &k->bdaddr) == 0 &&
3208 ltk_role(k->type) == role) 3210 ltk_role(k->type) == role) {
3211 rcu_read_unlock();
3209 return k; 3212 return k;
3213 }
3214 }
3215 rcu_read_unlock();
3210 3216
3211 return NULL; 3217 return NULL;
3212} 3218}
@@ -3309,7 +3315,7 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
3309 key = kzalloc(sizeof(*key), GFP_KERNEL); 3315 key = kzalloc(sizeof(*key), GFP_KERNEL);
3310 if (!key) 3316 if (!key)
3311 return NULL; 3317 return NULL;
3312 list_add(&key->list, &hdev->long_term_keys); 3318 list_add_rcu(&key->list, &hdev->long_term_keys);
3313 } 3319 }
3314 3320
3315 bacpy(&key->bdaddr, bdaddr); 3321 bacpy(&key->bdaddr, bdaddr);
@@ -3365,17 +3371,17 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
3365 3371
3366int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type) 3372int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
3367{ 3373{
3368 struct smp_ltk *k, *tmp; 3374 struct smp_ltk *k;
3369 int removed = 0; 3375 int removed = 0;
3370 3376
3371 list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) { 3377 list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
3372 if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type) 3378 if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
3373 continue; 3379 continue;
3374 3380
3375 BT_DBG("%s removing %pMR", hdev->name, bdaddr); 3381 BT_DBG("%s removing %pMR", hdev->name, bdaddr);
3376 3382
3377 list_del(&k->list); 3383 list_del_rcu(&k->list);
3378 kfree(k); 3384 kfree_rcu(k, rcu);
3379 removed++; 3385 removed++;
3380 } 3386 }
3381 3387
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index aec3b1dce1cc..09d76547d985 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4578,8 +4578,8 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
4578 */ 4578 */
4579 if (ltk->type == SMP_STK) { 4579 if (ltk->type == SMP_STK) {
4580 set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 4580 set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4581 list_del(&ltk->list); 4581 list_del_rcu(&ltk->list);
4582 kfree(ltk); 4582 kfree_rcu(ltk, rcu);
4583 } else { 4583 } else {
4584 clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 4584 clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
4585 } 4585 }
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 3dc5f0e66405..fd2dfe5222bc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -383,13 +383,13 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
383 /* If pairing failed clean up any keys we might have */ 383 /* If pairing failed clean up any keys we might have */
384 if (!complete) { 384 if (!complete) {
385 if (smp->ltk) { 385 if (smp->ltk) {
386 list_del(&smp->ltk->list); 386 list_del_rcu(&smp->ltk->list);
387 kfree(smp->ltk); 387 kfree_rcu(smp->ltk, rcu);
388 } 388 }
389 389
390 if (smp->slave_ltk) { 390 if (smp->slave_ltk) {
391 list_del(&smp->slave_ltk->list); 391 list_del_rcu(&smp->slave_ltk->list);
392 kfree(smp->slave_ltk); 392 kfree_rcu(smp->slave_ltk, rcu);
393 } 393 }
394 394
395 if (smp->remote_irk) { 395 if (smp->remote_irk) {
@@ -1321,7 +1321,6 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
1321 1321
1322 skb_pull(skb, sizeof(*rp)); 1322 skb_pull(skb, sizeof(*rp));
1323 1323
1324 hci_dev_lock(hdev);
1325 authenticated = (hcon->sec_level == BT_SECURITY_HIGH); 1324 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
1326 ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK, 1325 ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK,
1327 authenticated, smp->tk, smp->enc_key_size, 1326 authenticated, smp->tk, smp->enc_key_size,
@@ -1329,7 +1328,6 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
1329 smp->ltk = ltk; 1328 smp->ltk = ltk;
1330 if (!(smp->remote_key_dist & KEY_DIST_MASK)) 1329 if (!(smp->remote_key_dist & KEY_DIST_MASK))
1331 smp_distribute_keys(smp); 1330 smp_distribute_keys(smp);
1332 hci_dev_unlock(hdev);
1333 1331
1334 return 0; 1332 return 0;
1335} 1333}