From: Cen Zhang <zzzccc427@gmail.com>
To: Marcel Holtmann <marcel@holtmann.org>,
Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: linux-bluetooth@vger.kernel.org, baijiaju1990@gmail.com,
zzzccc427@gmail.com
Subject: [PATCH] Bluetooth: MGMT: snapshot LOAD_CONN_PARAM data before queueing update
Date: Fri, 3 Jul 2026 14:00:16 +0800 [thread overview]
Message-ID: <20260703060016.570188-1-zzzccc427@gmail.com> (raw)
MGMT_OP_LOAD_CONN_PARAM queues conn_update_sync() when a single parameter
update changes an existing LE central connection. The queued work currently
stores the hci_conn_params object from hdev->le_conn_params. A later
LOAD_CONN_PARAM request can clear disabled parameters and free that object
before hci_cmd_sync_work() runs the queued callback.
The buggy scenario involves two paths, with each column showing the order
within that path:
LOAD_CONN_PARAM update path: LOAD_CONN_PARAM clear path:
1. update the existing params 1. process a later multi-param load
2. queue conn_update_sync(params) 2. clear disabled parameters
3. return while the callback 3. free the queued params object
is still pending
4. callback dereferences params
Validation reproduced this kernel report:
BUG: KASAN: slab-use-after-free in conn_update_sync+0x2a/0xf0 [bluetooth]
Read of size 1 at addr ffff88810c697126 by task kworker/u17:0/377
Workqueue: hci0 hci_cmd_sync_work [bluetooth]
Call Trace:
<TASK>
dump_stack_lvl+0x66/0xa0
print_report+0xce/0x5f0
? conn_update_sync+0x2a/0xf0 [bluetooth]
? __virt_addr_valid+0x19f/0x330
? conn_update_sync+0x2a/0xf0 [bluetooth]
kasan_report+0xe0/0x110
? conn_update_sync+0x2a/0xf0 [bluetooth]
? __pfx_conn_update_sync+0x10/0x10 [bluetooth]
conn_update_sync+0x2a/0xf0 [bluetooth]
hci_cmd_sync_work+0x187/0x210 [bluetooth]
process_one_work+0x4fd/0xbc0
worker_thread+0x2d8/0x570
kthread+0x1ad/0x1f0
ret_from_fork+0x3c9/0x540
ret_from_fork_asm+0x1a/0x30
Allocated by task 466:
kasan_save_stack+0x33/0x60
kasan_save_track+0x17/0x60
__kasan_kmalloc+0xaa/0xb0
hci_conn_params_add+0xa6/0x240 [bluetooth]
load_conn_param+0x4e1/0x850 [bluetooth]
hci_sock_sendmsg+0x96b/0xf80 [bluetooth]
sock_write_iter+0x28e/0x2a0
vfs_write+0x6e4/0x810
ksys_write+0x147/0x170
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 474:
kasan_save_stack+0x33/0x60
kasan_save_track+0x17/0x60
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x313/0x590
hci_conn_params_clear_disabled+0x9b/0xc0 [bluetooth]
load_conn_param+0x4bf/0x850 [bluetooth]
hci_sock_sendmsg+0x96b/0xf80 [bluetooth]
sock_write_iter+0x28e/0x2a0
vfs_write+0x6e4/0x810
ksys_write+0x147/0x170
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Queue a private copy of the address and connection parameter values
instead, and free that copy from the sync-work destroy callback. The live
hdev->le_conn_params entry can then be cleared without invalidating queued
work.
Fixes: 0ece498c27d8c ("Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
net/bluetooth/mgmt.c | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 733a4b70e10c..4a38f7663445 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7947,6 +7947,11 @@ static int conn_update_sync(struct hci_dev *hdev, void *data)
return hci_le_conn_update_sync(hdev, conn, params);
}
+static void conn_update_sync_destroy(struct hci_dev *hdev, void *data, int err)
+{
+ kfree(data);
+}
+
static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
@@ -8054,9 +8059,28 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
(conn->le_conn_min_interval != min ||
conn->le_conn_max_interval != max ||
conn->le_conn_latency != latency ||
- conn->le_supv_timeout != timeout))
- hci_cmd_sync_queue(hdev, conn_update_sync,
- hci_param, NULL);
+ conn->le_supv_timeout != timeout)) {
+ struct hci_conn_params *update;
+
+ /* Queue a private snapshot so the live params
+ * entry can be freed later.
+ */
+ update = kzalloc_obj(*update);
+ if (!update)
+ continue;
+
+ update->addr = hci_param->addr;
+ update->addr_type = hci_param->addr_type;
+ update->conn_min_interval = min;
+ update->conn_max_interval = max;
+ update->conn_latency = latency;
+ update->supervision_timeout = timeout;
+
+ if (hci_cmd_sync_queue(hdev, conn_update_sync,
+ update,
+ conn_update_sync_destroy) < 0)
+ kfree(update);
+ }
}
}
--
2.43.0
next reply other threads:[~2026-07-03 6:00 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 6:00 Cen Zhang [this message]
2026-07-03 6:41 ` Bluetooth: MGMT: snapshot LOAD_CONN_PARAM data before queueing update bluez.test.bot
2026-07-03 15:09 ` [PATCH] " Luiz Augusto von Dentz
2026-07-03 16:54 ` Cen Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260703060016.570188-1-zzzccc427@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.