Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v1] Bluetooth: HIDP: Fix possible UAF
@ 2026-03-06  2:31 Luiz Augusto von Dentz
  2026-03-06  4:27 ` [v1] " bluez.test.bot
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2026-03-06  2:31 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This fixes the following trace caused by not dropping l2cap_conn
reference when user->remove callback is called:

[   97.809249] l2cap_conn_free: freeing conn ffff88810a171c00
[   97.809907] CPU: 1 UID: 0 PID: 1419 Comm: repro_standalon Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
[   97.809935] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[   97.809947] Call Trace:
[   97.809954]  <TASK>
[   97.809961]  dump_stack_lvl (lib/dump_stack.c:122)
[   97.809990]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
[   97.810017]  l2cap_conn_del (./include/linux/kref.h:66 net/bluetooth/l2cap_core.c:1821 net/bluetooth/l2cap_core.c:1798)
[   97.810055]  l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7347 (discriminator 1) net/bluetooth/l2cap_core.c:7340 (discriminator 1))
[   97.810086]  ? __pfx_l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7341)
[   97.810117]  hci_conn_hash_flush (./include/net/bluetooth/hci_core.h:2152 (discriminator 2) net/bluetooth/hci_conn.c:2644 (discriminator 2))
[   97.810148]  hci_dev_close_sync (net/bluetooth/hci_sync.c:5360)
[   97.810180]  ? __pfx_hci_dev_close_sync (net/bluetooth/hci_sync.c:5285)
[   97.810212]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810242]  ? up_write (./arch/x86/include/asm/atomic64_64.h:87 (discriminator 5) ./include/linux/atomic/atomic-arch-fallback.h:2852 (discriminator 5) ./include/linux/atomic/atomic-long.h:268 (discriminator 5) ./include/linux/atomic/atomic-instrumented.h:3391 (discriminator 5) kernel/locking/rwsem.c:1385 (discriminator 5) kernel/locking/rwsem.c:1643 (discriminator 5))
[   97.810267]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810290]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
[   97.810320]  hci_unregister_dev (net/bluetooth/hci_core.c:504 net/bluetooth/hci_core.c:2716)
[   97.810346]  vhci_release (drivers/bluetooth/hci_vhci.c:691)
[   97.810375]  ? __pfx_vhci_release (drivers/bluetooth/hci_vhci.c:678)
[   97.810404]  __fput (fs/file_table.c:470)
[   97.810430]  task_work_run (kernel/task_work.c:235)
[   97.810451]  ? __pfx_task_work_run (kernel/task_work.c:201)
[   97.810472]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810495]  ? do_raw_spin_unlock (./include/asm-generic/qspinlock.h:128 (discriminator 5) kernel/locking/spinlock_debug.c:142 (discriminator 5))
[   97.810527]  do_exit (kernel/exit.c:972)
[   97.810547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810574]  ? __pfx_do_exit (kernel/exit.c:897)
[   97.810594]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
[   97.810616]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810639]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
[   97.810664]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810688]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   97.810721]  do_group_exit (kernel/exit.c:1093)
[   97.810745]  get_signal (kernel/signal.c:3007 (discriminator 1))
[   97.810772]  ? security_file_permission (./arch/x86/include/asm/jump_label.h:37 security/security.c:2366)
[   97.810803]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810826]  ? vfs_read (fs/read_write.c:555)
[   97.810854]  ? __pfx_get_signal (kernel/signal.c:2800)
[   97.810880]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810905]  ? __pfx_vfs_read (fs/read_write.c:555)
[   97.810932]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810960]  arch_do_signal_or_restart (arch/x86/kernel/signal.c:337 (discriminator 1))
[   97.810990]  ? __pfx_arch_do_signal_or_restart (arch/x86/kernel/signal.c:334)
[   97.811021]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811055]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811078]  ? ksys_read (fs/read_write.c:707)
[   97.811106]  ? __pfx_ksys_read (fs/read_write.c:707)
[   97.811137]  exit_to_user_mode_loop (kernel/entry/common.c:66 kernel/entry/common.c:98)
[   97.811169]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
[   97.811192]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811215]  ? trace_hardirqs_off (./include/trace/events/preemptirq.h:36 (discriminator 33) kernel/trace/trace_preemptirq.c:95 (discriminator 33) kernel/trace/trace_preemptirq.c:90 (discriminator 33))
[   97.811240]  do_syscall_64 (./include/linux/irq-entry-common.h:226 ./include/linux/irq-entry-common.h:256 ./include/linux/entry-common.h:325 arch/x86/entry/syscall_64.c:100)
[   97.811268]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811292]  ? exc_page_fault (arch/x86/mm/fault.c:1480 (discriminator 3) arch/x86/mm/fault.c:1527 (discriminator 3))
[   97.811318]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
[   97.811338] RIP: 0033:0x445cfe
[   97.811352] Code: Unable to access opcode bytes at 0x445cd4.

Code starting with the faulting instruction
===========================================
[   97.811360] RSP: 002b:00007f65c41c6dc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
[   97.811378] RAX: fffffffffffffe00 RBX: 00007f65c41c76c0 RCX: 0000000000445cfe
[   97.811391] RDX: 0000000000000400 RSI: 00007f65c41c6e40 RDI: 0000000000000004
[   97.811403] RBP: 00007f65c41c7250 R08: 0000000000000000 R09: 0000000000000000
[   97.811415] R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffffe8
[   97.811428] R13: 0000000000000000 R14: 00007fff780a8c00 R15: 00007f65c41c76c0
[   97.811453]  </TASK>
[   98.402453] ==================================================================
[   98.403560] BUG: KASAN: use-after-free in __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.404541] Read of size 8 at addr ffff888113ee40a8 by task khidpd_00050004/1430
[   98.405361]
[   98.405563] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
[   98.405588] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[   98.405600] Call Trace:
[   98.405607]  <TASK>
[   98.405614]  dump_stack_lvl (lib/dump_stack.c:122)
[   98.405641]  print_report (mm/kasan/report.c:379 mm/kasan/report.c:482)
[   98.405667]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.405691]  ? __virt_addr_valid (arch/x86/mm/physaddr.c:55)
[   98.405724]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.405748]  kasan_report (mm/kasan/report.c:221 mm/kasan/report.c:597)
[   98.405778]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.405807]  __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.405832]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
[   98.405859]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
[   98.405888]  ? __pfx_do_raw_spin_lock (kernel/locking/spinlock_debug.c:114)
[   98.405915]  ? __pfx___mutex_lock (kernel/locking/mutex.c:775)
[   98.405939]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.405963]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
[   98.405984]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   98.406015]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406038]  ? lock_release (kernel/locking/lockdep.c:5536 kernel/locking/lockdep.c:5889 kernel/locking/lockdep.c:5875)
[   98.406061]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406085]  ? _raw_spin_unlock_irqrestore (./arch/x86/include/asm/irqflags.h:42 ./arch/x86/include/asm/irqflags.h:119 ./arch/x86/include/asm/irqflags.h:159 ./include/linux/spinlock_api_smp.h:178 kernel/locking/spinlock.c:194)
[   98.406107]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406130]  ? __timer_delete_sync (kernel/time/timer.c:1592)
[   98.406158]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
[   98.406186]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406210]  l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
[   98.406263]  hidp_session_thread (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 ./include/linux/kref.h:64 net/bluetooth/hidp/core.c:996 net/bluetooth/hidp/core.c:1305)
[   98.406293]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.406323]  ? kthread (kernel/kthread.c:433)
[   98.406340]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.406370]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406393]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   98.406424]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.406453]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406476]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
[   98.406499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406523]  ? kthread (kernel/kthread.c:433)
[   98.406539]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406565]  ? kthread (kernel/kthread.c:433)
[   98.406581]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.406610]  kthread (kernel/kthread.c:467)
[   98.406627]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.406645]  ret_from_fork (arch/x86/kernel/process.c:164)
[   98.406674]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
[   98.406704]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406728]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.406747]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
[   98.406774]  </TASK>
[   98.406780]
[   98.433693] The buggy address belongs to the physical page:
[   98.434405] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888113ee7c40 pfn:0x113ee4
[   98.435557] flags: 0x200000000000000(node=0|zone=2)
[   98.436198] raw: 0200000000000000 ffffea0004244308 ffff8881f6f3ebc0 0000000000000000
[   98.437195] raw: ffff888113ee7c40 0000000000000000 00000000ffffffff 0000000000000000
[   98.438115] page dumped because: kasan: bad access detected
[   98.438951]
[   98.439211] Memory state around the buggy address:
[   98.439871]  ffff888113ee3f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   98.440714]  ffff888113ee4000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.441580] >ffff888113ee4080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.442458]                                   ^
[   98.443011]  ffff888113ee4100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.443889]  ffff888113ee4180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.444768] ==================================================================
[   98.445719] Disabling lock debugging due to kernel taint
[   98.448074] l2cap_conn_free: freeing conn ffff88810c22b400
[   98.450012] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Tainted: G    B               7.0.0-rc1-dirty #14 PREEMPT(lazy)
[   98.450040] Tainted: [B]=BAD_PAGE
[   98.450047] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[   98.450059] Call Trace:
[   98.450065]  <TASK>
[   98.450071]  dump_stack_lvl (lib/dump_stack.c:122)
[   98.450099]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
[   98.450125]  l2cap_conn_put (net/bluetooth/l2cap_core.c:1822)
[   98.450154]  session_free (net/bluetooth/hidp/core.c:990)
[   98.450181]  hidp_session_thread (net/bluetooth/hidp/core.c:1307)
[   98.450213]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.450271]  ? kthread (kernel/kthread.c:433)
[   98.450293]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.450339]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450368]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   98.450406]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.450442]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450471]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
[   98.450499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450528]  ? kthread (kernel/kthread.c:433)
[   98.450547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450578]  ? kthread (kernel/kthread.c:433)
[   98.450598]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.450637]  kthread (kernel/kthread.c:467)
[   98.450657]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.450680]  ret_from_fork (arch/x86/kernel/process.c:164)
[   98.450715]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
[   98.450752]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450782]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.450804]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
[   98.450836]  </TASK>

Fixes: b4f34d8d9d26 ("Bluetooth: hidp: add new session-management helpers")
Reported-by: soufiane el hachmi <kilwa10@gmail.com>
Tested-by: soufiane el hachmi <kilwa10@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hidp/core.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 6724adce615b..e0e400381550 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -986,7 +986,8 @@ static void session_free(struct kref *ref)
 	skb_queue_purge(&session->intr_transmit);
 	fput(session->intr_sock->file);
 	fput(session->ctrl_sock->file);
-	l2cap_conn_put(session->conn);
+	if (session->conn)
+		l2cap_conn_put(session->conn);
 	kfree(session);
 }
 
@@ -1164,6 +1165,15 @@ static void hidp_session_remove(struct l2cap_conn *conn,
 
 	down_write(&hidp_session_sem);
 
+	/* Drop L2CAP reference immediately to indicate that
+	 * l2cap_unregister_user() shall not be called as it is already
+	 * considered removed.
+	 */
+	if (session->conn) {
+		l2cap_conn_put(session->conn);
+		session->conn = NULL;
+	}
+
 	hidp_session_terminate(session);
 
 	cancel_work_sync(&session->dev_init);
@@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg)
 	 * Instead, this call has the same semantics as if user-space tried to
 	 * delete the session.
 	 */
-	l2cap_unregister_user(session->conn, &session->user);
+	if (session->conn)
+		l2cap_unregister_user(session->conn, &session->user);
+
 	hidp_session_put(session);
 
 	module_put_and_kthread_exit(0);
-- 
2.53.0


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

* RE: [v1] Bluetooth: HIDP: Fix possible UAF
  2026-03-06  2:31 [PATCH v1] Bluetooth: HIDP: Fix possible UAF Luiz Augusto von Dentz
@ 2026-03-06  4:27 ` bluez.test.bot
  2026-03-06 18:40 ` [PATCH v1] " patchwork-bot+bluetooth
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-03-06  4:27 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

[-- Attachment #1: Type: text/plain, Size: 3149 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/project/bluetooth/list/?series=1062284

---Test result---

Test Summary:
CheckPatch                    PENDING   0.33 seconds
GitLint                       PENDING   0.26 seconds
SubjectPrefix                 PASS      0.12 seconds
BuildKernel                   PASS      26.03 seconds
CheckAllWarning               PASS      28.99 seconds
CheckSparse                   WARNING   32.97 seconds
BuildKernel32                 PASS      25.60 seconds
TestRunnerSetup               PASS      566.00 seconds
TestRunner_l2cap-tester       PASS      28.89 seconds
TestRunner_iso-tester         PASS      94.23 seconds
TestRunner_bnep-tester        PASS      6.47 seconds
TestRunner_mgmt-tester        FAIL      118.14 seconds
TestRunner_rfcomm-tester      PASS      9.63 seconds
TestRunner_sco-tester         FAIL      14.71 seconds
TestRunner_ioctl-tester       PASS      10.26 seconds
TestRunner_mesh-tester        FAIL      12.43 seconds
TestRunner_smp-tester         PASS      8.67 seconds
TestRunner_userchan-tester    PASS      6.76 seconds
IncrementalBuild              PENDING   0.79 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:
net/bluetooth/hidp/core.c:1486:1: error: bad constant expressionnet/bluetooth/hidp/core.c:1487:1: error: bad constant expressionnet/bluetooth/hidp/core.c:1488:1: error: bad constant expressionnet/bluetooth/hidp/core.c:1489:1: error: bad constant expressionnet/bluetooth/hidp/core.c:1490:1: error: bad constant expressionnet/bluetooth/hidp/core.c:1490:1: error: bad constant expressionnet/bluetooth/hidp/core.c:1491:1: error: bad constant expression
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.112 seconds
##############################
Test: TestRunner_sco-tester - FAIL
Desc: Run sco-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
BUG: sleeping function called from invalid context at net/core/sock.c:3782
Total: 30, Passed: 30 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.607 seconds
Mesh - Send cancel - 2                               Timed out    1.998 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



---
Regards,
Linux Bluetooth


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

* Re: [PATCH v1] Bluetooth: HIDP: Fix possible UAF
  2026-03-06  2:31 [PATCH v1] Bluetooth: HIDP: Fix possible UAF Luiz Augusto von Dentz
  2026-03-06  4:27 ` [v1] " bluez.test.bot
