* [PATCH v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref
@ 2026-06-05 14:23 Marco Elver
2026-06-05 15:47 ` Luiz Augusto von Dentz
2026-06-05 20:33 ` [v2] " bluez.test.bot
0 siblings, 2 replies; 3+ messages in thread
From: Marco Elver @ 2026-06-05 14:23 UTC (permalink / raw)
To: elver
Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-bluetooth,
linux-kernel, kasan-dev, stable, Siwei Zhang,
Luiz Augusto von Dentz
l2cap_chan_timeout() runs asynchronously and accesses chan->conn. If
the connection is torn down while the timer is running or pending,
chan->conn can be freed, leading to a use-after-free when the timer
worker attempts to lock conn->lock:
| BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
| BUG: KASAN: slab-use-after-free in atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline]
| BUG: KASAN: slab-use-after-free in __mutex_trylock_fast kernel/locking/mutex.c:161 [inline]
| BUG: KASAN: slab-use-after-free in mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318
| Write of size 8 at addr ffff8881298d9550 by task kworker/2:1/83
|
| CPU: 2 UID: 0 PID: 83 Comm: kworker/2:1 Not tainted 7.1.0-rc6-next-20260601-dirty #6 PREEMPT(full)
| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
| Workqueue: events l2cap_chan_timeout
| Call Trace:
| <TASK>
| instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
| atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline]
| __mutex_trylock_fast kernel/locking/mutex.c:161 [inline]
| mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318
| l2cap_chan_timeout+0x5d/0x1b0 net/bluetooth/l2cap_core.c:422
| process_one_work kernel/workqueue.c:3326 [inline]
| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
| kthread+0x346/0x430 kernel/kthread.c:436
| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
| </TASK>
|
| Allocated by task 320:
| l2cap_conn_add+0xa7/0x820 net/bluetooth/l2cap_core.c:7075
| l2cap_connect_cfm+0xdb/0xd70 net/bluetooth/l2cap_core.c:7452
| hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline]
| hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760
| hci_event_func net/bluetooth/hci_event.c:7796 [inline]
| hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847
| hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040
| process_one_work kernel/workqueue.c:3326 [inline]
| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
| kthread+0x346/0x430 kernel/kthread.c:436
| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
|
| Freed by task 322:
| hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline]
| hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736
| hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405
| hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
| hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679
| vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690
| __fput+0x369/0x890 fs/file_table.c:510
| task_work_run+0x160/0x1d0 kernel/task_work.c:233
| get_signal+0xf5b/0x1120 kernel/signal.c:2810
| arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337
| __exit_to_user_mode_loop kernel/entry/common.c:64 [inline]
| exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98
| __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [i
e]
| syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:
[inline]
| syscall_exit_to_user_mode include/linux/entry-common.h:318 [inline]
| do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100
| entry_SYSCALL_64_after_hwframe+0x77/0x7f
|
| Last potentially related work creation:
| hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline]
| hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760
| hci_event_func net/bluetooth/hci_event.c:7796 [inline]
| hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847
| hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040
| process_one_work kernel/workqueue.c:3326 [inline]
| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
| kthread+0x346/0x430 kernel/kthread.c:436
| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
| hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736
| hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405
| hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
| hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679
| vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690
| __fput+0x369/0x890 fs/file_table.c:510
| task_work_run+0x160/0x1d0 kernel/task_work.c:233
| get_signal+0xf5b/0x1120 kernel/signal.c:2810
| arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337
| __exit_to_user_mode_loop kernel/entry/common.c:64 [inline]
| exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98
| __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [i
e]
| syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:
[inline]
| syscall_exit_to_user_mode include/linux/entry-common.h:318 [inline]
| do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100
| entry_SYSCALL_64_after_hwframe+0x77/0x7f
|
| Last potentially related work creation:
| hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline]
| hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760
| hci_event_func net/bluetooth/hci_event.c:7796 [inline]
| hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847
| hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040
| process_one_work kernel/workqueue.c:3326 [inline]
| process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
| worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
| kthread+0x346/0x430 kernel/kthread.c:436
| ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
| ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
|
| The buggy address belongs to the object at ffff8881298d9400
| which belongs to the cache kmalloc-512 of size 512
| The buggy address is located 336 bytes inside of
| freed 512-byte region [ffff8881298d9400, ffff8881298d9600)
Fix it by having struct l2cap_chan hold a reference to l2cap_conn
(conn_ref) when the channel is added to the connection, and releasing it
in the channel destructor. This ensures the connection remains alive as
long as the channel exists. While conn and conn_ref point to the same
object, conn being NULL indicates it being torn down, while conn_ref's
only purpose is to associate its lifetime with the parent channel.
Fixes: 75780ca4c6a8 ("Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()")
Cc: <stable@vger.kernel.org>
Cc: Siwei Zhang <oss@fourdim.xyz>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Assisted-by: Gemini:gemini-3.1-pro-preview
Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz
Signed-off-by: Marco Elver <elver@google.com>
---
v2:
* Fix UAF in channel timeout by holding conn ref.
v1: https://lore.kernel.org/r/20260603123111.2334409-1-elver@google.com
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/l2cap_core.c | 15 +++++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index e0a1f2293679..de3673149deb 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -514,6 +514,7 @@ struct l2cap_seq_list {
struct l2cap_chan {
struct l2cap_conn *conn;
+ struct l2cap_conn *conn_ref;
struct kref kref;
atomic_t nesting;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c4ccfbda9d78..7f331a31b723 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -422,6 +422,9 @@ static void l2cap_chan_timeout(struct work_struct *work)
*/
l2cap_chan_lock(chan);
+ if (!chan->conn)
+ goto unlock;
+
if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
reason = ECONNREFUSED;
else if (chan->state == BT_CONNECT &&
@@ -434,10 +437,10 @@ static void l2cap_chan_timeout(struct work_struct *work)
chan->ops->close(chan);
+unlock:
l2cap_chan_unlock(chan);
- l2cap_chan_put(chan);
-
mutex_unlock(&conn->lock);
+ l2cap_chan_put(chan);
}
struct l2cap_chan *l2cap_chan_create(void)
@@ -490,6 +493,9 @@ static void l2cap_chan_destroy(struct kref *kref)
list_del(&chan->global_l);
write_unlock(&chan_list_lock);
+ if (chan->conn_ref)
+ l2cap_conn_put(chan->conn_ref);
+
kfree(chan);
}
@@ -594,6 +600,7 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
chan->conn = conn;
+ chan->conn_ref = l2cap_conn_get(conn);
switch (chan->chan_type) {
case L2CAP_CHAN_CONN_ORIENTED:
@@ -3160,12 +3167,16 @@ static void l2cap_ack_timeout(struct work_struct *work)
l2cap_chan_lock(chan);
+ if (!chan->conn)
+ goto unlock;
+
frames_to_ack = __seq_offset(chan, chan->buffer_seq,
chan->last_acked_seq);
if (frames_to_ack)
l2cap_send_rr_or_rnr(chan, 0);
+unlock:
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
}
--
2.54.0.1032.g2f8565e1d1-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref
2026-06-05 14:23 [PATCH v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref Marco Elver
@ 2026-06-05 15:47 ` Luiz Augusto von Dentz
2026-06-05 20:33 ` [v2] " bluez.test.bot
1 sibling, 0 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2026-06-05 15:47 UTC (permalink / raw)
To: Marco Elver
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, kasan-dev, stable,
Siwei Zhang, Luiz Augusto von Dentz
Hi Marco,
On Fri, Jun 5, 2026 at 10:23 AM Marco Elver <elver@google.com> wrote:
>
> l2cap_chan_timeout() runs asynchronously and accesses chan->conn. If
> the connection is torn down while the timer is running or pending,
> chan->conn can be freed, leading to a use-after-free when the timer
> worker attempts to lock conn->lock:
>
> | BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
> | BUG: KASAN: slab-use-after-free in atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline]
> | BUG: KASAN: slab-use-after-free in __mutex_trylock_fast kernel/locking/mutex.c:161 [inline]
> | BUG: KASAN: slab-use-after-free in mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318
> | Write of size 8 at addr ffff8881298d9550 by task kworker/2:1/83
> |
> | CPU: 2 UID: 0 PID: 83 Comm: kworker/2:1 Not tainted 7.1.0-rc6-next-20260601-dirty #6 PREEMPT(full)
> | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> | Workqueue: events l2cap_chan_timeout
> | Call Trace:
> | <TASK>
> | instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
> | atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline]
> | __mutex_trylock_fast kernel/locking/mutex.c:161 [inline]
> | mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318
> | l2cap_chan_timeout+0x5d/0x1b0 net/bluetooth/l2cap_core.c:422
> | process_one_work kernel/workqueue.c:3326 [inline]
> | process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
> | worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
> | kthread+0x346/0x430 kernel/kthread.c:436
> | ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
> | ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> | </TASK>
> |
> | Allocated by task 320:
> | l2cap_conn_add+0xa7/0x820 net/bluetooth/l2cap_core.c:7075
> | l2cap_connect_cfm+0xdb/0xd70 net/bluetooth/l2cap_core.c:7452
> | hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline]
> | hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760
> | hci_event_func net/bluetooth/hci_event.c:7796 [inline]
> | hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847
> | hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040
> | process_one_work kernel/workqueue.c:3326 [inline]
> | process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
> | worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
> | kthread+0x346/0x430 kernel/kthread.c:436
> | ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
> | ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> |
> | Freed by task 322:
> | hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline]
> | hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736
> | hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405
> | hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
> | hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679
> | vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690
> | __fput+0x369/0x890 fs/file_table.c:510
> | task_work_run+0x160/0x1d0 kernel/task_work.c:233
> | get_signal+0xf5b/0x1120 kernel/signal.c:2810
> | arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337
> | __exit_to_user_mode_loop kernel/entry/common.c:64 [inline]
> | exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98
> | __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [i
> e]
> | syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:
> [inline]
> | syscall_exit_to_user_mode include/linux/entry-common.h:318 [inline]
> | do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100
> | entry_SYSCALL_64_after_hwframe+0x77/0x7f
> |
> | Last potentially related work creation:
> | hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline]
> | hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760
> | hci_event_func net/bluetooth/hci_event.c:7796 [inline]
> | hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847
> | hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040
> | process_one_work kernel/workqueue.c:3326 [inline]
> | process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
> | worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
> | kthread+0x346/0x430 kernel/kthread.c:436
> | ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
> | hci_conn_hash_flush+0x101/0x1f0 net/bluetooth/hci_conn.c:2736
> | hci_dev_close_sync+0x889/0xde0 net/bluetooth/hci_sync.c:5405
> | hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
> | hci_unregister_dev+0x1f7/0x370 net/bluetooth/hci_core.c:2679
> | vhci_release+0x12a/0x180 drivers/bluetooth/hci_vhci.c:690
> | __fput+0x369/0x890 fs/file_table.c:510
> | task_work_run+0x160/0x1d0 kernel/task_work.c:233
> | get_signal+0xf5b/0x1120 kernel/signal.c:2810
> | arch_do_signal_or_restart+0x4d/0x600 arch/x86/kernel/signal.c:337
> | __exit_to_user_mode_loop kernel/entry/common.c:64 [inline]
> | exit_to_user_mode_loop+0x85/0x510 kernel/entry/common.c:98
> | __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [i
> e]
> | syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:
> [inline]
> | syscall_exit_to_user_mode include/linux/entry-common.h:318 [inline]
> | do_syscall_64+0x263/0x3d0 arch/x86/entry/syscall_64.c:100
> | entry_SYSCALL_64_after_hwframe+0x77/0x7f
> |
> | Last potentially related work creation:
> | hci_connect_cfm include/net/bluetooth/hci_core.h:2139 [inline]
> | hci_remote_features_evt+0x52f/0x9f0 net/bluetooth/hci_event.c:3760
> | hci_event_func net/bluetooth/hci_event.c:7796 [inline]
> | hci_event_packet+0x561/0xa70 net/bluetooth/hci_event.c:7847
> | hci_rx_work+0x370/0x890 net/bluetooth/hci_core.c:4040
> | process_one_work kernel/workqueue.c:3326 [inline]
> | process_scheduled_works+0x7c8/0xfb0 kernel/workqueue.c:3409
> | worker_thread+0x8a9/0xcf0 kernel/workqueue.c:3490
> | kthread+0x346/0x430 kernel/kthread.c:436
> | ret_from_fork+0x1a3/0x470 arch/x86/kernel/process.c:158
> | ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> |
> | The buggy address belongs to the object at ffff8881298d9400
> | which belongs to the cache kmalloc-512 of size 512
> | The buggy address is located 336 bytes inside of
> | freed 512-byte region [ffff8881298d9400, ffff8881298d9600)
>
> Fix it by having struct l2cap_chan hold a reference to l2cap_conn
> (conn_ref) when the channel is added to the connection, and releasing it
> in the channel destructor. This ensures the connection remains alive as
> long as the channel exists. While conn and conn_ref point to the same
> object, conn being NULL indicates it being torn down, while conn_ref's
> only purpose is to associate its lifetime with the parent channel.
>
> Fixes: 75780ca4c6a8 ("Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()")
> Cc: <stable@vger.kernel.org>
> Cc: Siwei Zhang <oss@fourdim.xyz>
> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> Assisted-by: Gemini:gemini-3.1-pro-preview
> Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> v2:
> * Fix UAF in channel timeout by holding conn ref.
>
> v1: https://lore.kernel.org/r/20260603123111.2334409-1-elver@google.com
> ---
> include/net/bluetooth/l2cap.h | 1 +
> net/bluetooth/l2cap_core.c | 15 +++++++++++++--
> 2 files changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index e0a1f2293679..de3673149deb 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -514,6 +514,7 @@ struct l2cap_seq_list {
>
> struct l2cap_chan {
> struct l2cap_conn *conn;
> + struct l2cap_conn *conn_ref;
> struct kref kref;
> atomic_t nesting;
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index c4ccfbda9d78..7f331a31b723 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -422,6 +422,9 @@ static void l2cap_chan_timeout(struct work_struct *work)
> */
> l2cap_chan_lock(chan);
>
> + if (!chan->conn)
> + goto unlock;
> +
> if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
> reason = ECONNREFUSED;
> else if (chan->state == BT_CONNECT &&
> @@ -434,10 +437,10 @@ static void l2cap_chan_timeout(struct work_struct *work)
>
> chan->ops->close(chan);
>
> +unlock:
> l2cap_chan_unlock(chan);
> - l2cap_chan_put(chan);
> -
> mutex_unlock(&conn->lock);
> + l2cap_chan_put(chan);
> }
>
> struct l2cap_chan *l2cap_chan_create(void)
> @@ -490,6 +493,9 @@ static void l2cap_chan_destroy(struct kref *kref)
> list_del(&chan->global_l);
> write_unlock(&chan_list_lock);
>
> + if (chan->conn_ref)
> + l2cap_conn_put(chan->conn_ref);
> +
> kfree(chan);
> }
>
> @@ -594,6 +600,7 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
> conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
>
> chan->conn = conn;
> + chan->conn_ref = l2cap_conn_get(conn);
>
> switch (chan->chan_type) {
> case L2CAP_CHAN_CONN_ORIENTED:
> @@ -3160,12 +3167,16 @@ static void l2cap_ack_timeout(struct work_struct *work)
>
> l2cap_chan_lock(chan);
>
> + if (!chan->conn)
> + goto unlock;
> +
> frames_to_ack = __seq_offset(chan, chan->buffer_seq,
> chan->last_acked_seq);
>
> if (frames_to_ack)
> l2cap_send_rr_or_rnr(chan, 0);
>
> +unlock:
> l2cap_chan_unlock(chan);
> l2cap_chan_put(chan);
> }
> --
> 2.54.0.1032.g2f8565e1d1-goog
While I consider this a much cleaner approach than any the previous,
perhaps we could go one step further and stop using chan->conn as an
indiciation that l2cap_chan_del has run/detach l2cap_chan and instead
perhaps use a flag e.g. FLAG_DEL, that way we can make chan->conn be
used for reference tracking alone and don't need to introduce yet
another field for it.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref
2026-06-05 14:23 [PATCH v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref Marco Elver
2026-06-05 15:47 ` Luiz Augusto von Dentz
@ 2026-06-05 20:33 ` bluez.test.bot
1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-06-05 20:33 UTC (permalink / raw)
To: linux-bluetooth, elver
[-- Attachment #1: Type: text/plain, Size: 3450 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=1106678
---Test result---
Test Summary:
CheckPatch FAIL 0.98 seconds
VerifyFixes PASS 0.14 seconds
VerifySignedoff PASS 0.14 seconds
GitLint FAIL 0.35 seconds
SubjectPrefix PASS 0.13 seconds
BuildKernel PASS 25.50 seconds
CheckAllWarning PASS 28.24 seconds
CheckSparse PASS 26.60 seconds
BuildKernel32 PASS 24.91 seconds
TestRunnerSetup PASS 524.91 seconds
TestRunner_l2cap-tester PASS 58.70 seconds
IncrementalBuild PASS 23.81 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#98:
| BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
ERROR: Unrecognized email address: 'https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz'
#218:
Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz
WARNING: Reported-by: should be immediately followed by Closes: with a URL to the report
#218:
Reported-by: https://sashiko.dev/#/patchset/20260521021249.3258069-1-oss%40fourdim.xyz
Signed-off-by: Marco Elver <elver@google.com>
total: 1 errors, 2 warnings, 0 checks, 60 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/14613573.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: GitLint - FAIL
Desc: Run gitlint
Output:
[v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref
8: B1 Line exceeds max length (107>80): "| BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline]"
9: B1 Line exceeds max length (125>80): "| BUG: KASAN: slab-use-after-free in atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline]"
10: B1 Line exceeds max length (93>80): "| BUG: KASAN: slab-use-after-free in __mutex_trylock_fast kernel/locking/mutex.c:161 [inline]"
11: B1 Line exceeds max length (84>80): "| BUG: KASAN: slab-use-after-free in mutex_lock+0x4f/0xa0 kernel/locking/mutex.c:318"
14: B1 Line exceeds max length (100>80): "| CPU: 2 UID: 0 PID: 83 Comm: kworker/2:1 Not tainted 7.1.0-rc6-next-20260601-dirty #6 PREEMPT(full)"
15: B1 Line exceeds max length (95>80): "| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014"
20: B1 Line exceeds max length (91>80): "| atomic_long_try_cmpxchg_acquire include/linux/atomic/atomic-instrumented.h:4456 [inline]"
https://github.com/bluez/bluetooth-next/pull/289
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-06-05 20:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05 14:23 [PATCH v2] Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref Marco Elver
2026-06-05 15:47 ` Luiz Augusto von Dentz
2026-06-05 20:33 ` [v2] " 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