Ben MeadorsandGitHub 168f669e61 esp32: fix NimBLE use-after-free crash when disabling bluetooth while connected (#10950)
* esp32: fix NimBLE use-after-free crash when disabling bluetooth while connected

Saving certain configs over BLE (e.g. MQTT module config) calls
disableBluetooth() -> NimbleBluetooth::deinit() while the phone is still
connected. deinit() called BLEDevice::deinit(true) straight away, which
deletes the BLEServer before nimble_port_stop(). Stopping the NimBLE
port with a live connection makes the host synthesize unsubscribe events
via ble_gatts_connection_broken() and dispatch them into the freed
BLEServer -> LoadProhibited panic in BLEServer::handleGATTServerEvent
(iterating server->m_notifyChrVec on freed memory).

Backtrace tail:
  BLEServer::handleGATTServerEvent (SUBSCRIBE)
  <- ble_gatts_subscribe_event <- ble_gatts_connection_broken
  <- ble_gap_conn_broken <- ble_gap_rx_disconn_complete

It was reliably preceded by our onRead callback pinning the NimBLE host
task in its up-to-20s polling loop ('BLE onRead: timeout after 19920 ms,
4000 tries'), so the host task couldn't process the teardown until long
after the objects under it were freed.

Fix: drain before demolition in deinit(). Clear
onReadCallbackIsWaitingForData so an in-flight onRead returns
immediately; disconnect the peer and wait (bounded, ~2s) for the host
task to run onDisconnect (which clears nimbleBluetoothConnHandle) so the
unsubscribe/GATT teardown lands on the still-live server; only then
BLEDevice::deinit(true). isDeInit is raised after the drain (onDisconnect
early-returns when set and would otherwise never clear the handle), the
deferred advertising restart is dropped (the stack is going away), and
the now-dangling bleServer pointer is nulled.

deinit() runs on the main task, so waiting on the host task's callbacks
is safe; the waits are bounded regardless.

Upstream ordering bug (delete BLEServer before nimble_port_stop) to be
reported to espressif/arduino-esp32 separately.

* esp32: gate onRead during BLE teardown and use Throttle for drain wait

Addresses review feedback on the NimBLE deinit UAF fix:

- Set a bleDraining flag before disconnecting so onRead bails immediately
  instead of arming the up-to-20s wait. Without this, a read that re-arms
  after deinit() clears onReadCallbackIsWaitingForData could pin the NimBLE
  host task, block onDisconnect from clearing the conn handle, and make the
  2s drain expire. onRead now skips the wait when draining, and the wait
  loop also observes the flag so an in-flight read is released.
- Use Throttle::isWithinTimespanMs() for the bounded drain wait instead of
  a raw millis() subtraction, per coding guidelines.

* esp32: reset BLE teardown guards on re-init

deinit() latches bleDraining (new) and isDeInit (pre-existing) as teardown
guards, but setup() never cleared them. AdminModule's disable-bluetooth admin
command calls deinit() directly without a reboot, and PowerFSM can re-enable
via setBluetoothEnable(true) -> setup() on the same boot (isActive() is false
because deinit() nulls bleServer). Without resetting the flags, the re-initialized
stack has onRead permanently bailing on the drain path (empty reads) and
onDisconnect early-returning without clearing the connection handle.

Clear both flags at the top of setup() so a re-init recovers cleanly.
2026-07-09 09:42:35 -05:00
2026-07-08 14:44:59 -05:00
2026-07-02 07:39:52 -05:00
2021-10-09 17:15:12 +11:00
2024-09-24 15:24:08 -05:00
2026-01-22 15:46:37 -06:00
2026-07-07 06:34:22 -05:00
2026-07-01 19:01:27 -05:00
2026-07-01 19:01:27 -05:00
2026-01-29 10:06:58 -06:00
2024-11-28 06:26:51 -06:00
2024-09-04 15:33:28 -07:00
2026-01-29 10:06:58 -06:00
2026-01-29 10:06:58 -06:00
2026-07-01 19:01:27 -05:00
2025-01-13 12:24:05 +08:00
2026-01-29 10:06:58 -06:00

Meshtastic Logo

Meshtastic Firmware

GitHub release downloads CI CLA assistant Fiscal Contributors Vercel

meshtastic%2Ffirmware | Trendshift

Overview

This repository contains the official device firmware for Meshtastic, an open-source LoRa mesh networking project designed for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware supports various hardware platforms, including ESP32, nRF52, RP2040/RP2350, and Linux-based devices.

Meshtastic enables text messaging, location sharing, and telemetry over a decentralized mesh network, making it ideal for outdoor adventures, emergency preparedness, and remote operations.

Get Started

Join our community and help improve Meshtastic! 🚀

Stats

Alt

S
Description
No description provided
Readme GPL-3.0
69 MiB
Languages
C++ 70.8%
C 25.8%
Python 2.2%
Shell 0.7%
Batchfile 0.2%
Other 0.1%