@ 2026-03-06 18:40 ` patchwork-bot+bluetooth
  2026-03-06 18:49 ` Pauli Virtanen
  2026-04-22  1:14 ` [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del Michael Bommarito
  3 siblings, 0 replies; 14+ messages in thread
From: patchwork-bot+bluetooth @ 2026-03-06 18:40 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hello:

This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Thu,  5 Mar 2026 21:31:55 -0500 you wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> This fixes the following trace caused by not dropping l2cap_conn
> reference when user->remove callback is called:
> 
> [   97.809249] l2cap_conn_free: freeing conn ffff88810a171c00
> [   97.809907] CPU: 1 UID: 0 PID: 1419 Comm: repro_standalon Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
> [   97.809935] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> [   97.809947] Call Trace:
> [   97.809954]  <TASK>
> [   97.809961]  dump_stack_lvl (lib/dump_stack.c:122)
> [   97.809990]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
> [   97.810017]  l2cap_conn_del (./include/linux/kref.h:66 net/bluetooth/l2cap_core.c:1821 net/bluetooth/l2cap_core.c:1798)
> [   97.810055]  l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7347 (discriminator 1) net/bluetooth/l2cap_core.c:7340 (discriminator 1))
> [   97.810086]  ? __pfx_l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7341)
> [   97.810117]  hci_conn_hash_flush (./include/net/bluetooth/hci_core.h:2152 (discriminator 2) net/bluetooth/hci_conn.c:2644 (discriminator 2))
> [   97.810148]  hci_dev_close_sync (net/bluetooth/hci_sync.c:5360)
> [   97.810180]  ? __pfx_hci_dev_close_sync (net/bluetooth/hci_sync.c:5285)
> [   97.810212]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810242]  ? up_write (./arch/x86/include/asm/atomic64_64.h:87 (discriminator 5) ./include/linux/atomic/atomic-arch-fallback.h:2852 (discriminator 5) ./include/linux/atomic/atomic-long.h:268 (discriminator 5) ./include/linux/atomic/atomic-instrumented.h:3391 (discriminator 5) kernel/locking/rwsem.c:1385 (discriminator 5) kernel/locking/rwsem.c:1643 (discriminator 5))
> [   97.810267]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810290]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
> [   97.810320]  hci_unregister_dev (net/bluetooth/hci_core.c:504 net/bluetooth/hci_core.c:2716)
> [   97.810346]  vhci_release (drivers/bluetooth/hci_vhci.c:691)
> [   97.810375]  ? __pfx_vhci_release (drivers/bluetooth/hci_vhci.c:678)
> [   97.810404]  __fput (fs/file_table.c:470)
> [   97.810430]  task_work_run (kernel/task_work.c:235)
> [   97.810451]  ? __pfx_task_work_run (kernel/task_work.c:201)
> [   97.810472]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810495]  ? do_raw_spin_unlock (./include/asm-generic/qspinlock.h:128 (discriminator 5) kernel/locking/spinlock_debug.c:142 (discriminator 5))
> [   97.810527]  do_exit (kernel/exit.c:972)
> [   97.810547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810574]  ? __pfx_do_exit (kernel/exit.c:897)
> [   97.810594]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
> [   97.810616]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810639]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
> [   97.810664]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810688]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> [   97.810721]  do_group_exit (kernel/exit.c:1093)
> [   97.810745]  get_signal (kernel/signal.c:3007 (discriminator 1))
> [   97.810772]  ? security_file_permission (./arch/x86/include/asm/jump_label.h:37 security/security.c:2366)
> [   97.810803]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810826]  ? vfs_read (fs/read_write.c:555)
> [   97.810854]  ? __pfx_get_signal (kernel/signal.c:2800)
> [   97.810880]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810905]  ? __pfx_vfs_read (fs/read_write.c:555)
> [   97.810932]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810960]  arch_do_signal_or_restart (arch/x86/kernel/signal.c:337 (discriminator 1))
> [   97.810990]  ? __pfx_arch_do_signal_or_restart (arch/x86/kernel/signal.c:334)
> [   97.811021]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811055]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811078]  ? ksys_read (fs/read_write.c:707)
> [   97.811106]  ? __pfx_ksys_read (fs/read_write.c:707)
> [   97.811137]  exit_to_user_mode_loop (kernel/entry/common.c:66 kernel/entry/common.c:98)
> [   97.811169]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
> [   97.811192]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811215]  ? trace_hardirqs_off (./include/trace/events/preemptirq.h:36 (discriminator 33) kernel/trace/trace_preemptirq.c:95 (discriminator 33) kernel/trace/trace_preemptirq.c:90 (discriminator 33))
> [   97.811240]  do_syscall_64 (./include/linux/irq-entry-common.h:226 ./include/linux/irq-entry-common.h:256 ./include/linux/entry-common.h:325 arch/x86/entry/syscall_64.c:100)
> [   97.811268]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811292]  ? exc_page_fault (arch/x86/mm/fault.c:1480 (discriminator 3) arch/x86/mm/fault.c:1527 (discriminator 3))
> [   97.811318]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
> [   97.811338] RIP: 0033:0x445cfe
> [   97.811352] Code: Unable to access opcode bytes at 0x445cd4.
> 
> [...]

Here is the summary with links:
  - [v1] Bluetooth: HIDP: Fix possible UAF
    https://git.kernel.org/bluetooth/bluetooth-next/c/708efc5f2338

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

* Re: [PATCH v1] Bluetooth: HIDP: Fix possible UAF
  2026-03-06  2:31 [PATCH v1] Bluetooth: HIDP: Fix possible UAF Luiz Augusto von Dentz
  2026-03-06  4:27 ` [v1] " bluez.test.bot
  2026-03-06 18:40 ` [PATCH v1] " patchwork-bot+bluetooth
@ 2026-03-06 18:49 ` Pauli Virtanen
  2026-03-06 19:23   ` Luiz Augusto von Dentz
  2026-04-22  1:14 ` [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del Michael Bommarito
  3 siblings, 1 reply; 14+ messages in thread
From: Pauli Virtanen @ 2026-03-06 18:49 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, linux-bluetooth

Hi,

to, 2026-03-05 kello 21:31 -0500, Luiz Augusto von Dentz kirjoitti:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> This fixes the following trace caused by not dropping l2cap_conn
> reference when user->remove callback is called:
> 
> [   97.809249] l2cap_conn_free: freeing conn ffff88810a171c00
> [   97.809907] CPU: 1 UID: 0 PID: 1419 Comm: repro_standalon Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
> [   97.809935] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> [   97.809947] Call Trace:
> [   97.809954]  <TASK>
> [   97.809961]  dump_stack_lvl (lib/dump_stack.c:122)
> [   97.809990]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
> [   97.810017]  l2cap_conn_del (./include/linux/kref.h:66 net/bluetooth/l2cap_core.c:1821 net/bluetooth/l2cap_core.c:1798)
> [   97.810055]  l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7347 (discriminator 1) net/bluetooth/l2cap_core.c:7340 (discriminator 1))
> [   97.810086]  ? __pfx_l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7341)
> [   97.810117]  hci_conn_hash_flush (./include/net/bluetooth/hci_core.h:2152 (discriminator 2) net/bluetooth/hci_conn.c:2644 (discriminator 2))
> [   97.810148]  hci_dev_close_sync (net/bluetooth/hci_sync.c:5360)
> [   97.810180]  ? __pfx_hci_dev_close_sync (net/bluetooth/hci_sync.c:5285)
> [   97.810212]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810242]  ? up_write (./arch/x86/include/asm/atomic64_64.h:87 (discriminator 5) ./include/linux/atomic/atomic-arch-fallback.h:2852 (discriminator 5) ./include/linux/atomic/atomic-long.h:268 (discriminator 5) ./include/linux/atomic/atomic-instrumented.h:3391 (discriminator 5) kernel/locking/rwsem.c:1385 (discriminator 5) kernel/locking/rwsem.c:1643 (discriminator 5))
> [   97.810267]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810290]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
> [   97.810320]  hci_unregister_dev (net/bluetooth/hci_core.c:504 net/bluetooth/hci_core.c:2716)
> [   97.810346]  vhci_release (drivers/bluetooth/hci_vhci.c:691)
> [   97.810375]  ? __pfx_vhci_release (drivers/bluetooth/hci_vhci.c:678)
> [   97.810404]  __fput (fs/file_table.c:470)
> [   97.810430]  task_work_run (kernel/task_work.c:235)
> [   97.810451]  ? __pfx_task_work_run (kernel/task_work.c:201)
> [   97.810472]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810495]  ? do_raw_spin_unlock (./include/asm-generic/qspinlock.h:128 (discriminator 5) kernel/locking/spinlock_debug.c:142 (discriminator 5))
> [   97.810527]  do_exit (kernel/exit.c:972)
> [   97.810547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810574]  ? __pfx_do_exit (kernel/exit.c:897)
> [   97.810594]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
> [   97.810616]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810639]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
> [   97.810664]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810688]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> [   97.810721]  do_group_exit (kernel/exit.c:1093)
> [   97.810745]  get_signal (kernel/signal.c:3007 (discriminator 1))
> [   97.810772]  ? security_file_permission (./arch/x86/include/asm/jump_label.h:37 security/security.c:2366)
> [   97.810803]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810826]  ? vfs_read (fs/read_write.c:555)
> [   97.810854]  ? __pfx_get_signal (kernel/signal.c:2800)
> [   97.810880]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810905]  ? __pfx_vfs_read (fs/read_write.c:555)
> [   97.810932]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.810960]  arch_do_signal_or_restart (arch/x86/kernel/signal.c:337 (discriminator 1))
> [   97.810990]  ? __pfx_arch_do_signal_or_restart (arch/x86/kernel/signal.c:334)
> [   97.811021]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811055]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811078]  ? ksys_read (fs/read_write.c:707)
> [   97.811106]  ? __pfx_ksys_read (fs/read_write.c:707)
> [   97.811137]  exit_to_user_mode_loop (kernel/entry/common.c:66 kernel/entry/common.c:98)
> [   97.811169]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
> [   97.811192]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811215]  ? trace_hardirqs_off (./include/trace/events/preemptirq.h:36 (discriminator 33) kernel/trace/trace_preemptirq.c:95 (discriminator 33) kernel/trace/trace_preemptirq.c:90 (discriminator 33))
> [   97.811240]  do_syscall_64 (./include/linux/irq-entry-common.h:226 ./include/linux/irq-entry-common.h:256 ./include/linux/entry-common.h:325 arch/x86/entry/syscall_64.c:100)
> [   97.811268]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   97.811292]  ? exc_page_fault (arch/x86/mm/fault.c:1480 (discriminator 3) arch/x86/mm/fault.c:1527 (discriminator 3))
> [   97.811318]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
> [   97.811338] RIP: 0033:0x445cfe
> [   97.811352] Code: Unable to access opcode bytes at 0x445cd4.
> 
> Code starting with the faulting instruction
> ===========================================
> [   97.811360] RSP: 002b:00007f65c41c6dc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
> [   97.811378] RAX: fffffffffffffe00 RBX: 00007f65c41c76c0 RCX: 0000000000445cfe
> [   97.811391] RDX: 0000000000000400 RSI: 00007f65c41c6e40 RDI: 0000000000000004
> [   97.811403] RBP: 00007f65c41c7250 R08: 0000000000000000 R09: 0000000000000000
> [   97.811415] R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffffe8
> [   97.811428] R13: 0000000000000000 R14: 00007fff780a8c00 R15: 00007f65c41c76c0
> [   97.811453]  </TASK>
> [   98.402453] ==================================================================
> [   98.403560] BUG: KASAN: use-after-free in __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> [   98.404541] Read of size 8 at addr ffff888113ee40a8 by task khidpd_00050004/1430
> [   98.405361]
> [   98.405563] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
> [   98.405588] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> [   98.405600] Call Trace:
> [   98.405607]  <TASK>
> [   98.405614]  dump_stack_lvl (lib/dump_stack.c:122)
> [   98.405641]  print_report (mm/kasan/report.c:379 mm/kasan/report.c:482)
> [   98.405667]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.405691]  ? __virt_addr_valid (arch/x86/mm/physaddr.c:55)
> [   98.405724]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> [   98.405748]  kasan_report (mm/kasan/report.c:221 mm/kasan/report.c:597)
> [   98.405778]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> [   98.405807]  __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> [   98.405832]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
> [   98.405859]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
> [   98.405888]  ? __pfx_do_raw_spin_lock (kernel/locking/spinlock_debug.c:114)
> [   98.405915]  ? __pfx___mutex_lock (kernel/locking/mutex.c:775)
> [   98.405939]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.405963]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
> [   98.405984]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> [   98.406015]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406038]  ? lock_release (kernel/locking/lockdep.c:5536 kernel/locking/lockdep.c:5889 kernel/locking/lockdep.c:5875)
> [   98.406061]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406085]  ? _raw_spin_unlock_irqrestore (./arch/x86/include/asm/irqflags.h:42 ./arch/x86/include/asm/irqflags.h:119 ./arch/x86/include/asm/irqflags.h:159 ./include/linux/spinlock_api_smp.h:178 kernel/locking/spinlock.c:194)
> [   98.406107]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406130]  ? __timer_delete_sync (kernel/time/timer.c:1592)
> [   98.406158]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
> [   98.406186]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406210]  l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
> [   98.406263]  hidp_session_thread (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 ./include/linux/kref.h:64 net/bluetooth/hidp/core.c:996 net/bluetooth/hidp/core.c:1305)
> [   98.406293]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> [   98.406323]  ? kthread (kernel/kthread.c:433)
> [   98.406340]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> [   98.406370]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406393]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> [   98.406424]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> [   98.406453]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406476]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
> [   98.406499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406523]  ? kthread (kernel/kthread.c:433)
> [   98.406539]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406565]  ? kthread (kernel/kthread.c:433)
> [   98.406581]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> [   98.406610]  kthread (kernel/kthread.c:467)
> [   98.406627]  ? __pfx_kthread (kernel/kthread.c:412)
> [   98.406645]  ret_from_fork (arch/x86/kernel/process.c:164)
> [   98.406674]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
> [   98.406704]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.406728]  ? __pfx_kthread (kernel/kthread.c:412)
> [   98.406747]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
> [   98.406774]  </TASK>
> [   98.406780]
> [   98.433693] The buggy address belongs to the physical page:
> [   98.434405] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888113ee7c40 pfn:0x113ee4
> [   98.435557] flags: 0x200000000000000(node=0|zone=2)
> [   98.436198] raw: 0200000000000000 ffffea0004244308 ffff8881f6f3ebc0 0000000000000000
> [   98.437195] raw: ffff888113ee7c40 0000000000000000 00000000ffffffff 0000000000000000
> [   98.438115] page dumped because: kasan: bad access detected
> [   98.438951]
> [   98.439211] Memory state around the buggy address:
> [   98.439871]  ffff888113ee3f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [   98.440714]  ffff888113ee4000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [   98.441580] >ffff888113ee4080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [   98.442458]                                   ^
> [   98.443011]  ffff888113ee4100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [   98.443889]  ffff888113ee4180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [   98.444768] ==================================================================
> [   98.445719] Disabling lock debugging due to kernel taint
> [   98.448074] l2cap_conn_free: freeing conn ffff88810c22b400
> [   98.450012] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Tainted: G    B               7.0.0-rc1-dirty #14 PREEMPT(lazy)
> [   98.450040] Tainted: [B]=BAD_PAGE
> [   98.450047] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> [   98.450059] Call Trace:
> [   98.450065]  <TASK>
> [   98.450071]  dump_stack_lvl (lib/dump_stack.c:122)
> [   98.450099]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
> [   98.450125]  l2cap_conn_put (net/bluetooth/l2cap_core.c:1822)
> [   98.450154]  session_free (net/bluetooth/hidp/core.c:990)
> [   98.450181]  hidp_session_thread (net/bluetooth/hidp/core.c:1307)
> [   98.450213]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> [   98.450271]  ? kthread (kernel/kthread.c:433)
> [   98.450293]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> [   98.450339]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.450368]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> [   98.450406]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> [   98.450442]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.450471]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
> [   98.450499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.450528]  ? kthread (kernel/kthread.c:433)
> [   98.450547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.450578]  ? kthread (kernel/kthread.c:433)
> [   98.450598]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> [   98.450637]  kthread (kernel/kthread.c:467)
> [   98.450657]  ? __pfx_kthread (kernel/kthread.c:412)
> [   98.450680]  ret_from_fork (arch/x86/kernel/process.c:164)
> [   98.450715]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
> [   98.450752]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> [   98.450782]  ? __pfx_kthread (kernel/kthread.c:412)
> [   98.450804]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
> [   98.450836]  </TASK>
> 
> Fixes: b4f34d8d9d26 ("Bluetooth: hidp: add new session-management helpers")
> Reported-by: soufiane el hachmi <kilwa10@gmail.com>
> Tested-by: soufiane el hachmi <kilwa10@gmail.com>
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
>  net/bluetooth/hidp/core.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index 6724adce615b..e0e400381550 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
> @@ -986,7 +986,8 @@ static void session_free(struct kref *ref)
>  	skb_queue_purge(&session->intr_transmit);
>  	fput(session->intr_sock->file);
>  	fput(session->ctrl_sock->file);
> -	l2cap_conn_put(session->conn);
> +	if (session->conn)
> +		l2cap_conn_put(session->conn);
>  	kfree(session);
>  }
>  
> @@ -1164,6 +1165,15 @@ static void hidp_session_remove(struct l2cap_conn *conn,
>  
>  	down_write(&hidp_session_sem);
>  
> +	/* Drop L2CAP reference immediately to indicate that
> +	 * l2cap_unregister_user() shall not be called as it is already
> +	 * considered removed.
> +	 */
> +	if (session->conn) {
> +		l2cap_conn_put(session->conn);
> +		session->conn = NULL;
> +	}
> +
>  	hidp_session_terminate(session);
>  
>  	cancel_work_sync(&session->dev_init);
> @@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg)
>  	 * Instead, this call has the same semantics as if user-space tried to
>  	 * delete the session.
>  	 */
> -	l2cap_unregister_user(session->conn, &session->user);
> +	if (session->conn)
> +		l2cap_unregister_user(session->conn, &session->user);

