aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAldo Ariel Panzardo <qwe.aldo@gmail.com>2026-09-15 12:59:52 -0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-09-16 13:51:34 -0400
commitb5dbb41b212c50c095a4dbee3017a84fe94f033b (patch)
tree928065df1378aac0c1ad6f27be7cb920f3f967fa
parentBluetooth: L2CAP: validate frame length before control and FCS access (diff)
Bluetooth: mgmt: fix race in read_unconf_index_list()
read_unconf_index_list() counts unconfigured controllers before allocating its response, then checks the device flags again while filling it. hci_dev_list_lock stabilizes list membership, but it does not serialize the per-device flags. During asynchronous controller setup, the worker can set HCI_UNCONFIGURED and clear HCI_SETUP between the two passes. A controller omitted from the allocation count can then become eligible for the fill pass, causing an out-of-bounds write to rp->index[]. Allocate space for every device on hci_dev_list. Since list membership cannot change while hci_dev_list_lock is held, the response remains large enough regardless of flag transitions. The reported count and response length still include only eligible unconfigured controllers. Fixes: 73d1df2a7a10 ("Bluetooth: Add support for Read Unconfigured Index List command") Cc: stable@vger.kernel.org Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-rw-r--r--net/bluetooth/mgmt.c8
1 files changed, 2 insertions, 6 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f740e745ae78..41956cdde982 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -496,13 +496,9 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
read_lock(&hci_dev_list_lock);
- count = 0;
- list_for_each_entry(d, &hci_dev_list, list) {
- if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
- count++;
- }
+ count = list_count_nodes(&hci_dev_list);
- rp_len = sizeof(*rp) + (2 * count);
+ rp_len = sizeof(*rp) + (sizeof(__le16) * count);
rp = kmalloc(rp_len, GFP_ATOMIC);
if (!rp) {
read_unlock(&hci_dev_list_lock);