From 9464ecd6e32ff80d09b0c1678805c0fa4e722821 Mon Sep 17 00:00:00 2001 From: Shreeyash Date: Tue, 23 Sep 2025 18:36:03 +0530 Subject: [PATCH] fix(nimble):fix array overflow caused by invalid connection handle indexing --- nimble/host/src/ble_gap.c | 61 +++++++++++++++++------------- nimble/host/src/ble_hs_conn_priv.h | 5 +++ nimble/host/src/ble_hs_hci_evt.c | 3 +- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index a57a7090a..f1aa2261c 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -318,7 +318,6 @@ static uint8_t pawr_adv_handle; static uint16_t pawr_sync_handle; #endif -int slave_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry); #if NIMBLE_BLE_CONNECT @@ -345,11 +344,6 @@ static int ble_gap_conn_cancel_tx(void); static int ble_gap_disc_enable_tx(int enable, int filter_duplicates); #endif -uint16_t g_max_tx_time[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; -uint16_t g_max_rx_time[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1 ]; -uint16_t g_max_tx_octets[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; -uint16_t g_max_rx_octets[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; - STATS_SECT_DECL(ble_gap_stats) ble_gap_stats; STATS_NAME_START(ble_gap_stats) STATS_NAME(ble_gap_stats, wl_set) @@ -1626,8 +1620,8 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason) // Send disconnect event in slave role if connect was sent if ((conn != NULL) && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { - if (slave_conn[conn_handle]) { - slave_conn[conn_handle] = 0; + if (conn->slave_conn) { + conn->slave_conn = 0; } else { send = 0; } @@ -1644,10 +1638,15 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason) ble_hs_atomic_conn_delete(conn_handle); - g_max_tx_time[conn_handle] = 0; - g_max_rx_time[conn_handle] = 0; - g_max_tx_octets[conn_handle] = 0; - g_max_rx_octets[conn_handle] = 0; + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + if (conn != NULL) { + conn->bhc_max_tx_time = 0; + conn->bhc_max_rx_time = 0; + conn->bhc_max_tx_octets = 0; + conn->bhc_max_rx_octets = 0; + } + ble_hs_unlock(); event.type = BLE_GAP_EVENT_DISCONNECT; event.disconnect.reason = reason; @@ -3137,9 +3136,9 @@ ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used conn->supported_feat = get_le32(ev->features); } - if (conn != NULL) { - ble_gap_event_connect_call(ev->conn_handle, 0); - slave_conn[ev->conn_handle] = 1; + if (conn != NULL) { + ble_gap_event_connect_call(ev->conn_handle, ev->status); + conn->slave_conn = 1; } } #endif @@ -3221,7 +3220,7 @@ ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev) #if NIMBLE_BLE_CONNECT struct ble_gap_event event; uint16_t conn_handle = le16toh(ev->conn_handle); - + struct ble_hs_conn *conn; memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_DATA_LEN_CHG; event.data_len_chg.max_tx_octets = le16toh(ev->max_tx_octets); @@ -3229,11 +3228,16 @@ ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev) event.data_len_chg.max_tx_time = le16toh(ev->max_tx_time); event.data_len_chg.max_rx_time = le16toh(ev->max_rx_time); - g_max_tx_octets[conn_handle] = event.data_len_chg.max_tx_octets; - g_max_rx_octets[conn_handle] = event.data_len_chg.max_rx_octets; - g_max_tx_time[conn_handle] = event.data_len_chg.max_tx_time; - g_max_rx_time[conn_handle] = event.data_len_chg.max_rx_time; - + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + if (conn != NULL) { + conn->bhc_max_tx_octets = event.data_len_chg.max_tx_octets; + conn->bhc_max_rx_octets = event.data_len_chg.max_rx_octets; + conn->bhc_max_tx_time = event.data_len_chg.max_tx_time; + conn->bhc_max_rx_time = event.data_len_chg.max_rx_time; + } + ble_hs_unlock(); + ble_gap_event_listener_call(&event); ble_gap_call_conn_event_cb(&event, conn_handle); #endif @@ -8346,16 +8350,21 @@ ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, * If yes, then just return event to host indicating success * since controller will not send any event in this scenario */ - if (g_max_tx_time[conn_handle] == tx_time && g_max_tx_octets[conn_handle] == tx_octets) { + struct ble_hs_conn *conn; + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + if (conn != NULL && conn->bhc_max_tx_time == tx_time && conn->bhc_max_tx_octets == tx_octets) { struct ble_gap_event event; memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_DATA_LEN_CHG; - event.data_len_chg.max_tx_octets = g_max_tx_octets[conn_handle]; - event.data_len_chg.max_rx_octets = g_max_rx_octets[conn_handle]; - event.data_len_chg.max_tx_time = g_max_tx_time[conn_handle]; - event.data_len_chg.max_rx_time = g_max_rx_time[conn_handle]; + event.data_len_chg.max_tx_octets = conn->bhc_max_tx_octets; + event.data_len_chg.max_rx_octets = conn->bhc_max_rx_octets; + event.data_len_chg.max_tx_time = conn->bhc_max_tx_time; + event.data_len_chg.max_rx_time = conn->bhc_max_rx_time; event.data_len_chg.conn_handle = conn_handle; ble_gap_event_listener_call(&event); diff --git a/nimble/host/src/ble_hs_conn_priv.h b/nimble/host/src/ble_hs_conn_priv.h index c994ed220..82833ad36 100644 --- a/nimble/host/src/ble_hs_conn_priv.h +++ b/nimble/host/src/ble_hs_conn_priv.h @@ -51,6 +51,7 @@ struct ble_hs_conn { SLIST_ENTRY(ble_hs_conn) bhc_next; uint16_t bhc_handle; uint8_t bhc_our_addr_type; + uint8_t slave_conn : 1; #if MYNEWT_VAL(BLE_EXT_ADV) uint8_t bhc_our_rnd_addr[6]; #endif @@ -61,6 +62,10 @@ struct ble_hs_conn { uint16_t bhc_itvl; uint16_t bhc_latency; uint16_t bhc_supervision_timeout; + uint16_t bhc_max_tx_octets; + uint16_t bhc_max_rx_octets; + uint16_t bhc_max_tx_time; + uint16_t bhc_max_rx_time; uint8_t bhc_master_clock_accuracy; uint32_t supported_feat; diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index a6460988e..f2292368f 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -38,7 +38,6 @@ struct ble_gap_reattempt_ctxt { extern int ble_gap_master_connect_reattempt(uint16_t conn_handle); extern int ble_gap_slave_adv_reattempt(void); -extern int slave_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; #endif #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) @@ -330,7 +329,7 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data, } else if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER) && \ ((ev->reason == BLE_ERR_CONN_ESTABLISHMENT) || \ - (!slave_conn[ev->conn_handle] && ev->reason == BLE_ERR_CONN_SPVN_TMO))) { //slave + (!conn->slave_conn && ev->reason == BLE_ERR_CONN_SPVN_TMO))) { //slave BLE_HS_LOG(INFO, "Reattempt advertising; reason: 0x%x, status = %x", ev->reason, ev->status);