Does this TOCTOU on session->conn:

[Task 1]                             [Task 2]
hci_dev_lock()
  l2cap_disconn_cfm()
    l2cap_conn_del()
                                     if (session->conn)
      hidp_session_remove()
      l2cap_conn_free()
                                       l2cap_unregister_user()
                                         hdev = conn->hcon->hdev <UAF>

I wonder if it is same issue as
https://syzkaller.appspot.com/bug?extid=14b6d57fb728e27ce23c

and I remember the earlier patch that tries to address the race via
changing the locking:

https://lore.kernel.org/all/20251106182016.26508-1-ssranevjti@gmail.com/

AFAICS, done that way the call to l2cap_unregister_user() in
hidp_session_thread() should be noop via the !list_empty(&user->list)
branch, as the hidp_session_remove() already ran. session->conn would
remain until it is put when session->ref refcount goes to zero.


> +
>  	hidp_session_put(session);
>  
>  	module_put_and_kthread_exit(0);

-- 
Pauli Virtanen

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

* Re: [PATCH v1] Bluetooth: HIDP: Fix possible UAF
  2026-03-06 18:49 ` Pauli Virtanen
@ 2026-03-06 19:23   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2026-03-06 19:23 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: linux-bluetooth

Hi Pauli,

On Fri, Mar 6, 2026 at 1:49 PM Pauli Virtanen <pav@iki.fi> wrote:
>
> Hi,
>
> to, 2026-03-05 kello 21:31 -0500, Luiz Augusto von Dentz kirjoitti:
> > From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> >
> > This fixes the following trace caused by not dropping l2cap_conn
> > reference when user->remove callback is called:
> >
> > [   97.809249] l2cap_conn_free: freeing conn ffff88810a171c00
> > [   97.809907] CPU: 1 UID: 0 PID: 1419 Comm: repro_standalon Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
> > [   97.809935] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> > [   97.809947] Call Trace:
> > [   97.809954]  <TASK>
> > [   97.809961]  dump_stack_lvl (lib/dump_stack.c:122)
> > [   97.809990]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
> > [   97.810017]  l2cap_conn_del (./include/linux/kref.h:66 net/bluetooth/l2cap_core.c:1821 net/bluetooth/l2cap_core.c:1798)
> > [   97.810055]  l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7347 (discriminator 1) net/bluetooth/l2cap_core.c:7340 (discriminator 1))
> > [   97.810086]  ? __pfx_l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7341)
> > [   97.810117]  hci_conn_hash_flush (./include/net/bluetooth/hci_core.h:2152 (discriminator 2) net/bluetooth/hci_conn.c:2644 (discriminator 2))
> > [   97.810148]  hci_dev_close_sync (net/bluetooth/hci_sync.c:5360)
> > [   97.810180]  ? __pfx_hci_dev_close_sync (net/bluetooth/hci_sync.c:5285)
> > [   97.810212]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810242]  ? up_write (./arch/x86/include/asm/atomic64_64.h:87 (discriminator 5) ./include/linux/atomic/atomic-arch-fallback.h:2852 (discriminator 5) ./include/linux/atomic/atomic-long.h:268 (discriminator 5) ./include/linux/atomic/atomic-instrumented.h:3391 (discriminator 5) kernel/locking/rwsem.c:1385 (discriminator 5) kernel/locking/rwsem.c:1643 (discriminator 5))
> > [   97.810267]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810290]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
> > [   97.810320]  hci_unregister_dev (net/bluetooth/hci_core.c:504 net/bluetooth/hci_core.c:2716)
> > [   97.810346]  vhci_release (drivers/bluetooth/hci_vhci.c:691)
> > [   97.810375]  ? __pfx_vhci_release (drivers/bluetooth/hci_vhci.c:678)
> > [   97.810404]  __fput (fs/file_table.c:470)
> > [   97.810430]  task_work_run (kernel/task_work.c:235)
> > [   97.810451]  ? __pfx_task_work_run (kernel/task_work.c:201)
> > [   97.810472]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810495]  ? do_raw_spin_unlock (./include/asm-generic/qspinlock.h:128 (discriminator 5) kernel/locking/spinlock_debug.c:142 (discriminator 5))
> > [   97.810527]  do_exit (kernel/exit.c:972)
> > [   97.810547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810574]  ? __pfx_do_exit (kernel/exit.c:897)
> > [   97.810594]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
> > [   97.810616]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810639]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
> > [   97.810664]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810688]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> > [   97.810721]  do_group_exit (kernel/exit.c:1093)
> > [   97.810745]  get_signal (kernel/signal.c:3007 (discriminator 1))
> > [   97.810772]  ? security_file_permission (./arch/x86/include/asm/jump_label.h:37 security/security.c:2366)
> > [   97.810803]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810826]  ? vfs_read (fs/read_write.c:555)
> > [   97.810854]  ? __pfx_get_signal (kernel/signal.c:2800)
> > [   97.810880]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810905]  ? __pfx_vfs_read (fs/read_write.c:555)
> > [   97.810932]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.810960]  arch_do_signal_or_restart (arch/x86/kernel/signal.c:337 (discriminator 1))
> > [   97.810990]  ? __pfx_arch_do_signal_or_restart (arch/x86/kernel/signal.c:334)
> > [   97.811021]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.811055]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.811078]  ? ksys_read (fs/read_write.c:707)
> > [   97.811106]  ? __pfx_ksys_read (fs/read_write.c:707)
> > [   97.811137]  exit_to_user_mode_loop (kernel/entry/common.c:66 kernel/entry/common.c:98)
> > [   97.811169]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
> > [   97.811192]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.811215]  ? trace_hardirqs_off (./include/trace/events/preemptirq.h:36 (discriminator 33) kernel/trace/trace_preemptirq.c:95 (discriminator 33) kernel/trace/trace_preemptirq.c:90 (discriminator 33))
> > [   97.811240]  do_syscall_64 (./include/linux/irq-entry-common.h:226 ./include/linux/irq-entry-common.h:256 ./include/linux/entry-common.h:325 arch/x86/entry/syscall_64.c:100)
> > [   97.811268]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   97.811292]  ? exc_page_fault (arch/x86/mm/fault.c:1480 (discriminator 3) arch/x86/mm/fault.c:1527 (discriminator 3))
> > [   97.811318]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
> > [   97.811338] RIP: 0033:0x445cfe
> > [   97.811352] Code: Unable to access opcode bytes at 0x445cd4.
> >
> > Code starting with the faulting instruction
> > ===========================================
> > [   97.811360] RSP: 002b:00007f65c41c6dc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
> > [   97.811378] RAX: fffffffffffffe00 RBX: 00007f65c41c76c0 RCX: 0000000000445cfe
> > [   97.811391] RDX: 0000000000000400 RSI: 00007f65c41c6e40 RDI: 0000000000000004
> > [   97.811403] RBP: 00007f65c41c7250 R08: 0000000000000000 R09: 0000000000000000
> > [   97.811415] R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffffe8
> > [   97.811428] R13: 0000000000000000 R14: 00007fff780a8c00 R15: 00007f65c41c76c0
> > [   97.811453]  </TASK>
> > [   98.402453] ==================================================================
> > [   98.403560] BUG: KASAN: use-after-free in __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> > [   98.404541] Read of size 8 at addr ffff888113ee40a8 by task khidpd_00050004/1430
> > [   98.405361]
> > [   98.405563] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
> > [   98.405588] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> > [   98.405600] Call Trace:
> > [   98.405607]  <TASK>
> > [   98.405614]  dump_stack_lvl (lib/dump_stack.c:122)
> > [   98.405641]  print_report (mm/kasan/report.c:379 mm/kasan/report.c:482)
> > [   98.405667]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.405691]  ? __virt_addr_valid (arch/x86/mm/physaddr.c:55)
> > [   98.405724]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> > [   98.405748]  kasan_report (mm/kasan/report.c:221 mm/kasan/report.c:597)
> > [   98.405778]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> > [   98.405807]  __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
> > [   98.405832]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
> > [   98.405859]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
> > [   98.405888]  ? __pfx_do_raw_spin_lock (kernel/locking/spinlock_debug.c:114)
> > [   98.405915]  ? __pfx___mutex_lock (kernel/locking/mutex.c:775)
> > [   98.405939]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.405963]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
> > [   98.405984]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> > [   98.406015]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406038]  ? lock_release (kernel/locking/lockdep.c:5536 kernel/locking/lockdep.c:5889 kernel/locking/lockdep.c:5875)
> > [   98.406061]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406085]  ? _raw_spin_unlock_irqrestore (./arch/x86/include/asm/irqflags.h:42 ./arch/x86/include/asm/irqflags.h:119 ./arch/x86/include/asm/irqflags.h:159 ./include/linux/spinlock_api_smp.h:178 kernel/locking/spinlock.c:194)
> > [   98.406107]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406130]  ? __timer_delete_sync (kernel/time/timer.c:1592)
> > [   98.406158]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
> > [   98.406186]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406210]  l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
> > [   98.406263]  hidp_session_thread (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 ./include/linux/kref.h:64 net/bluetooth/hidp/core.c:996 net/bluetooth/hidp/core.c:1305)
> > [   98.406293]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> > [   98.406323]  ? kthread (kernel/kthread.c:433)
> > [   98.406340]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> > [   98.406370]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406393]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> > [   98.406424]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> > [   98.406453]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406476]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
> > [   98.406499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406523]  ? kthread (kernel/kthread.c:433)
> > [   98.406539]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406565]  ? kthread (kernel/kthread.c:433)
> > [   98.406581]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> > [   98.406610]  kthread (kernel/kthread.c:467)
> > [   98.406627]  ? __pfx_kthread (kernel/kthread.c:412)
> > [   98.406645]  ret_from_fork (arch/x86/kernel/process.c:164)
> > [   98.406674]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
> > [   98.406704]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.406728]  ? __pfx_kthread (kernel/kthread.c:412)
> > [   98.406747]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
> > [   98.406774]  </TASK>
> > [   98.406780]
> > [   98.433693] The buggy address belongs to the physical page:
> > [   98.434405] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888113ee7c40 pfn:0x113ee4
> > [   98.435557] flags: 0x200000000000000(node=0|zone=2)
> > [   98.436198] raw: 0200000000000000 ffffea0004244308 ffff8881f6f3ebc0 0000000000000000
> > [   98.437195] raw: ffff888113ee7c40 0000000000000000 00000000ffffffff 0000000000000000
> > [   98.438115] page dumped because: kasan: bad access detected
> > [   98.438951]
> > [   98.439211] Memory state around the buggy address:
> > [   98.439871]  ffff888113ee3f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> > [   98.440714]  ffff888113ee4000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [   98.441580] >ffff888113ee4080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [   98.442458]                                   ^
> > [   98.443011]  ffff888113ee4100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [   98.443889]  ffff888113ee4180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [   98.444768] ==================================================================
> > [   98.445719] Disabling lock debugging due to kernel taint
> > [   98.448074] l2cap_conn_free: freeing conn ffff88810c22b400
> > [   98.450012] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Tainted: G    B               7.0.0-rc1-dirty #14 PREEMPT(lazy)
> > [   98.450040] Tainted: [B]=BAD_PAGE
> > [   98.450047] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> > [   98.450059] Call Trace:
> > [   98.450065]  <TASK>
> > [   98.450071]  dump_stack_lvl (lib/dump_stack.c:122)
> > [   98.450099]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
> > [   98.450125]  l2cap_conn_put (net/bluetooth/l2cap_core.c:1822)
> > [   98.450154]  session_free (net/bluetooth/hidp/core.c:990)
> > [   98.450181]  hidp_session_thread (net/bluetooth/hidp/core.c:1307)
> > [   98.450213]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> > [   98.450271]  ? kthread (kernel/kthread.c:433)
> > [   98.450293]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> > [   98.450339]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.450368]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
> > [   98.450406]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
> > [   98.450442]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.450471]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
> > [   98.450499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.450528]  ? kthread (kernel/kthread.c:433)
> > [   98.450547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.450578]  ? kthread (kernel/kthread.c:433)
> > [   98.450598]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
> > [   98.450637]  kthread (kernel/kthread.c:467)
> > [   98.450657]  ? __pfx_kthread (kernel/kthread.c:412)
> > [   98.450680]  ret_from_fork (arch/x86/kernel/process.c:164)
> > [   98.450715]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
> > [   98.450752]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
> > [   98.450782]  ? __pfx_kthread (kernel/kthread.c:412)
> > [   98.450804]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
> > [   98.450836]  </TASK>
> >
> > Fixes: b4f34d8d9d26 ("Bluetooth: hidp: add new session-management helpers")
> > Reported-by: soufiane el hachmi <kilwa10@gmail.com>
> > Tested-by: soufiane el hachmi <kilwa10@gmail.com>
> > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > ---
> >  net/bluetooth/hidp/core.c | 16 ++++++++++++++--
> >  1 file changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> > index 6724adce615b..e0e400381550 100644
> > --- a/net/bluetooth/hidp/core.c
> > +++ b/net/bluetooth/hidp/core.c
> > @@ -986,7 +986,8 @@ static void session_free(struct kref *ref)
> >       skb_queue_purge(&session->intr_transmit);
> >       fput(session->intr_sock->file);
> >       fput(session->ctrl_sock->file);
> > -     l2cap_conn_put(session->conn);
> > +     if (session->conn)
> > +             l2cap_conn_put(session->conn);
> >       kfree(session);
> >  }
> >
> > @@ -1164,6 +1165,15 @@ static void hidp_session_remove(struct l2cap_conn *conn,
> >
> >       down_write(&hidp_session_sem);
> >
> > +     /* Drop L2CAP reference immediately to indicate that
> > +      * l2cap_unregister_user() shall not be called as it is already
> > +      * considered removed.
> > +      */
> > +     if (session->conn) {
> > +             l2cap_conn_put(session->conn);
> > +             session->conn = NULL;
> > +     }
> > +
> >       hidp_session_terminate(session);
> >
> >       cancel_work_sync(&session->dev_init);
> > @@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg)
> >        * Instead, this call has the same semantics as if user-space tried to
> >        * delete the session.
> >        */
> > -     l2cap_unregister_user(session->conn, &session->user);
> > +     if (session->conn)
> > +             l2cap_unregister_user(session->conn, &session->user);
>
> Does this TOCTOU on session->conn:
>
> [Task 1]                             [Task 2]
> hci_dev_lock()
>   l2cap_disconn_cfm()
>     l2cap_conn_del()
>                                      if (session->conn)
>       hidp_session_remove()
>       l2cap_conn_free()
>                                        l2cap_unregister_user()
>                                          hdev = conn->hcon->hdev <UAF>
>
> I wonder if it is same issue as
> https://syzkaller.appspot.com/bug?extid=14b6d57fb728e27ce23c
>
> and I remember the earlier patch that tries to address the race via
> changing the locking:
>
> https://lore.kernel.org/all/20251106182016.26508-1-ssranevjti@gmail.com/

Interesting, this one might have slipped through. It seems valid and
looks like it would address the TOCTOU, let me check with the reporter
if the above fix the problem as well then we migh just drop the change
setting the l2cap_conn to NULL.

>
> AFAICS, done that way the call to l2cap_unregister_user() in
> hidp_session_thread() should be noop via the !list_empty(&user->list)
> branch, as the hidp_session_remove() already ran. session->conn would
> remain until it is put when session->ref refcount goes to zero.
>
>
> > +
> >       hidp_session_put(session);
> >
> >       module_put_and_kthread_exit(0);
>
> --
> Pauli Virtanen



-- 
Luiz Augusto von Dentz

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

* [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del
  2026-03-06  2:31 [PATCH v1] Bluetooth: HIDP: Fix possible UAF Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2026-03-06 18:49 ` Pauli Virtanen
