From 39d55550cee4a18f6cf9f7790b0c8561c7edd353 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 26 Jul 2020 16:56:20 +0200 Subject: [PATCH] Use-after-free on freeing FSM Functions associated with a state transition are called with the FSM mutex unlocked and this gave dds_security_fsm_free a chance of freeing the memory while the FSM thread was still accessing the state. This marks the FSM as "busy" while the mutex is unlocked for the invoking of this functions and waits with freeing the memory until it is no longer busy. Signed-off-by: Erik Boasson --- src/security/core/src/dds_security_fsm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/security/core/src/dds_security_fsm.c b/src/security/core/src/dds_security_fsm.c index e2b9436..03bd287 100644 --- a/src/security/core/src/dds_security_fsm.c +++ b/src/security/core/src/dds_security_fsm.c @@ -50,6 +50,7 @@ struct dds_security_fsm struct dds_security_fsm *next_fsm; struct dds_security_fsm *prev_fsm; bool deleting; + bool busy; struct dds_security_fsm_control *control; const dds_security_fsm_transition *transitions; uint32_t size; @@ -245,6 +246,7 @@ static void fsm_state_change (struct dds_security_fsm_control *control, struct f fsm->current = fsm->transitions[i].end; set_state_timer (fsm); + fsm->busy = true; ddsrt_mutex_unlock (&control->lock); if (fsm->transitions[i].func) @@ -253,6 +255,8 @@ static void fsm_state_change (struct dds_security_fsm_control *control, struct f fsm->current->func (fsm, fsm->arg); ddsrt_mutex_lock (&control->lock); + fsm->busy = false; + if (!fsm->deleting) fsm_check_auto_state_change (fsm); else @@ -447,6 +451,7 @@ struct dds_security_fsm * dds_security_fsm_create (struct dds_security_fsm_contr fsm->overall_timeout_event.endtime = DDS_NEVER; fsm->overall_timeout_event.fsm = fsm; fsm->deleting = false; + fsm->busy = false; fsm->next_fsm = NULL; fsm->prev_fsm = NULL; fsm->control = control; @@ -490,6 +495,8 @@ static void fsm_delete (struct dds_security_fsm_control *control, struct dds_sec { remove_fsm_from_list (control, fsm); fsm_deactivate (control, fsm); + while (fsm->busy) + ddsrt_cond_wait (&control->cond, &control->lock); ddsrt_free(fsm); }