From edc2be1abd2708697d5d0c238176f6df067354d1 Mon Sep 17 00:00:00 2001 From: tahiraltundag Date: Thu, 24 Sep 2026 21:42:44 +0300 Subject: [PATCH] fix(ble_gap): fix NULL deref and use-after-free in ble_gap_rx_rd_rem_ver_info_complete conn was dereferenced after ble_hs_unlock() without NULL check, and the NULL check came after the stores. If handle is already gone (disconnect raced rem-ver complete), this panics. Also touching conn after unlock is a UAF. Check NULL and copy rem-ver fields while holding lock, save is_master flag before unlock. Mirrors the safe pattern in ble_gap_rx_rd_rem_sup_feat_complete. Fixes #1183 Signed-off-by: tahiraltundag --- src/nimble/nimble/host/src/ble_gap.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/nimble/nimble/host/src/ble_gap.c b/src/nimble/nimble/host/src/ble_gap.c index 778e6fbd6..436b00790 100644 --- a/src/nimble/nimble/host/src/ble_gap.c +++ b/src/nimble/nimble/host/src/ble_gap.c @@ -2853,23 +2853,25 @@ ble_gap_rx_rd_rem_ver_info_complete(const struct ble_hci_ev_rd_rem_ver_info_cmp { #if NIMBLE_BLE_CONNECT struct ble_hs_conn *conn; + int is_master; ble_hs_lock(); - conn = ble_hs_conn_find(le16toh(ev->conn_handle)); - - ble_hs_unlock(); + if (conn == NULL) { + ble_hs_unlock(); + return; + } conn->bhc_rd_rem_ver_params.version = ev->version; conn->bhc_rd_rem_ver_params.manufacturer = ev->manufacturer; conn->bhc_rd_rem_ver_params.subversion = ev->subversion; + is_master = conn->bhc_flags & BLE_HS_CONN_F_MASTER; + ble_hs_unlock(); - if ((conn != NULL) && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { + if (!is_master) { ble_gap_rd_rem_sup_feat_tx(ev->conn_handle); - } else { - if ((conn != NULL) && (ev->status == 0)) { - ble_gap_event_connect_call(ev->conn_handle, ev->status); - } + } else if (ev->status == 0) { + ble_gap_event_connect_call(ev->conn_handle, ev->status); } #endif }