@ 2026-04-22  1:14 ` Michael Bommarito
  2026-04-22  4:13   ` bluez.test.bot
                     ` (2 more replies)
  3 siblings, 3 replies; 14+ messages in thread
From: Michael Bommarito @ 2026-04-22  1:14 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Luiz Augusto von Dentz, linux-bluetooth, linux-kernel

commit dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF") changed
hidp_session_remove() to drop the L2CAP reference and set
session->conn = NULL once the session is considered removed, and
added an if (session->conn) guard around the l2cap_unregister_user()
call at the kthread-exit site in hidp_session_thread().

The sibling call site in hidp_connection_del() still invokes
l2cap_unregister_user(session->conn, &session->user) unconditionally.
hidp_session_find() takes the session refcount under
down_read(&hidp_session_sem) and returns; between the find() and the
call at :1421, hidp_session_remove() can run on another thread
(driven by the remote peer disconnecting or local teardown), take
down_write(&hidp_session_sem), set session->conn to NULL, and return.
The HIDPCONNDEL ioctl path then dereferences a NULL l2cap_conn inside
l2cap_unregister_user(), which acquires conn->lock without a NULL
check.  Result: kernel NULL-pointer dereference.

Apply the same if (session->conn) guard used at the twin site.  No
functional change when session->conn is non-NULL.

Discovery and verification:

- Found via static audit of every session->conn read in hidp/core.c
  after the referenced commit landed.  The other reads are safe
  (creation-time in hidp_session_dev_init, already-guarded in
  session_free / hidp_session_thread / hidp_session_remove; the other
  hidp_session_find callers do not touch session->conn at all), so
  :1421 is the only remaining unguarded site.
- Runtime A/B confirmed in UML with CONFIG_BT_HIDP=y + CONFIG_KASAN=y:
  a late_initcall stub that injects a fake hidp_session with
  conn=NULL into hidp_session_list and invokes hidp_connection_del()
  panics on the pre-fix tree at __mutex_lock from
  l2cap_unregister_user+0x2d, and returns cleanly on the post-fix
  tree with the new guard short-circuiting before the deref.

Fixes: dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF")
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Assisted-by: Claude:claude-opus-4-7
---
 net/bluetooth/hidp/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 7bcf8c5ceaee..9192efd1b156 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1417,7 +1417,7 @@ int hidp_connection_del(struct hidp_conndel_req *req)
 				       HIDP_TRANS_HID_CONTROL |
 				         HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
 				       NULL, 0);
-	else
+	else if (session->conn)
 		l2cap_unregister_user(session->conn, &session->user);
 
 	hidp_session_put(session);
-- 
2.53.0


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

* RE: Bluetooth: HIDP: guard session->conn in hidp_connection_del
  2026-04-22  1:14 ` [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del Michael Bommarito
@ 2026-04-22  4:13   ` bluez.test.bot
  2026-04-22 14:55   ` [PATCH] " Luiz Augusto von Dentz
  2026-05-02 16:43   ` [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem Michael Bommarito
  2 siblings, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-04-22  4:13 UTC (permalink / raw)
  To: linux-bluetooth, michael.bommarito

[-- Attachment #1: Type: text/plain, Size: 4405 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/project/bluetooth/list/?series=1084091

---Test result---

Test Summary:
CheckPatch                    FAIL      0.55 seconds
GitLint                       PASS      0.20 seconds
SubjectPrefix                 PASS      0.08 seconds
BuildKernel                   PASS      26.22 seconds
CheckAllWarning               PASS      28.58 seconds
CheckSparse                   PASS      27.49 seconds
BuildKernel32                 PASS      25.59 seconds
TestRunnerSetup               PASS      574.90 seconds
TestRunner_l2cap-tester       PASS      27.87 seconds
TestRunner_iso-tester         PASS      42.34 seconds
TestRunner_bnep-tester        PASS      6.48 seconds
TestRunner_mgmt-tester        FAIL      114.28 seconds
TestRunner_rfcomm-tester      PASS      9.83 seconds
TestRunner_sco-tester         PASS      14.50 seconds
TestRunner_ioctl-tester       PASS      10.22 seconds
TestRunner_mesh-tester        FAIL      12.18 seconds
TestRunner_smp-tester         PASS      8.81 seconds
TestRunner_userchan-tester    PASS      6.92 seconds
TestRunner_6lowpan-tester     FAIL      8.68 seconds
IncrementalBuild              PASS      25.52 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
Bluetooth: HIDP: guard session->conn in hidp_connection_del
WARNING: Non-standard signature: Assisted-by:
#140: 
Assisted-by: Claude:claude-opus-4-7

ERROR: Unrecognized email address: 'Claude:claude-opus-4-7'
#140: 
Assisted-by: Claude:claude-opus-4-7

total: 1 errors, 1 warnings, 0 checks, 8 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/patch/14533271.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.112 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.627 seconds
Mesh - Send cancel - 2                               Timed out    1.994 seconds
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc7-gcdeca5510265 #1 Not tainted
------------------------------------------------------
kworker/0:1/11 is trying to acquire lock:
ffff888002735940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x75/0x180

but task is already holding lock:
ffffffff9d84f9e0 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #4 (rtnl_mutex){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       lowpan_register_netdev+0x11/0x30
       chan_ready_cb+0x836/0xd00
       l2cap_recv_frame+0x61bb/0x88e0
       l2cap_recv_acldata+0x790/0xdf0
       hci_rx_work+0x500/0xd00
       process_scheduled_works+0xba7/0x1a90
       worker_thread+0x514/0xbb0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

-> #3 (&chan->lock#3/1){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       l2cap_chan_connect+0x74e/0x1980
       lowpan_control_write+0x523/0x660
       full_proxy_write+0x10b/0x190
       vfs_write+0x1c0/0xf60
       ksys_write+0xf1/0x1d0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #2 (&conn->lock){+.+.}-{4:4}:
...
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0


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

---
Regards,
Linux Bluetooth


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

* Re: [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del
  2026-04-22  1:14 ` [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del Michael Bommarito
  2026-04-22  4:13   ` bluez.test.bot
@ 2026-04-22 14:55   ` Luiz Augusto von Dentz
  2026-04-22 15:09     ` Michael Bommarito
  2026-05-02 16:43   ` [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem Michael Bommarito
  2 siblings, 1 reply; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2026-04-22 14:55 UTC (permalink / raw)
  To: Michael Bommarito; +Cc: Marcel Holtmann, linux-bluetooth, linux-kernel

Hi Michael,

On Tue, Apr 21, 2026 at 9:14 PM Michael Bommarito
<michael.bommarito@gmail.com> wrote:
>
> commit dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF") changed
> hidp_session_remove() to drop the L2CAP reference and set
> session->conn = NULL once the session is considered removed, and
> added an if (session->conn) guard around the l2cap_unregister_user()
> call at the kthread-exit site in hidp_session_thread().
>
> The sibling call site in hidp_connection_del() still invokes
> l2cap_unregister_user(session->conn, &session->user) unconditionally.
> hidp_session_find() takes the session refcount under
> down_read(&hidp_session_sem) and returns; between the find() and the
> call at :1421, hidp_session_remove() can run on another thread
> (driven by the remote peer disconnecting or local teardown), take
> down_write(&hidp_session_sem), set session->conn to NULL, and return.
> The HIDPCONNDEL ioctl path then dereferences a NULL l2cap_conn inside
> l2cap_unregister_user(), which acquires conn->lock without a NULL
> check.  Result: kernel NULL-pointer dereference.
>
> Apply the same if (session->conn) guard used at the twin site.  No
> functional change when session->conn is non-NULL.
>
> Discovery and verification:
>
> - Found via static audit of every session->conn read in hidp/core.c
>   after the referenced commit landed.  The other reads are safe
>   (creation-time in hidp_session_dev_init, already-guarded in
>   session_free / hidp_session_thread / hidp_session_remove; the other
>   hidp_session_find callers do not touch session->conn at all), so
>   :1421 is the only remaining unguarded site.
> - Runtime A/B confirmed in UML with CONFIG_BT_HIDP=y + CONFIG_KASAN=y:
>   a late_initcall stub that injects a fake hidp_session with
>   conn=NULL into hidp_session_list and invokes hidp_connection_del()
>   panics on the pre-fix tree at __mutex_lock from
>   l2cap_unregister_user+0x2d, and returns cleanly on the post-fix
>   tree with the new guard short-circuiting before the deref.
>
> Fixes: dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF")
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> Assisted-by: Claude:claude-opus-4-7
> ---
>  net/bluetooth/hidp/core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index 7bcf8c5ceaee..9192efd1b156 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
> @@ -1417,7 +1417,7 @@ int hidp_connection_del(struct hidp_conndel_req *req)
>                                        HIDP_TRANS_HID_CONTROL |
>                                          HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
>                                        NULL, 0);
> -       else
> +       else if (session->conn)
>                 l2cap_unregister_user(session->conn, &session->user);
>
>         hidp_session_put(session);
> --
> 2.53.0

We might need a lock in order to access the session->conn:

https://sashiko.dev/#/patchset/20260422011437.176643-1-michael.bommarito%40gmail.com


-- 
Luiz Augusto von Dentz

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

* Re: [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del
  2026-04-22 14:55   ` [PATCH] " Luiz Augusto von Dentz
@ 2026-04-22 15:09     ` Michael Bommarito
  2026-04-22 15:48       ` Pauli Virtanen
  2026-04-22 15:49       ` Luiz Augusto von Dentz
  0 siblings, 2 replies; 14+ messages in thread
From: Michael Bommarito @ 2026-04-22 15:09 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Marcel Holtmann, linux-bluetooth, linux-kernel

On Wed, Apr 22, 2026 at 10:55 AM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> We might need a lock in order to access the session->conn:

This one is a little easier than the other txwin_size issue in terms
of blast radius.

What pattern would you prefer here?

Option 1, smaller but ordering questions: hold the semaphore across
check and use like this:

down_read(&hidp_session_sem);
if (session->conn)
    l2cap_unregister_user(session->conn, &session->user);
up_read(&hidp_session_sem)


Option 2, more correct but more cycles: snapshot the conn and use outside

down_read(&hidp_session_sem);
conn = session->conn;
if (conn)
    l2cap_conn_get(conn);
up_read(&hidp_session_sem);
if (conn) {
    l2cap_unregister_user(conn, &session->user);
    l2cap_conn_put(conn);
}

Thanks,
Mike Bommarito

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

* Re: [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del
  2026-04-22 15:09     ` Michael Bommarito
@ 2026-04-22 15:48       ` Pauli Virtanen
  2026-04-22 15:49       ` Luiz Augusto von Dentz
  1 sibling, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2026-04-22 15:48 UTC (permalink / raw)
  To: Michael Bommarito, Luiz Augusto von Dentz
  Cc: Marcel Holtmann, linux-bluetooth, linux-kernel

Hi,

ke, 2026-04-22 kello 11:09 -0400, Michael Bommarito kirjoitti:
> On Wed, Apr 22, 2026 at 10:55 AM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> > We might need a lock in order to access the session->conn:
> 
> This one is a little easier than the other txwin_size issue in terms
> of blast radius.
> 
> What pattern would you prefer here?
> 
> Option 1, smaller but ordering questions: hold the semaphore across
> check and use like this:
> 
> down_read(&hidp_session_sem);
> if (session->conn)
>     l2cap_unregister_user(session->conn, &session->user);
> up_read(&hidp_session_sem)
> 
> 
> Option 2, more correct but more cycles: snapshot the conn and use outside
> 
> down_read(&hidp_session_sem);
> conn = session->conn;
> if (conn)
>     l2cap_conn_get(conn);
> up_read(&hidp_session_sem);
> if (conn) {
>     l2cap_unregister_user(conn, &session->user);
>     l2cap_conn_put(conn);
> }

I'm not sure now (would need to rethink it through), but one probably
should check if dbf666e4fc9b is needed or whether 752a6c9596d alone
would be enough to address the original issue.

-- 
Pauli Virtanen

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

* Re: [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del
  2026-04-22 15:09     ` Michael Bommarito
  2026-04-22 15:48       ` Pauli Virtanen
@ 2026-04-22 15:49       ` Luiz Augusto von Dentz
  1 sibling, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2026-04-22 15:49 UTC (permalink / raw)
  To: Michael Bommarito; +Cc: Marcel Holtmann, linux-bluetooth, linux-kernel

Hi Michael,

On Wed, Apr 22, 2026 at 11:09 AM Michael Bommarito
<michael.bommarito@gmail.com> wrote:
>
> On Wed, Apr 22, 2026 at 10:55 AM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> > We might need a lock in order to access the session->conn:
>
> This one is a little easier than the other txwin_size issue in terms
> of blast radius.
>
> What pattern would you prefer here?
>
> Option 1, smaller but ordering questions: hold the semaphore across
> check and use like this:
>
> down_read(&hidp_session_sem);
> if (session->conn)
>     l2cap_unregister_user(session->conn, &session->user);
> up_read(&hidp_session_sem)
>
>
> Option 2, more correct but more cycles: snapshot the conn and use outside
>
> down_read(&hidp_session_sem);
> conn = session->conn;
> if (conn)
>     l2cap_conn_get(conn);
> up_read(&hidp_session_sem);
> if (conn) {
>     l2cap_unregister_user(conn, &session->user);
>     l2cap_conn_put(conn);
> }

Neither seems completely correct, in my opinion. I guess we want to
use option 2 but set the session->conn to NULL since it will call
l2cap_unregister_user.

> Thanks,
> Mike Bommarito



-- 
Luiz Augusto von Dentz

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

* [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem
  2026-04-22  1:14 ` [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del Michael Bommarito
  2026-04-22  4:13   ` bluez.test.bot
  2026-04-22 14:55   ` [PATCH] " Luiz Augusto von Dentz
@ 2026-05-02 16:43   ` Michael Bommarito
  2026-05-02 17:44     ` [v2] " bluez.test.bot
  2026-05-04 17:10     ` [PATCH v2] " patchwork-bot+bluetooth
  2 siblings, 2 replies; 14+ messages in thread
From: Michael Bommarito @ 2026-05-02 16:43 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Luiz Augusto von Dentz, Pauli Virtanen, linux-bluetooth,
	linux-kernel

Commit dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF") made
hidp_session_remove() drop the L2CAP reference and set
session->conn = NULL once the session is considered removed, and
added a bare if (session->conn) guard around the kthread-exit
l2cap_unregister_user() call in hidp_session_thread().  The sibling
ioctl site in hidp_connection_del() still reads session->conn
unlocked and unguarded, and the kthread-exit guard itself is a
lockless double-read.

hidp_session_find() drops hidp_session_sem before returning, so
hidp_session_remove() can null session->conn between the lookup and
the call in hidp_connection_del().  Worse, since commit 752a6c9596dd
("Bluetooth: L2CAP: Fix use-after-free in l2cap_unregister_user")
takes mutex_lock(&conn->lock) inside l2cap_unregister_user(), a
stale non-NULL snapshot also UAFs on conn->lock.  v1 only added an
if (session->conn) guard at the ioctl site, which doesn't address
either race; Luiz suggested snapshotting session->conn under the
sem and clearing it before the call.

Taking hidp_session_sem across l2cap_unregister_user() would be
wrong: l2cap_conn_del() already establishes the lock order

  conn->lock -> hidp_session_sem

via l2cap_unregister_all_users() -> user->remove ==
hidp_session_remove(), so taking hidp_session_sem before conn->lock
would AB/BA deadlock.

Factor a helper hidp_session_unregister_conn() that under
down_write(&hidp_session_sem) snapshots session->conn and clears
the member, then outside the sem calls l2cap_unregister_user() and
l2cap_conn_put() on the snapshot.  Call it from both
hidp_connection_del() and hidp_session_thread()'s exit path.  At
most one consumer wins the write-sem; later callers observe
session->conn == NULL and skip the unregister and put, so the
reference hidp_session_new() took via l2cap_conn_get() is consumed
exactly once.  session_free() already tolerates a NULL session->conn.

Fixes: dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF")
Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Link: https://lore.kernel.org/all/20260422011437.176643-1-michael.bommarito@gmail.com/
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Assisted-by: Claude:claude-opus-4-7
---
Tested under UML with CONFIG_BT_HIDP=y, CONFIG_KASAN=y, and
CONFIG_PROVE_LOCKING=y.  W=1 build of net/bluetooth/hidp/ clean;
boot clean.  A KCFLAGS-gated test stub (not part of this patch)
drove hidp_session_unregister_conn() twice in a row against a fake
session with conn = NULL: the helper short-circuited both times and
lockdep stayed silent.

 net/bluetooth/hidp/core.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 7bcf8c5ceaee..976f91eeb745 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1035,6 +1035,28 @@ static struct hidp_session *hidp_session_find(const bdaddr_t *bdaddr)
 	return session;
 }
 
+/*
+ * Consume session->conn: clear the member under hidp_session_sem, then
+ * l2cap_unregister_user() and l2cap_conn_put() the snapshot outside the
+ * sem.  At most one caller wins; later callers see NULL and skip.  The
+ * reference is the one hidp_session_new() took via l2cap_conn_get().
+ */
+static void hidp_session_unregister_conn(struct hidp_session *session)
+{
+	struct l2cap_conn *conn;
+
+	down_write(&hidp_session_sem);
+	conn = session->conn;
+	if (conn)
+		session->conn = NULL;
+	up_write(&hidp_session_sem);
+
+	if (conn) {
+		l2cap_unregister_user(conn, &session->user);
+		l2cap_conn_put(conn);
+	}
+}
+
 /*
  * Start session synchronously
  * This starts a session thread and waits until initialization
@@ -1311,8 +1333,7 @@ static int hidp_session_thread(void *arg)
 	 * Instead, this call has the same semantics as if user-space tried to
 	 * delete the session.
 	 */
-	if (session->conn)
-		l2cap_unregister_user(session->conn, &session->user);
+	hidp_session_unregister_conn(session);
 
 	hidp_session_put(session);
 
@@ -1418,7 +1439,7 @@ int hidp_connection_del(struct hidp_conndel_req *req)
 				         HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
 				       NULL, 0);
 	else
-		l2cap_unregister_user(session->conn, &session->user);
+		hidp_session_unregister_conn(session);
 
 	hidp_session_put(session);
 
-- 
2.53.0


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

* RE: [v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem
  2026-05-02 16:43   ` [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem Michael Bommarito
@ 2026-05-02 17:44     ` bluez.test.bot
  2026-05-04 17:10     ` [PATCH v2] " patchwork-bot+bluetooth
  1 sibling, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-05-02 17:44 UTC (permalink / raw)
  To: linux-bluetooth, michael.bommarito

[-- Attachment #1: Type: text/plain, Size: 3741 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/project/bluetooth/list/?series=1088829

---Test result---

Test Summary:
CheckPatch                    PASS      0.64 seconds
GitLint                       FAIL      0.24 seconds
SubjectPrefix                 PASS      0.09 seconds
BuildKernel                   PASS      28.18 seconds
CheckAllWarning               PASS      30.05 seconds
CheckSparse                   PASS      28.76 seconds
BuildKernel32                 PASS      26.27 seconds
TestRunnerSetup               PASS      579.48 seconds
TestRunner_l2cap-tester       FAIL      6.77 seconds
TestRunner_iso-tester         PASS      295.82 seconds
TestRunner_bnep-tester        FAIL      6.75 seconds
TestRunner_mgmt-tester        FAIL      8.99 seconds
TestRunner_rfcomm-tester      PASS      29.07 seconds
TestRunner_sco-tester         PASS      68.13 seconds
TestRunner_ioctl-tester       FAIL      37.43 seconds
TestRunner_mesh-tester        PASS      27.11 seconds
TestRunner_smp-tester         PASS      6.58 seconds
TestRunner_userchan-tester    FAIL      6.68 seconds
TestRunner_6lowpan-tester     PASS      22.83 seconds
IncrementalBuild              PASS      25.14 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
42: B1 Line exceeds max length (86>80): "Link: https://lore.kernel.org/all/20260422011437.176643-1-michael.bommarito@gmail.com/"
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
No test result found
##############################
Test: TestRunner_bnep-tester - FAIL
Desc: Run bnep-tester with test-runner
Output:
No test result found
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
No test result found
##############################
Test: TestRunner_ioctl-tester - FAIL
Desc: Run ioctl-tester with test-runner
Output:
Total: 28, Passed: 0 (0.0%), Failed: 11, Not Run: 17

Failed Test Cases
Device List                                          Timed out  -30.849 seconds
Device Info                                          Timed out   -6.201 seconds
Reset Stat                                           Timed out   -6.204 seconds
Set Link Mode - ACCEPT                               Timed out   -6.207 seconds
Set Pkt Type - DM                                    Timed out  -14.394 seconds
Set Pkt Type - DH                                    Timed out  -14.397 seconds
Set Pkt Type - HV                                    Timed out  -14.400 seconds
Set Pkt Type - 2-DH                                  Timed out  -14.403 seconds
Set Pkt Type - 2-DH                                  Timed out  -14.406 seconds
Set Pkt Type - ALL                                   Timed out  -14.409 seconds
Set ACL MTU - 1                                      Timed out  -14.411 seconds
##############################
Test: TestRunner_userchan-tester - FAIL
Desc: Run userchan-tester with test-runner
Output:
No test result found


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

---
Regards,
Linux Bluetooth


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

* Re: [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem
  2026-05-02 16:43   ` [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem Michael Bommarito
  2026-05-02 17:44     ` [v2] " bluez.test.bot
@ 2026-05-04 17:10     ` patchwork-bot+bluetooth
  1 sibling, 0 replies; 14+ messages in thread
From: patchwork-bot+bluetooth @ 2026-05-04 17:10 UTC (permalink / raw)
  To: Michael Bommarito; +Cc: marcel, luiz.dentz, pav, linux-bluetooth, linux-kernel

Hello:

This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Sat,  2 May 2026 12:43:03 -0400 you wrote:
> Commit dbf666e4fc9b ("Bluetooth: HIDP: Fix possible UAF") made
> hidp_session_remove() drop the L2CAP reference and set
> session->conn = NULL once the session is considered removed, and
> added a bare if (session->conn) guard around the kthread-exit
> l2cap_unregister_user() call in hidp_session_thread().  The sibling
> ioctl site in hidp_connection_del() still reads session->conn
> unlocked and unguarded, and the kthread-exit guard itself is a
> lockless double-read.
> 
> [...]

Here is the summary with links:
  - [v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem
    https://git.kernel.org/bluetooth/bluetooth-next/c/fd572908d364

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2026-05-04 17:10 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-06  2:31 [PATCH v1] Bluetooth: HIDP: Fix possible UAF Luiz Augusto von Dentz
2026-03-06  4:27 ` [v1] " bluez.test.bot
2026-03-06 18:40 ` [PATCH v1] " patchwork-bot+bluetooth
2026-03-06 18:49 ` Pauli Virtanen
2026-03-06 19:23   ` Luiz Augusto von Dentz
2026-04-22  1:14 ` [PATCH] Bluetooth: HIDP: guard session->conn in hidp_connection_del Michael Bommarito
2026-04-22  4:13   ` bluez.test.bot
2026-04-22 14:55   ` [PATCH] " Luiz Augusto von Dentz
2026-04-22 15:09     ` Michael Bommarito
2026-04-22 15:48       ` Pauli Virtanen
2026-04-22 15:49       ` Luiz Augusto von Dentz
2026-05-02 16:43   ` [PATCH v2] Bluetooth: HIDP: serialise l2cap_unregister_user via hidp_session_sem Michael Bommarito
2026-05-02 17:44     ` [v2] " bluez.test.bot
2026-05-04 17:10     ` [PATCH v2] " patchwork-bot+bluetooth

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