[PW_SID:1152930] Bluetooth: hci_core: Fix IRK lookup lifetime races - #658
[PW_SID:1152930] Bluetooth: hci_core: Fix IRK lookup lifetime races#658BluezTestBot wants to merge 1 commit into
Conversation
The IRK lookup helpers traverse the identity resolving key list under RCU, but return a raw pointer after leaving the read-side critical section. A concurrent management unpair or key reload can unlink and free that entry while SMP key distribution still updates its value and RPA through hci_add_irk(). RCU also does not serialize list mutations. SMP cleanup and key distribution can update the IRK list without the hdev mutex while management paths update it with that mutex held, allowing concurrent list_add_rcu() and list_del_rcu() operations on the same list. Give each IRK a list-owned reference and return caller-owned references from lookup and add helpers. Keep the SMP context reference until pairing teardown, and drop the list reference only once when an entry is unlinked. Add a dedicated spinlock for IRK list and payload updates, and copy payload snapshots under that lock so readers do not race updates. Initialize new entries completely before publishing them. Unlink an IRK added during unpair before dropping the SMP context reference. An exact KASAN interleaving that removes and drains the RCU entry after lookup but before hci_add_irk() resumes now completes without a use-after-free. A forced late-add/unpair interleaving leaves no linked IRK behind. A KASAN and lockdep enabled VHCI pairing/unpair test also completes successfully. Fixes: a7ec733 ("Bluetooth: Fix removing any IRKs when unpairing devices") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Kazuki Hanai <hnkz.64@gmail.com>
|
CheckPatch |
|
VerifyFixes |
|
VerifySignedoff |
|
GitLint |
|
SubjectPrefix |
|
BuildKernel |
|
CheckAllWarning |
|
CheckSparse |
|
BuildKernel32 |
|
CheckKernelLLVM |
|
TestRunnerSetup |
|
TestRunner_l2cap-tester |
|
TestRunner_iso-tester |
|
TestRunner_bnep-tester |
|
TestRunner_mgmt-tester |
|
TestRunner_rfcomm-tester |
|
TestRunner_sco-tester |
|
TestRunner_ioctl-tester |
|
TestRunner_mesh-tester |
|
TestRunner_smp-tester |
|
TestRunner_userchan-tester |
|
TestRunner_6lowpan-tester |
|
IncrementalBuild |
The IRK lookup helpers traverse the identity resolving key list under
RCU, but return a raw pointer after leaving the read-side critical
section. A concurrent management unpair or key reload can unlink and
free that entry while SMP key distribution still updates its value and
RPA through hci_add_irk().
RCU also does not serialize list mutations. SMP cleanup and key
distribution can update the IRK list without the hdev mutex while
management paths update it with that mutex held, allowing concurrent
list_add_rcu() and list_del_rcu() operations on the same list.
Give each IRK a list-owned reference and return caller-owned references
from lookup and add helpers. Keep the SMP context reference until pairing
teardown, and drop the list reference only once when an entry is
unlinked. Add a dedicated spinlock for IRK list and payload updates, and
copy payload snapshots under that lock so readers do not race updates.
Initialize new entries completely before publishing them. Unlink an IRK
added during unpair before dropping the SMP context reference.
An exact KASAN interleaving that removes and drains the RCU entry after
lookup but before hci_add_irk() resumes now completes without a
use-after-free. A forced late-add/unpair interleaving leaves no linked IRK
behind. A KASAN and lockdep enabled VHCI pairing/unpair test also
completes successfully.
Fixes: a7ec733 ("Bluetooth: Fix removing any IRKs when unpairing devices")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Kazuki Hanai hnkz.64@gmail.com
include/net/bluetooth/hci_core.h | 19 ++-
net/bluetooth/hci_conn.c | 34 ++++--
net/bluetooth/hci_core.c | 202 +++++++++++++++++++++++++------
net/bluetooth/hci_debugfs.c | 6 +-
net/bluetooth/hci_event.c | 16 ++-
net/bluetooth/hci_sync.c | 16 ++-
net/bluetooth/iso.c | 18 ++-
net/bluetooth/mgmt.c | 12 +-
net/bluetooth/smp.c | 20 ++-
9 files changed, 274 insertions(+), 69 deletions(-)