Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: Keep IRKs alive during updates
@ 2026-10-12  3:02 Cen Zhang
  2026-10-12  8:07 ` bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Cen Zhang @ 2026-10-12  3:02 UTC (permalink / raw)
  To: marcel, luiz.dentz, johan.hedberg
  Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427

An IRK selected by hci_add_irk() must remain allocated until its value
and RPA have been copied. hci_find_irk_by_addr() returns a borrowed
pointer after dropping its RCU read lock, leaving the subsequent stores
without lifetime protection on the SMP receive path.

A valid SMP Identity Address Information message can update an existing
IRK while MGMT Load IRKs replaces the identity resolving key list.
l2cap_recv_acldata() drops hdev->lock before SMP processing, so the
connection and channel locks do not exclude load_irks(). One possible
ordering is:

    SMP receive worker               Management / RCU
    hci_add_irk()
      hci_find_irk_by_addr()
        rcu_read_lock()
        find matching IRK
        rcu_read_unlock()
                                     load_irks()
                                       hci_dev_lock()
                                       hci_smp_irks_clear()
                                         list_del_rcu()
                                         kfree_rcu()
                                       hci_dev_unlock()
                                     RCU grace period ends
                                     IRK is freed
      memcpy(irk->val, val, 16)
      bacpy(&irk->rpa, rpa)

The receive worker then writes into freed memory. KASAN reported a
16-byte write in hci_add_irk(), 45 bytes into a freed smp_irk
allocation.

Keep an outer RCU read-side critical section in hci_add_irk() across the
lookup and both copies. Drop it before the GFP_KERNEL allocation and
reacquire it before publishing a new node. Reclamation must then wait
until the stores finish. This also avoids acquiring hdev->lock under the
L2CAP locks, which would invert the existing lock order.

The change has not been runtime-tested.

KASAN report as below:

    ==================================================================
    BUG: KASAN: slab-use-after-free in hci_add_irk+0x77/0x2a0
    Write of size 16 at addr ffff88810bbdcc2d by task kworker/u17:0/526

    Workqueue: hci0 hci_rx_work
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? hci_add_irk+0x77/0x2a0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? hci_add_irk+0x77/0x2a0
     kasan_report+0xe0/0x110
     ? hci_add_irk+0x77/0x2a0
     kasan_check_range+0x105/0x1b0
     __asan_memcpy+0x3c/0x60
     hci_add_irk+0x77/0x2a0
     smp_recv_cb+0x594d/0x8e40
     ? __pfx_smp_recv_cb+0x10/0x10
     ? __pfx___might_resched+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? stack_depot_save_flags+0x29/0x9a0
     ? __mutex_lock+0x182c/0x2590
     ? kasan_save_stack+0x42/0x60
     ? l2cap_recv_frame+0x9ef/0x8830
     ? __kasan_slab_free+0x5f/0x80
     ? kmem_cache_free+0x242/0x580
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? find_held_lock+0x2b/0x80
     ? l2cap_recv_frame+0xaef/0x8830
     ? __pfx___mutex_lock+0x10/0x10
     ? __lock_acquire+0x466/0x2260
     ? __pfx_l2cap_chan_hold_unless_zero+0x10/0x10
     ? l2cap_recv_frame+0x13cc/0x8830
     ? __pfx_smp_recv_cb+0x10/0x10
     l2cap_recv_frame+0x13cc/0x8830
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __mutex_lock+0x182c/0x2590
     ? __pfx_l2cap_recv_frame+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? find_held_lock+0x2b/0x80
     ? l2cap_recv_acldata+0x1eb/0x10e0
     ? __pfx___mutex_lock+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __mutex_unlock_slowpath+0x147/0x920
     ? __pfx_l2cap_conn_hold_unless_zero+0x10/0x10
     ? __pfx_hci_conn_enter_active_mode+0x10/0x10
     ? l2cap_recv_acldata+0x13d/0x10e0
     ? srso_alias_return_thunk+0x5/0xfbef5
     l2cap_recv_acldata+0xe9f/0x10e0
     ? srso_alias_return_thunk+0x5/0xfbef5
     hci_rx_work+0x5a6/0xf00
     ? srso_alias_return_thunk+0x5/0xfbef5
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>

    Allocated by task 520:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_cache_noprof+0x251/0x610
     hci_add_irk+0x131/0x2a0
     load_irks+0x5fb/0x8c0
     hci_sock_sendmsg+0x128b/0x22e0
     sock_write_iter+0x4c0/0x550
     do_iter_readv_writev+0x59c/0x860
     vfs_writev+0x30e/0xc10
     do_writev+0x241/0x2f0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    Freed by task 0:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     __rcu_free_sheaf_prepare+0x65/0x2a0
     rcu_free_sheaf+0x1f/0xe0
     rcu_core+0x661/0x1d10
     handle_softirqs+0x201/0x930
     __irq_exit_rcu+0x110/0x1e0
     irq_exit_rcu+0xe/0x20
     sysvec_apic_timer_interrupt+0x6c/0x80
     asm_sysvec_apic_timer_interrupt+0x1a/0x20

    The buggy address belongs to the object at ffff88810bbdcc00
                                                                which
                                belongs to the cache kmalloc-64 of size 64
    The buggy address is located 45 bytes inside of
                                                                freed
                                64-byte region [ffff88810bbdcc00,
                                ffff88810bbdcc40)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x10bbdc
    flags: 0x200000000000000(node=0|zone=2)
    page_type: f5(slab)
        raw: 0200000000000000 ffff8881000428c0 dead000000000100
    dead000000000122
        raw: 0000000000000000 0000000000200020 00000000f5000000
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff88810bbdcb00: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
     ffff88810bbdcb80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
    >ffff88810bbdcc00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
                                      ^
     ffff88810bbdcc80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
     ffff88810bbdcd00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
    ==================================================================
    Disabling lock debugging due to kernel taint

Fixes: adae20cb2d20 ("Bluetooth: Convert IRK list to RCU")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 209244fd93918..f8c274c21c0f7 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1317,8 +1317,14 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
 {
 	struct smp_irk *irk;
 
+	/*
+	 * Keep the IRK alive until the value and RPA copies are complete.
+	 */
+	rcu_read_lock();
 	irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type);
 	if (!irk) {
+		rcu_read_unlock();
+
 		irk = kzalloc_obj(*irk);
 		if (!irk)
 			return NULL;
@@ -1326,11 +1332,13 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
 		bacpy(&irk->bdaddr, bdaddr);
 		irk->addr_type = addr_type;
 
+		rcu_read_lock();
 		list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
 	}
 
 	memcpy(irk->val, val, 16);
 	bacpy(&irk->rpa, rpa);
+	rcu_read_unlock();
 
 	return irk;
 }

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* RE: Bluetooth: Keep IRKs alive during updates
  2026-10-12  3:02 [PATCH] Bluetooth: Keep IRKs alive during updates Cen Zhang
@ 2026-10-12  8:07 ` bluez.test.bot
  0 siblings, 0 replies; 2+ messages in thread
