static int long_term_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
- struct list_head *p, *n;
+ struct smp_ltk *ltk;
- hci_dev_lock(hdev);
- list_for_each_safe(p, n, &hdev->long_term_keys) {
- struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list);
+ rcu_read_lock();
+ list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
<k->bdaddr, ltk->bdaddr_type, ltk->authenticated,
ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
__le64_to_cpu(ltk->rand), 16, ltk->val);
- }
- hci_dev_unlock(hdev);
+ rcu_read_unlock();
return 0;
}
void hci_smp_ltks_clear(struct hci_dev *hdev)
{
- struct smp_ltk *k, *tmp;
+ struct smp_ltk *k;
- list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
- list_del(&k->list);
- kfree(k);
+ list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
+ list_del_rcu(&k->list);
+ kfree_rcu(k, rcu);
}
}
{
struct smp_ltk *k;
- list_for_each_entry(k, &hdev->long_term_keys, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
if (k->ediv != ediv || k->rand != rand)
continue;
if (ltk_role(k->type) != role)
continue;
+ rcu_read_unlock();
return k;
}
+ rcu_read_unlock();
return NULL;
}
{
struct smp_ltk *k;
- list_for_each_entry(k, &hdev->long_term_keys, list)
+ rcu_read_lock();
+ list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
if (addr_type == k->bdaddr_type &&
bacmp(bdaddr, &k->bdaddr) == 0 &&
- ltk_role(k->type) == role)
+ ltk_role(k->type) == role) {
+ rcu_read_unlock();
return k;
+ }
+ }
+ rcu_read_unlock();
return NULL;
}
key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key)
return NULL;
- list_add(&key->list, &hdev->long_term_keys);
+ list_add_rcu(&key->list, &hdev->long_term_keys);
}
bacpy(&key->bdaddr, bdaddr);
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
{
- struct smp_ltk *k, *tmp;
+ struct smp_ltk *k;
int removed = 0;
- list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
+ list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
continue;
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
- list_del(&k->list);
- kfree(k);
+ list_del_rcu(&k->list);
+ kfree_rcu(k, rcu);
removed++;
}
/* If pairing failed clean up any keys we might have */
if (!complete) {
if (smp->ltk) {
- list_del(&smp->ltk->list);
- kfree(smp->ltk);
+ list_del_rcu(&smp->ltk->list);
+ kfree_rcu(smp->ltk, rcu);
}
if (smp->slave_ltk) {
- list_del(&smp->slave_ltk->list);
- kfree(smp->slave_ltk);
+ list_del_rcu(&smp->slave_ltk->list);
+ kfree_rcu(smp->slave_ltk, rcu);
}
if (smp->remote_irk) {
skb_pull(skb, sizeof(*rp));
- hci_dev_lock(hdev);
authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK,
authenticated, smp->tk, smp->enc_key_size,
smp->ltk = ltk;
if (!(smp->remote_key_dist & KEY_DIST_MASK))
smp_distribute_keys(smp);
- hci_dev_unlock(hdev);
return 0;
}