diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-11-13 07:37:47 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-11-14 19:53:27 -0500 |
commit | 970d0f1b280372cfd46b6de5529d96f8448de943 (patch) | |
tree | 5c851219000bb94098fc2edca1561eaca617b170 /net | |
parent | 3e64b7bd8234b459134b3059919828122e2fd79f (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.c | 42 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 4 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 10 |
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 = { | |||
778 | static int long_term_keys_show(struct seq_file *f, void *ptr) | 778 | static 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 | <k->bdaddr, ltk->bdaddr_type, ltk->authenticated, | 786 | <k->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 | ||
3107 | void hci_smp_ltks_clear(struct hci_dev *hdev) | 3105 | void 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 | ||
3366 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type) | 3372 | int 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(<k->list); | 4581 | list_del_rcu(<k->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 | } |