* [PATCH v2 0/1] Bluetooth: fix stack OOB write in the legacy adv data path @ 2026-11-10 17:53 Piyus Kedia 2026-11-10 17:53 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Piyus Kedia 0 siblings, 1 reply; 5+ messages in thread From: Piyus Kedia @ 2026-11-10 17:53 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: linux-bluetooth, linux-kernel, Kapil Vaswani, Piyus Kedia Hi, We would like to follow up on the stack out-of-bounds writes in eir_create_adv_data() and eir_create_scan_rsp() we reported earlier. The patch we suggested earlier bounded the copy in eir.c. As Luiz pointed out, the stale advertising instance is the bug rather than the missing bounds check, so this new patch unregisters instances that no longer fit the controller's capability, at power-on, and reports them with MGMT_EV_ADVERTISING_REMOVED. Userspace can add them again with the right size. Verified at runtime: with this patch applied, the reproducer completes cleanly on both the adv_data and scan_rsp paths and the instance is removed; without it KASAN reports a 220-byte write into the 31-byte buffer at eir.c:303 and eir.c:360. The tree it was verified on has net/bluetooth/eir.c and hci_powered_update_adv_sync() byte-identical to this base. Apologies for the form of our earlier submission: it was a bug report that patchwork picked up as a patch, which is why the whole report ended up as the commit message. Link to v1: https://patchwork.kernel.org/series/1206772/ Thanks and regards, Piyus Kedia Kapil Vaswani Piyus Kedia (1): Bluetooth: hci_sync: drop adv instances the controller cannot carry net/bluetooth/hci_sync.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) -- 2.34.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry 2026-11-10 17:53 [PATCH v2 0/1] Bluetooth: fix stack OOB write in the legacy adv data path Piyus Kedia @ 2026-11-10 17:53 ` Piyus Kedia 2026-11-10 18:59 ` Bluetooth: fix stack OOB write in the legacy adv data path bluez.test.bot 2026-11-11 19:49 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Luiz Augusto von Dentz 0 siblings, 2 replies; 5+ messages in thread From: Piyus Kedia @ 2026-11-10 17:53 UTC (permalink / raw) To: Marcel Holtmann, Luiz Augusto von Dentz Cc: linux-bluetooth, linux-kernel, Kapil Vaswani, Piyus Kedia, stable An advertising instance stores up to HCI_MAX_EXT_AD_LENGTH (251) bytes in adv_info. How much of that is accepted when the instance is added is decided by max_adv_len(), which depends on a feature bit in the controller's LE Extended Advertising support: ext_adv_capable(dev) ? HCI_MAX_EXT_AD_LENGTH : HCI_MAX_AD_LENGTH ext_adv_capable() reads hdev->le_features[1], which is re-read from the controller on every bring-up, while the instance list is only freed in hci_release_dev(). Instances therefore outlive a power cycle, and an instance added while the controller reported LE Extended Advertising can be far larger than the capability now allows. hci_update_adv_data_sync() picks the writing path by that same bit. Without it the legacy path runs, and hci_set_adv_data_sync() writes into struct hci_cp_le_set_adv_data, whose data[] is HCI_MAX_AD_LENGTH (31) bytes on the stack, while eir_create_adv_data() copies adv->adv_data_len bytes into it. A controller that reports the feature on one bring-up and not on the next overflows that buffer. This can happen when, for example, a USB dongle answers LE Read Local Features differently after a reset. scan_rsp_len has the same problem against hci_cp_le_set_scan_rsp_data. BUG: KASAN: stack-out-of-bounds in eir_create_adv_data+0x2ab/0x440 Write of size 220 at addr ffffc90006b679c1 by task syz-executor BUG: KASAN: stack-out-of-bounds in eir_create_scan_rsp+0x119/0x1a0 Write of size 220 at addr ffffc90006ca79c1 by task syz-executor Both are reached from HCIDEVUP by way of hci_powered_update_adv_sync() re-arming a stored instance. Bounding the copy in eir.c would leave the instance registered and unusable, to be retried on every bring-up. Unregister it instead, once the features have been re-read and before anything is scheduled, and report it with MGMT_EV_ADVERTISING_REMOVED. Userspace can add the instance again at a size this controller will accept. Dropping the instances before the list_empty() test below also lets the default instance be set up. The removal is under hci_dev_lock() because hci_schedule_adv_instance_sync() sends commands, which cannot be done with the lock held. Fixes: 112b5090c219 ("Bluetooth: MGMT: Fix always using HCI_MAX_AD_LENGTH") Cc: stable@vger.kernel.org Co-developed-by: Kapil Vaswani <kapil@presceralabs.ai> Signed-off-by: Kapil Vaswani <kapil@presceralabs.ai> Signed-off-by: Piyus Kedia <piyus@iiitd.ac.in> --- net/bluetooth/hci_sync.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 9213e3ef9f26..ee8b1cd9dee5 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -3608,6 +3608,34 @@ static int hci_powered_update_adv_sync(struct hci_dev *hdev) if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) return 0; + /* An instance's data was accepted against max_adv_len() as it was + * when the instance was added, and that is a branch on a controller + * feature which has just been re-read. Anything too large for the + * current capability can no longer be rendered: drop it and tell + * userspace, so it can add the instance again at a size this + * controller will take. + * + * This is safe as long as there is no command send while the lock is + * held. + */ + hci_dev_lock(hdev); + + list_for_each_entry_safe(adv, tmp, &hdev->adv_instances, list) { + u8 instance = adv->instance; + + if (adv->adv_data_len <= max_adv_len(hdev) && + adv->scan_rsp_len <= max_adv_len(hdev)) + continue; + + bt_dev_warn(hdev, "instance %u too large for this controller", + instance); + + if (!hci_remove_adv_instance(hdev, instance)) + mgmt_advertising_removed(NULL, hdev, instance); + } + + hci_dev_unlock(hdev); + /* If RPA Resolution has not been enable yet it means the * resolving list is empty and we should attempt to program the * local IRK in order to support using own_addr_type -- 2.34.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* RE: Bluetooth: fix stack OOB write in the legacy adv data path 2026-11-10 17:53 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Piyus Kedia @ 2026-11-10 18:59 ` bluez.test.bot 2026-11-11 19:49 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Luiz Augusto von Dentz 1 sibling, 0 replies; 5+ messages in thread From: bluez.test.bot @ 2026-11-10 18:59 UTC (permalink / raw) To: linux-bluetooth, piyus [-- Attachment #1: Type: text/plain, Size: 1605 bytes --] This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/series/1207528/ ---Test result--- Test Summary: CheckPatch PASS 0.53 seconds VerifyFixes PASS 0.07 seconds VerifySignedoff PASS 0.07 seconds GitLint PASS 0.20 seconds SubjectPrefix PASS 0.06 seconds BuildKernel PASS 24.04 seconds CheckAllWarning PASS 27.41 seconds CheckSparse PASS 29.59 seconds BuildKernel32 PASS 24.15 seconds CheckKernelLLVM PASS 26.22 seconds TestRunnerSetup PASS 554.53 seconds TestRunner_l2cap-tester PASS 13.20 seconds TestRunner_iso-tester PASS 9.60 seconds TestRunner_bnep-tester PASS 2.86 seconds TestRunner_mgmt-tester PASS 84.44 seconds TestRunner_rfcomm-tester PASS 4.22 seconds TestRunner_sco-tester PASS 5.17 seconds TestRunner_ioctl-tester PASS 4.29 seconds TestRunner_mesh-tester PASS 5.16 seconds TestRunner_smp-tester PASS 4.04 seconds TestRunner_userchan-tester PASS 2.93 seconds TestRunner_6lowpan-tester PASS 4.15 seconds IncrementalBuild PASS 23.04 seconds https://github.com/bluez/bluetooth-next/pull/1105 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry 2026-11-10 17:53 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Piyus Kedia 2026-11-10 18:59 ` Bluetooth: fix stack OOB write in the legacy adv data path bluez.test.bot @ 2026-11-11 19:49 ` Luiz Augusto von Dentz 2026-11-12 12:57 ` Piyus Kedia 1 sibling, 1 reply; 5+ messages in thread From: Luiz Augusto von Dentz @ 2026-11-11 19:49 UTC (permalink / raw) To: Piyus Kedia Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, Kapil Vaswani, stable Hi Piyus, On Tue, Nov 10, 2026 at 12:54 PM Piyus Kedia <piyus@iiitd.ac.in> wrote: > > An advertising instance stores up to HCI_MAX_EXT_AD_LENGTH (251) bytes > in adv_info. How much of that is accepted when the instance is added is > decided by max_adv_len(), which depends on a feature bit in the > controller's LE Extended Advertising support: > > ext_adv_capable(dev) ? HCI_MAX_EXT_AD_LENGTH : HCI_MAX_AD_LENGTH > > ext_adv_capable() reads hdev->le_features[1], which is re-read from the > controller on every bring-up, while the instance list is only freed in > hci_release_dev(). Instances therefore outlive a power cycle, and an > instance added while the controller reported LE Extended Advertising > can be far larger than the capability now allows. > > hci_update_adv_data_sync() picks the writing path by that same bit. > Without it the legacy path runs, and hci_set_adv_data_sync() writes > into struct hci_cp_le_set_adv_data, whose data[] is HCI_MAX_AD_LENGTH > (31) bytes on the stack, while eir_create_adv_data() copies > adv->adv_data_len bytes into it. A controller that reports the feature > on one bring-up and not on the next overflows that buffer. This can > happen when, for example, a USB dongle answers LE Read Local Features > differently after a reset. scan_rsp_len has the same problem against > hci_cp_le_set_scan_rsp_data. > > BUG: KASAN: stack-out-of-bounds in eir_create_adv_data+0x2ab/0x440 > Write of size 220 at addr ffffc90006b679c1 by task syz-executor > > BUG: KASAN: stack-out-of-bounds in eir_create_scan_rsp+0x119/0x1a0 > Write of size 220 at addr ffffc90006ca79c1 by task syz-executor > > Both are reached from HCIDEVUP by way of hci_powered_update_adv_sync() > re-arming a stored instance. > > Bounding the copy in eir.c would leave the instance registered and > unusable, to be retried on every bring-up. Unregister it instead, once > the features have been re-read and before anything is scheduled, and > report it with MGMT_EV_ADVERTISING_REMOVED. Userspace can add the > instance again at a size this controller will accept. Dropping the > instances before the list_empty() test below also lets the default > instance be set up. > > The removal is under hci_dev_lock() because > hci_schedule_adv_instance_sync() sends commands, which cannot be done > with the lock held. > > Fixes: 112b5090c219 ("Bluetooth: MGMT: Fix always using HCI_MAX_AD_LENGTH") > Cc: stable@vger.kernel.org > Co-developed-by: Kapil Vaswani <kapil@presceralabs.ai> > Signed-off-by: Kapil Vaswani <kapil@presceralabs.ai> > Signed-off-by: Piyus Kedia <piyus@iiitd.ac.in> > --- > net/bluetooth/hci_sync.c | 28 ++++++++++++++++++++++++++++ > 1 file changed, 28 insertions(+) > > diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c > index 9213e3ef9f26..ee8b1cd9dee5 100644 > --- a/net/bluetooth/hci_sync.c > +++ b/net/bluetooth/hci_sync.c > @@ -3608,6 +3608,34 @@ static int hci_powered_update_adv_sync(struct hci_dev *hdev) > if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) > return 0; > > + /* An instance's data was accepted against max_adv_len() as it was > + * when the instance was added, and that is a branch on a controller > + * feature which has just been re-read. Anything too large for the > + * current capability can no longer be rendered: drop it and tell > + * userspace, so it can add the instance again at a size this > + * controller will take. > + * > + * This is safe as long as there is no command send while the lock is > + * held. > + */ > + hci_dev_lock(hdev); > + > + list_for_each_entry_safe(adv, tmp, &hdev->adv_instances, list) { > + u8 instance = adv->instance; > + > + if (adv->adv_data_len <= max_adv_len(hdev) && > + adv->scan_rsp_len <= max_adv_len(hdev)) > + continue; > + > + bt_dev_warn(hdev, "instance %u too large for this controller", > + instance); > + > + if (!hci_remove_adv_instance(hdev, instance)) > + mgmt_advertising_removed(NULL, hdev, instance); > + } > + > + hci_dev_unlock(hdev); > + > /* If RPA Resolution has not been enable yet it means the > * resolving list is empty and we should attempt to program the > * local IRK in order to support using own_addr_type > -- > 2.34.1 Sashiko flagged a few problems: https://sashiko.dev/#/patchset/20261110175334.676816-1-piyus%40iiitd.ac.in -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry 2026-11-11 19:49 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Luiz Augusto von Dentz @ 2026-11-12 12:57 ` Piyus Kedia 0 siblings, 0 replies; 5+ messages in thread From: Piyus Kedia @ 2026-11-12 12:57 UTC (permalink / raw) To: Luiz Augusto von Dentz Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, Kapil Vaswani, stable Hi Luiz, We just submitted another version that addressed the issues raised by Sashiko. https://lore.kernel.org/linux-bluetooth/20261112125420.3905719-1-piyus@iiitd.ac.in/T/#u Best, Piyus On Thu, Nov 12, 2026 at 1:19 AM Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote: > > Hi Piyus, > > On Tue, Nov 10, 2026 at 12:54 PM Piyus Kedia <piyus@iiitd.ac.in> wrote: > > > > An advertising instance stores up to HCI_MAX_EXT_AD_LENGTH (251) bytes > > in adv_info. How much of that is accepted when the instance is added is > > decided by max_adv_len(), which depends on a feature bit in the > > controller's LE Extended Advertising support: > > > > ext_adv_capable(dev) ? HCI_MAX_EXT_AD_LENGTH : HCI_MAX_AD_LENGTH > > > > ext_adv_capable() reads hdev->le_features[1], which is re-read from the > > controller on every bring-up, while the instance list is only freed in > > hci_release_dev(). Instances therefore outlive a power cycle, and an > > instance added while the controller reported LE Extended Advertising > > can be far larger than the capability now allows. > > > > hci_update_adv_data_sync() picks the writing path by that same bit. > > Without it the legacy path runs, and hci_set_adv_data_sync() writes > > into struct hci_cp_le_set_adv_data, whose data[] is HCI_MAX_AD_LENGTH > > (31) bytes on the stack, while eir_create_adv_data() copies > > adv->adv_data_len bytes into it. A controller that reports the feature > > on one bring-up and not on the next overflows that buffer. This can > > happen when, for example, a USB dongle answers LE Read Local Features > > differently after a reset. scan_rsp_len has the same problem against > > hci_cp_le_set_scan_rsp_data. > > > > BUG: KASAN: stack-out-of-bounds in eir_create_adv_data+0x2ab/0x440 > > Write of size 220 at addr ffffc90006b679c1 by task syz-executor > > > > BUG: KASAN: stack-out-of-bounds in eir_create_scan_rsp+0x119/0x1a0 > > Write of size 220 at addr ffffc90006ca79c1 by task syz-executor > > > > Both are reached from HCIDEVUP by way of hci_powered_update_adv_sync() > > re-arming a stored instance. > > > > Bounding the copy in eir.c would leave the instance registered and > > unusable, to be retried on every bring-up. Unregister it instead, once > > the features have been re-read and before anything is scheduled, and > > report it with MGMT_EV_ADVERTISING_REMOVED. Userspace can add the > > instance again at a size this controller will accept. Dropping the > > instances before the list_empty() test below also lets the default > > instance be set up. > > > > The removal is under hci_dev_lock() because > > hci_schedule_adv_instance_sync() sends commands, which cannot be done > > with the lock held. > > > > Fixes: 112b5090c219 ("Bluetooth: MGMT: Fix always using HCI_MAX_AD_LENGTH") > > Cc: stable@vger.kernel.org > > Co-developed-by: Kapil Vaswani <kapil@presceralabs.ai> > > Signed-off-by: Kapil Vaswani <kapil@presceralabs.ai> > > Signed-off-by: Piyus Kedia <piyus@iiitd.ac.in> > > --- > > net/bluetooth/hci_sync.c | 28 ++++++++++++++++++++++++++++ > > 1 file changed, 28 insertions(+) > > > > diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c > > index 9213e3ef9f26..ee8b1cd9dee5 100644 > > --- a/net/bluetooth/hci_sync.c > > +++ b/net/bluetooth/hci_sync.c > > @@ -3608,6 +3608,34 @@ static int hci_powered_update_adv_sync(struct hci_dev *hdev) > > if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) > > return 0; > > > > + /* An instance's data was accepted against max_adv_len() as it was > > + * when the instance was added, and that is a branch on a controller > > + * feature which has just been re-read. Anything too large for the > > + * current capability can no longer be rendered: drop it and tell > > + * userspace, so it can add the instance again at a size this > > + * controller will take. > > + * > > + * This is safe as long as there is no command send while the lock is > > + * held. > > + */ > > + hci_dev_lock(hdev); > > + > > + list_for_each_entry_safe(adv, tmp, &hdev->adv_instances, list) { > > + u8 instance = adv->instance; > > + > > + if (adv->adv_data_len <= max_adv_len(hdev) && > > + adv->scan_rsp_len <= max_adv_len(hdev)) > > + continue; > > + > > + bt_dev_warn(hdev, "instance %u too large for this controller", > > + instance); > > + > > + if (!hci_remove_adv_instance(hdev, instance)) > > + mgmt_advertising_removed(NULL, hdev, instance); > > + } > > + > > + hci_dev_unlock(hdev); > > + > > /* If RPA Resolution has not been enable yet it means the > > * resolving list is empty and we should attempt to program the > > * local IRK in order to support using own_addr_type > > -- > > 2.34.1 > > Sashiko flagged a few problems: > > https://sashiko.dev/#/patchset/20261110175334.676816-1-piyus%40iiitd.ac.in > > -- > Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-12 12:57 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-10 17:53 [PATCH v2 0/1] Bluetooth: fix stack OOB write in the legacy adv data path Piyus Kedia 2026-11-10 17:53 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Piyus Kedia 2026-11-10 18:59 ` Bluetooth: fix stack OOB write in the legacy adv data path bluez.test.bot 2026-11-11 19:49 ` [PATCH v2 1/1] Bluetooth: hci_sync: drop adv instances the controller cannot carry Luiz Augusto von Dentz 2026-11-12 12:57 ` Piyus Kedia
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox