* [PATCH] Bluetooth: hci_sync: Fix scan response data UAF
@ 2026-07-20 16:47 Chengfeng Ye
2026-07-20 19:54 ` Luiz Augusto von Dentz
0 siblings, 1 reply; 2+ messages in thread
From: Chengfeng Ye @ 2026-07-20 16:47 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-bluetooth, linux-kernel, Chengfeng Ye, stable
eir_create_scan_rsp() calls hci_find_adv_instance(), whose return value is
valid only while hdev->lock is held. After advertising setup was moved to
hci_cmd_sync_work, neither scan response data builder held that lock.
hci_set_ext_scan_rsp_data_sync() also kept the returned pointer while
waiting for the controller and wrote scan_rsp_changed through it afterward.
An advertising termination event can therefore interleave as follows:
hci_cmd_sync_work hci_rx_work
hci_find_adv_instance()
__hci_cmd_sync_status()
wait for controller reply hci_dev_lock()
hci_remove_adv_instance()
kfree(adv)
adv->scan_rsp_changed = false
KASAN reported:
BUG: KASAN: slab-use-after-free in hci_set_ext_scan_rsp_data_sync+0x2e1/0x300
Write of size 1 at addr ffff88810a45d21d by task kworker/u17:0/88
Workqueue: hci0 hci_cmd_sync_work
Call Trace:
hci_set_ext_scan_rsp_data_sync+0x2e1/0x300
hci_schedule_adv_instance_sync+0x390/0x4c0
hci_cmd_sync_work+0x173/0x300
Allocated by task 87:
hci_add_adv_instance+0x538/0xac0
add_advertising+0x885/0x1160
Freed by task 89:
kfree+0x131/0x3c0
hci_remove_adv_instance+0x1d8/0x3b0
hci_le_ext_adv_term_evt+0x17b/0x730
Hold hdev->lock while looking up the instance, building the scan
response, and clearing its dirty bit. Clear the bit before waiting for
the controller so no adv_info pointer survives the wait, and restore it
under the lock if the command fails. This also preserves an update that
races with a successful command because that update sets the bit again.
Protect the legacy scan response builder with the same lock.
Fixes: cba6b758711c ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
net/bluetooth/hci_sync.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 532534bc601c..8c69a98c71e8 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -1490,9 +1490,13 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
int err;
if (instance) {
+ hci_dev_lock(hdev);
+
adv = hci_find_adv_instance(hdev, instance);
- if (!adv || !adv->scan_rsp_changed)
+ if (!adv || !adv->scan_rsp_changed) {
+ hci_dev_unlock(hdev);
return 0;
+ }
}
len = eir_create_scan_rsp(hdev, instance, pdu->data);
@@ -1502,15 +1506,27 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+ if (adv) {
+ adv->scan_rsp_changed = false;
+ hci_dev_unlock(hdev);
+ }
+
err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
struct_size(pdu, data, len), pdu,
HCI_CMD_TIMEOUT);
- if (err)
+ if (err) {
+ if (instance) {
+ hci_dev_lock(hdev);
+ adv = hci_find_adv_instance(hdev, instance);
+ if (adv)
+ adv->scan_rsp_changed = true;
+ hci_dev_unlock(hdev);
+ }
+
return err;
+ }
- if (adv) {
- adv->scan_rsp_changed = false;
- } else {
+ if (!instance) {
memcpy(hdev->scan_rsp_data, pdu->data, len);
hdev->scan_rsp_data_len = len;
}
@@ -1525,8 +1541,14 @@ static int __hci_set_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
memset(&cp, 0, sizeof(cp));
+ if (instance)
+ hci_dev_lock(hdev);
+
len = eir_create_scan_rsp(hdev, instance, cp.data);
+ if (instance)
+ hci_dev_unlock(hdev);
+
if (hdev->scan_rsp_data_len == len &&
!memcmp(cp.data, hdev->scan_rsp_data, len))
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] Bluetooth: hci_sync: Fix scan response data UAF
2026-07-20 16:47 [PATCH] Bluetooth: hci_sync: Fix scan response data UAF Chengfeng Ye
@ 2026-07-20 19:54 ` Luiz Augusto von Dentz
0 siblings, 0 replies; 2+ messages in thread
From: Luiz Augusto von Dentz @ 2026-07-20 19:54 UTC (permalink / raw)
To: Chengfeng Ye; +Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, stable
Hi,
On Mon, Jul 20, 2026 at 12:47 PM Chengfeng Ye <nicoyip.dev@gmail.com> wrote:
>
> eir_create_scan_rsp() calls hci_find_adv_instance(), whose return value is
> valid only while hdev->lock is held. After advertising setup was moved to
> hci_cmd_sync_work, neither scan response data builder held that lock.
> hci_set_ext_scan_rsp_data_sync() also kept the returned pointer while
> waiting for the controller and wrote scan_rsp_changed through it afterward.
>
> An advertising termination event can therefore interleave as follows:
>
> hci_cmd_sync_work hci_rx_work
> hci_find_adv_instance()
> __hci_cmd_sync_status()
> wait for controller reply hci_dev_lock()
> hci_remove_adv_instance()
> kfree(adv)
> adv->scan_rsp_changed = false
>
> KASAN reported:
>
> BUG: KASAN: slab-use-after-free in hci_set_ext_scan_rsp_data_sync+0x2e1/0x300
> Write of size 1 at addr ffff88810a45d21d by task kworker/u17:0/88
> Workqueue: hci0 hci_cmd_sync_work
> Call Trace:
> hci_set_ext_scan_rsp_data_sync+0x2e1/0x300
> hci_schedule_adv_instance_sync+0x390/0x4c0
> hci_cmd_sync_work+0x173/0x300
> Allocated by task 87:
> hci_add_adv_instance+0x538/0xac0
> add_advertising+0x885/0x1160
> Freed by task 89:
> kfree+0x131/0x3c0
> hci_remove_adv_instance+0x1d8/0x3b0
> hci_le_ext_adv_term_evt+0x17b/0x730
>
> Hold hdev->lock while looking up the instance, building the scan
> response, and clearing its dirty bit. Clear the bit before waiting for
> the controller so no adv_info pointer survives the wait, and restore it
> under the lock if the command fails. This also preserves an update that
> races with a successful command because that update sets the bit again.
> Protect the legacy scan response builder with the same lock.
>
> Fixes: cba6b758711c ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2")
> Cc: stable@vger.kernel.org
> Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
> ---
> net/bluetooth/hci_sync.c | 32 +++++++++++++++++++++++++++-----
> 1 file changed, 27 insertions(+), 5 deletions(-)
>
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> index 532534bc601c..8c69a98c71e8 100644
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -1490,9 +1490,13 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
> int err;
>
> if (instance) {
> + hci_dev_lock(hdev);
> +
> adv = hci_find_adv_instance(hdev, instance);
> - if (!adv || !adv->scan_rsp_changed)
> + if (!adv || !adv->scan_rsp_changed) {
> + hci_dev_unlock(hdev);
> return 0;
> + }
> }
>
> len = eir_create_scan_rsp(hdev, instance, pdu->data);
> @@ -1502,15 +1506,27 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
> pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
> pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;
>
> + if (adv) {
> + adv->scan_rsp_changed = false;
> + hci_dev_unlock(hdev);
> + }
> +
> err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
> struct_size(pdu, data, len), pdu,
> HCI_CMD_TIMEOUT);
> - if (err)
> + if (err) {
> + if (instance) {
> + hci_dev_lock(hdev);
> + adv = hci_find_adv_instance(hdev, instance);
> + if (adv)
> + adv->scan_rsp_changed = true;
> + hci_dev_unlock(hdev);
> + }
> +
> return err;
> + }
>
> - if (adv) {
> - adv->scan_rsp_changed = false;
> - } else {
> + if (!instance) {
> memcpy(hdev->scan_rsp_data, pdu->data, len);
> hdev->scan_rsp_data_len = len;
> }
> @@ -1525,8 +1541,14 @@ static int __hci_set_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
>
> memset(&cp, 0, sizeof(cp));
>
> + if (instance)
> + hci_dev_lock(hdev);
> +
> len = eir_create_scan_rsp(hdev, instance, cp.data);
>
> + if (instance)
> + hci_dev_unlock(hdev);
> +
> if (hdev->scan_rsp_data_len == len &&
> !memcmp(cp.data, hdev->scan_rsp_data, len))
> return 0;
> --
> 2.43.0
It looks like Sashiko found some other places where this could be a problem:
https://sashiko.dev/#/patchset/20260720164738.2921802-1-nicoyip.dev%40gmail.com
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-20 19:55 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 16:47 [PATCH] Bluetooth: hci_sync: Fix scan response data UAF Chengfeng Ye
2026-07-20 19:54 ` Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox