This is an automated email from the ASF dual-hosted git repository.

janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit 23d61150ddae4bc8356356d7ef09d816fb89da45
Author: Szymon Janc <[email protected]>
AuthorDate: Mon Sep 23 15:59:46 2024 +0200

    nimble/host: Add extended advertising report event validation
    
    Validate if HCI event received from controller has proper sizes before
    passing it to GAP event.
---
 nimble/host/src/ble_hs_hci_evt.c | 53 ++++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 8 deletions(-)

diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c
index 181a2fb48..37265c016 100644
--- a/nimble/host/src/ble_hs_hci_evt.c
+++ b/nimble/host/src/ble_hs_hci_evt.c
@@ -597,29 +597,66 @@ ble_hs_hci_decode_legacy_type(uint16_t evt_type)
         return -1;
     }
 }
-#endif
 
 static int
-ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data,
-                              unsigned int len)
+ble_hs_hci_evt_le_ext_adv_rpt_first_pass(const void *data, unsigned int len)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
     const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data;
     const struct ext_adv_report *report;
-    struct ble_gap_ext_disc_desc desc;
     int i;
-    int legacy_event_type;
 
     if (len < sizeof(*ev)) {
-        return BLE_HS_EBADDATA;
+        return BLE_HS_ECONTROLLER;
     }
 
+    len -= sizeof(*ev);
+    data += sizeof(*ev);
+
     if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN ||
         ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) {
         return BLE_HS_EBADDATA;
     }
 
-    /* TODO properly validate len of the event */
+    for (i = 0; i < ev->num_reports; i++) {
+        if (len < sizeof(*report)) {
+            return BLE_HS_ECONTROLLER;
+        }
+
+        report = data;
+
+        if (report->data_len > len) {
+            return BLE_HS_ECONTROLLER;
+        }
+
+        len -= sizeof(*report) + report->data_len;
+        data += sizeof(*report) + report->data_len;
+    }
+
+    /* Make sure length was correct */
+    if (len) {
+        return BLE_HS_ECONTROLLER;
+    }
+
+    return 0;
+}
+#endif
+
+static int
+ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data,
+                              unsigned int len)
+{
+#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
+    const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data;
+    const struct ext_adv_report *report;
+    struct ble_gap_ext_disc_desc desc;
+    int legacy_event_type;
+    int rc;
+    int i;
+
+    rc = ble_hs_hci_evt_le_ext_adv_rpt_first_pass(data, len);
+    if (rc != 0) {
+        return rc;
+    }
 
     report = &ev->reports[0];
     for (i = 0; i < ev->num_reports; i++) {

Reply via email to