Fix resource leak and unchecked mbedTLS errors in ml_derp_connect() - #37
Open
antonmeyer wants to merge 1 commit into
Open
Fix resource leak and unchecked mbedTLS errors in ml_derp_connect()#37antonmeyer wants to merge 1 commit into
antonmeyer wants to merge 1 commit into
Conversation
Two related bugs in the DERP TLS connection setup:
1. mbedtls_ctr_drbg_seed()/mbedtls_ssl_config_defaults()/mbedtls_ssl_setup()'s
return values were never checked. A failure in any of them - plausible
under low memory, since these are exactly the calls that allocate - let
the code continue straight into mbedtls_ssl_handshake() with a
partially/incorrectly initialized SSL context, producing a confusing
downstream MBEDTLS_ERR_SSL_BAD_INPUT_DATA ("Bad input parameters to
function") instead of surfacing the real, earlier failure.
2. Every failure path after mbedtls_ssl_init()/etc. (TLS handshake
failure, HTTP-upgrade write failure, upgrade-response timeout/read-
failure/rejection) only ever called ml_close_sock() on the raw socket -
never mbedtls_ssl_free()/mbedtls_ssl_config_free()/mbedtls_ctr_drbg_free()/
mbedtls_entropy_free(). Those four are only freed by
ml_derp_disconnect(), which runs solely on an *established* connection
later dropping - a connect attempt that never reached
ML_EVT_DERP_CONNECTED leaked all four, permanently, every single time.
On a link unstable enough to fail DERP connects repeatedly, this leaks
on every retry - a direct, mechanical path from "network is flaky" to
slow memory exhaustion, found via exactly that real-world scenario.
Fixed by refactoring to a single `goto fail` cleanup path, matching the
pattern mbedTLS's own reference example (programs/ssl/ssl_client1.c)
uses: every failure past mbedtls_ssl_init() now frees all four
structures before returning, and the three previously-unchecked setup
calls now check their return value and log the real mbedTLS error
string instead of silently continuing.
Verified building clean as part of a full ESP-IDF app (esp32s3 target)
using this component; not independently reproduced as a standalone
crash here, found via production hardware showing internal-SRAM
exhaustion correlated with these exact error signatures.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related bugs found in
ml_derp_connect()(components/microlink/src/ml_derp.c) while investigating an internal-SRAM exhaustion incident on real ESP32-S3 hardware running this component (mothership role, alongsideesp_http_server/an MQTT broker):Unchecked mbedTLS setup return values.
mbedtls_ctr_drbg_seed(),mbedtls_ssl_config_defaults(), andmbedtls_ssl_setup()'s return values were never checked. A failure in any of them — plausible under low memory, since these are exactly the calls that allocate — let the code continue straight intombedtls_ssl_handshake()with a partially/incorrectly initialized SSL context. On our hardware this surfaced as a confusing, misleadingMBEDTLS_ERR_SSL_BAD_INPUT_DATA("Bad input parameters to function") repeating on every retry, rather than the real, earlier failure being logged.Resource leak on every failed connect attempt. Every failure path after
mbedtls_ssl_init()/etc. (TLS handshake failure, HTTP-upgrade write failure, upgrade-response timeout/read-failure/rejection) only ever calledml_close_sock()on the raw socket — nevermbedtls_ssl_free()/mbedtls_ssl_config_free()/mbedtls_ctr_drbg_free()/mbedtls_entropy_free(). Those four are only freed byml_derp_disconnect(), which runs solely on an established connection later dropping — a connect attempt that never reachedML_EVT_DERP_CONNECTEDleaked all four structures, permanently, every single time. On a link unstable enough to fail DERP connects repeatedly (which is what we were independently chasing down on our end), this leaks on every retry — a direct, mechanical path from "network is flaky" to slow memory exhaustion.Fix
Refactored to a single
goto failcleanup path, matching the pattern mbedTLS's own reference example (programs/ssl/ssl_client1.c) uses for exactly this kind of setup. Every failure pastmbedtls_ssl_init()now frees all four structures before returning, and the three previously-unchecked setup calls now check their return value and log the real mbedTLS error string instead of silently continuing.Testing
Verified building clean as part of a full ESP-IDF application (esp32s3 target) using this component. Not independently reproduced as a standalone minimal repro — found via production hardware showing internal-SRAM exhaustion (
heap_caps_get_minimum_free_sizedropping to a few KB) correlated with these exact error signatures in the field, on a device with an already-unstable DERP/DISCO link to one peer.