<p>neels <strong>uploaded patch set #2</strong> to this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/15660">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_fsm_inst_watch()<br><br>I discovered an osmo-msc use-after-free crash from an invalid message, caused<br>by this pattern:<br><br>   void event_action()<br>   {<br>           osmo_fsm_inst_dispatch(foo, FOO_EVENT, NULL);<br>           osmo_fsm_inst_dispatch(bar, BAR_EVENT, NULL);<br>   }<br><br>Usually, FOO_EVENT takes successful action, and afterwards we also notify bar<br>of another event. However, in this particular case FOO_EVENT caused failure,<br>and the immediate error handling directly terminated and deallocated bar.<br>In such cases, dispatching BAR_EVENT causes a use-after-free; this constituted<br>a DoS vector just from sending messages that fail to validate to osmo-msc.<br><br>Instead, introduce this pattern for accessing FSM instances after<br>failure-critical actions, which watches out for a given osmo_fsm_inst's<br>deallocation:<br><br>   void event_action()<br>   {<br>           struct osmo_fsm_inst_watcher watch_bar;<br><br>           osmo_fsm_inst_watch(&watch_bar, bar);<br>           osmo_fsm_inst_dispatch(foo, FOO_EVENT, NULL);<br>           osmo_fsm_inst_unwatch(&watch_bar);<br><br>           if (watch_bar.exists)<br>                   osmo_fsm_inst_dispatch(bar, BAR_EVENT, NULL);<br>   }<br><br>Implementation: at first I had thought of a simple lookup whether bar still is<br>listed in the bar->fsm list of osmo_fsm_inst instances. That worked well, but<br>theoretically, after a deallocation, another FSM may have been allocated,<br>possibly at the exact same memory address. This chance is slim, but<br>nevertheless quite possible. The only fully safe way is to explicitly watch an<br>instance.<br><br>Test: incorporate FSM instance watchers in fsm_dealloc_test.c, with<br>OSMO_ASSERTs verifying that the watchers reflect exactly whether an object is<br>still allocated. Though the test's expected output does not print anything when<br>the osmo_fsm_inst_watchers reflect the expected values, I did verify that the<br>test catches bugs when introduced deliberately.<br><br>Related: Iaa8e3da2969ebb4c78bff11d0d59f01b10f341d7 (osmo-msc),<br>         I790d2172c7c67610915cb74b0766fb18f2795b29 (osmo-mgw)<br>Change-Id: I4d8306488506c60b4c2fc1c4cb3ac04654db9c43<br>---<br>M include/osmocom/core/fsm.h<br>M src/fsm.c<br>M tests/fsm/fsm_dealloc_test.c<br>3 files changed, 116 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/60/15660/2</pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/15660">change 15660</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/15660"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I4d8306488506c60b4c2fc1c4cb3ac04654db9c43 </div>
<div style="display:none"> Gerrit-Change-Number: 15660 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-MessageType: newpatchset </div>