tm: fix shm double-free of script-route refs on shared transactions#4113
Open
kvwake wants to merge 1 commit into
Open
tm: fix shm double-free of script-route refs on shared transactions#4113kvwake wants to merge 1 commit into
kvwake wants to merge 1 commit into
Conversation
t_on_reply()/t_on_negative()/t_on_branch() did an unlocked "if (*holder) shm_free(*holder); *holder = dup(...)" on a route-ref field of the shared transaction cell. From a request route against an existing transaction (e.g. a retransmitted in-dialog ACK handled by two UDP workers concurrently), both read the same pointer and free it; the second shm_free() aborts while holding the global shm lock, wedging every process (FAST_LOCK spin) until restart. Swap the holder atomically under the transaction reply lock, freeing the old pointer outside the lock. Take the lock only in REQUEST_ROUTE, since FAILURE_ROUTE and (with onreply_avp_mode) ONREPLY_ROUTE already hold LOCK_REPLIES and may re-arm these handlers. Refs OpenSIPS#4112
kvwake
marked this pull request as ready for review
July 16, 2026 15:28
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
Fixes a shared-memory double-free in the
tmmodule that crashes a worker and, onFAST_LOCKbuilds, locks the entire opensips server until restart. More details in #4112.t_on_reply(),t_on_negative()(scriptt_on_failure) andt_on_branch()update a script-route reference stored in the transaction cell with an unlocked read-modify-write:When these are called from a request route against an already-existing transaction, a retransmitted in-dialog ACK matched via
t_check_trans()and processed by multiple UDP workers concurrently.holderpoints into the shared transaction cell. Two processes read the same pointer and bothshm_free()it. The second free trips the allocator's double-free detector, whichabort()s while holding the global shm lock. on aFAST_LOCKbuild the orphaned lock then makes every process spin at 100% CPU and the server stops processing traffic (sockets stay open, nothing is handled) until it is restarted.Found in 3.4.17, but same code for 3.5/3.6/4.0/master
Solution
Route the three setters through a shared helper (
tm_set_script_route_ref()) that swaps the holder pointer atomically under the transaction reply lock and frees the swapped-out (now private) pointer afterwards. The shm alloc/free are kept outsideLOCK_REPLIES, so the reply lock is never nested around the global shm lock.The reply lock is taken only in
REQUEST_ROUTE, the sole context that can reach a shared cell field concurrently without already holding the reply lock.FAILURE_ROUTEand, withonreply_avp_mode,ONREPLY_ROUTEalready run underLOCK_REPLIESand may call these handlers, so acquiring the non-recursive reply lock there would probably deadlock.An lock free approach would be to skip the update when the transaction already exists in
REQUEST_ROUTE(settingon_replyon an already-created transaction is a no-op). Switch to that if preferred — the current PR keeps existing behavior and only makes the update safe.Builds clean under gcc and clang with
-Werrorand passes the unit-test suite (make test). Let me know if I missed any testing that should be done prior to submitting a PR.Compatibility
No script- or API-level changes; no configuration or migration required. Behavior is unchanged except that concurrent updates of the shared route-ref field are now serialized.
Closing issues
closes #4112