Bluetooth: Fix potential use-after-free when clear keys
authorMin Li <lm0963hack@gmail.com>
Mon, 7 Aug 2023 11:07:41 +0000 (19:07 +0800)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 11 Aug 2023 18:56:16 +0000 (11:56 -0700)
Similar to commit c5d2b6fa26b5 ("Bluetooth: Fix use-after-free in
hci_remove_ltk/hci_remove_irk"). We can not access k after kfree_rcu()
call.

Fixes: d7d41682efc2 ("Bluetooth: Fix Suspicious RCU usage warnings")
Signed-off-by: Min Li <lm0963hack@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/hci_core.c

index 0fefa6788911b3b07d604f8117e53d2886a8276a..d7552b394ac22691d51b0f40248b13989f06b658 100644 (file)
@@ -1074,9 +1074,9 @@ void hci_uuids_clear(struct hci_dev *hdev)
 
 void hci_link_keys_clear(struct hci_dev *hdev)
 {
-       struct link_key *key;
+       struct link_key *key, *tmp;
 
-       list_for_each_entry(key, &hdev->link_keys, list) {
+       list_for_each_entry_safe(key, tmp, &hdev->link_keys, list) {
                list_del_rcu(&key->list);
                kfree_rcu(key, rcu);
        }
@@ -1084,9 +1084,9 @@ void hci_link_keys_clear(struct hci_dev *hdev)
 
 void hci_smp_ltks_clear(struct hci_dev *hdev)
 {
-       struct smp_ltk *k;
+       struct smp_ltk *k, *tmp;
 
-       list_for_each_entry(k, &hdev->long_term_keys, list) {
+       list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
                list_del_rcu(&k->list);
                kfree_rcu(k, rcu);
        }
@@ -1094,9 +1094,9 @@ void hci_smp_ltks_clear(struct hci_dev *hdev)
 
 void hci_smp_irks_clear(struct hci_dev *hdev)
 {
-       struct smp_irk *k;
+       struct smp_irk *k, *tmp;
 
-       list_for_each_entry(k, &hdev->identity_resolving_keys, list) {
+       list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
                list_del_rcu(&k->list);
                kfree_rcu(k, rcu);
        }
@@ -1104,9 +1104,9 @@ void hci_smp_irks_clear(struct hci_dev *hdev)
 
 void hci_blocked_keys_clear(struct hci_dev *hdev)
 {
-       struct blocked_key *b;
+       struct blocked_key *b, *tmp;
 
-       list_for_each_entry(b, &hdev->blocked_keys, list) {
+       list_for_each_entry_safe(b, tmp, &hdev->blocked_keys, list) {
                list_del_rcu(&b->list);
                kfree_rcu(b, rcu);
        }