From: bluez.test.bot @ 2026-10-12  8:07 UTC (permalink / raw)
  To: linux-bluetooth, zzzccc427

[-- Attachment #1: Type: text/plain, Size: 1604 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1183564/

---Test result---

Test Summary:
CheckPatch                    PASS      0.68 seconds
VerifyFixes                   PASS      0.12 seconds
VerifySignedoff               PASS      0.12 seconds
GitLint                       PASS      0.31 seconds
SubjectPrefix                 PASS      0.12 seconds
BuildKernel                   PASS      24.69 seconds
CheckAllWarning               PASS      27.78 seconds
CheckSparse                   PASS      30.55 seconds
BuildKernel32                 PASS      24.90 seconds
CheckKernelLLVM               PASS      25.69 seconds
TestRunnerSetup               PASS      596.48 seconds
TestRunner_l2cap-tester       PASS      13.79 seconds
TestRunner_iso-tester         PASS      9.74 seconds
TestRunner_bnep-tester        PASS      2.94 seconds
TestRunner_mgmt-tester        PASS      57.16 seconds
TestRunner_rfcomm-tester      PASS      4.24 seconds
TestRunner_sco-tester         PASS      5.29 seconds
TestRunner_ioctl-tester       PASS      4.32 seconds
TestRunner_mesh-tester        PASS      5.20 seconds
TestRunner_smp-tester         PASS      4.06 seconds
TestRunner_userchan-tester    PASS      3.35 seconds
TestRunner_6lowpan-tester     PASS      4.09 seconds
IncrementalBuild              PASS      23.50 seconds



https://github.com/bluez/bluetooth-next/pull/903

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-12  8:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-12  3:02 [PATCH] Bluetooth: Keep IRKs alive during updates Cen Zhang
2026-10-12  8:07 ` bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox