|
@@ -748,16 +748,15 @@ static const struct file_operations white_list_fops = {
|
|
|
static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
|
|
|
{
|
|
|
struct hci_dev *hdev = f->private;
|
|
|
- struct list_head *p, *n;
|
|
|
+ struct smp_irk *irk;
|
|
|
|
|
|
- hci_dev_lock(hdev);
|
|
|
- list_for_each_safe(p, n, &hdev->identity_resolving_keys) {
|
|
|
- struct smp_irk *irk = list_entry(p, struct smp_irk, list);
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
|
|
|
seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
|
|
|
&irk->bdaddr, irk->addr_type,
|
|
|
16, irk->val, &irk->rpa);
|
|
|
}
|
|
|
- hci_dev_unlock(hdev);
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -3114,11 +3113,11 @@ void hci_smp_ltks_clear(struct hci_dev *hdev)
|
|
|
|
|
|
void hci_smp_irks_clear(struct hci_dev *hdev)
|
|
|
{
|
|
|
- struct smp_irk *k, *tmp;
|
|
|
+ struct smp_irk *k;
|
|
|
|
|
|
- list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
|
|
|
- list_del(&k->list);
|
|
|
- kfree(k);
|
|
|
+ list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
|
|
|
+ list_del_rcu(&k->list);
|
|
|
+ kfree_rcu(k, rcu);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3221,17 +3220,22 @@ struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
|
|
|
{
|
|
|
struct smp_irk *irk;
|
|
|
|
|
|
- list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
|
|
|
- if (!bacmp(&irk->rpa, rpa))
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
|
|
|
+ if (!bacmp(&irk->rpa, rpa)) {
|
|
|
+ rcu_read_unlock();
|
|
|
return irk;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
|
|
|
+ list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
|
|
|
if (smp_irk_matches(hdev, irk->val, rpa)) {
|
|
|
bacpy(&irk->rpa, rpa);
|
|
|
+ rcu_read_unlock();
|
|
|
return irk;
|
|
|
}
|
|
|
}
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
@@ -3245,11 +3249,15 @@ struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0)
|
|
|
return NULL;
|
|
|
|
|
|
- list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
|
|
|
if (addr_type == irk->addr_type &&
|
|
|
- bacmp(bdaddr, &irk->bdaddr) == 0)
|
|
|
+ bacmp(bdaddr, &irk->bdaddr) == 0) {
|
|
|
+ rcu_read_unlock();
|
|
|
return irk;
|
|
|
+ }
|
|
|
}
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
@@ -3344,7 +3352,7 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
bacpy(&irk->bdaddr, bdaddr);
|
|
|
irk->addr_type = addr_type;
|
|
|
|
|
|
- list_add(&irk->list, &hdev->identity_resolving_keys);
|
|
|
+ list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
|
|
|
}
|
|
|
|
|
|
memcpy(irk->val, val, 16);
|
|
@@ -3390,16 +3398,16 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
|
|
|
|
|
|
void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
|
|
|
{
|
|
|
- struct smp_irk *k, *tmp;
|
|
|
+ struct smp_irk *k;
|
|
|
|
|
|
- list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
|
|
|
+ list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
|
|
|
if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_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);
|
|
|
}
|
|
|
}
|
|
|
|