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 <eb@ilities.com>
This commit is contained in:
parent
79773729d6
commit
39d55550ce
1 changed files with 7 additions and 0 deletions
|
@ -50,6 +50,7 @@ struct dds_security_fsm
|
||||||
struct dds_security_fsm *next_fsm;
|
struct dds_security_fsm *next_fsm;
|
||||||
struct dds_security_fsm *prev_fsm;
|
struct dds_security_fsm *prev_fsm;
|
||||||
bool deleting;
|
bool deleting;
|
||||||
|
bool busy;
|
||||||
struct dds_security_fsm_control *control;
|
struct dds_security_fsm_control *control;
|
||||||
const dds_security_fsm_transition *transitions;
|
const dds_security_fsm_transition *transitions;
|
||||||
uint32_t size;
|
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;
|
fsm->current = fsm->transitions[i].end;
|
||||||
set_state_timer (fsm);
|
set_state_timer (fsm);
|
||||||
|
|
||||||
|
fsm->busy = true;
|
||||||
ddsrt_mutex_unlock (&control->lock);
|
ddsrt_mutex_unlock (&control->lock);
|
||||||
|
|
||||||
if (fsm->transitions[i].func)
|
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);
|
fsm->current->func (fsm, fsm->arg);
|
||||||
|
|
||||||
ddsrt_mutex_lock (&control->lock);
|
ddsrt_mutex_lock (&control->lock);
|
||||||
|
fsm->busy = false;
|
||||||
|
|
||||||
if (!fsm->deleting)
|
if (!fsm->deleting)
|
||||||
fsm_check_auto_state_change (fsm);
|
fsm_check_auto_state_change (fsm);
|
||||||
else
|
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.endtime = DDS_NEVER;
|
||||||
fsm->overall_timeout_event.fsm = fsm;
|
fsm->overall_timeout_event.fsm = fsm;
|
||||||
fsm->deleting = false;
|
fsm->deleting = false;
|
||||||
|
fsm->busy = false;
|
||||||
fsm->next_fsm = NULL;
|
fsm->next_fsm = NULL;
|
||||||
fsm->prev_fsm = NULL;
|
fsm->prev_fsm = NULL;
|
||||||
fsm->control = control;
|
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);
|
remove_fsm_from_list (control, fsm);
|
||||||
fsm_deactivate (control, fsm);
|
fsm_deactivate (control, fsm);
|
||||||
|
while (fsm->busy)
|
||||||
|
ddsrt_cond_wait (&control->cond, &control->lock);
|
||||||
ddsrt_free(fsm);
|
ddsrt_free(fsm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue