From 642f096ed2ba9ea5b53696197f863a7e586b88c6 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 26 Apr 2017 15:23:24 +0200 Subject: [PATCH] dialog: more safety checks to detect if dialog is gone after event route execution - avoid execution of script callbacks for event route - related to GH #1059 and #1069 - backport of a8b7f94a5c305e14313d5528792f9ca6518d5969 (cherry picked from commit d95f09670a0d3d0c997c7f1c94eb66bdd4c4da0f) --- modules/dialog/dlg_handlers.c | 43 +++++++++++++++++++++++++++++++++++-------- modules/dialog/dlg_hash.h | 2 +- modules/dialog/dlg_profile.c | 4 ++++ modules/dialog/dlg_var.c | 12 ++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) --- a/modules/dialog/dlg_handlers.c +++ b/modules/dialog/dlg_handlers.c @@ -455,7 +455,11 @@ static void dlg_onreply(struct cell* t, event = DLG_EVENT_RPL3xx; next_state_dlg( dlg, event, &old_state, &new_state, &unref); - dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state); + if(dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, + new_state)<0) { + /* dialog is gone */ + return; + } if (new_state==DLG_STATE_EARLY) { run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); @@ -1315,7 +1319,10 @@ void dlg_onroute(struct sip_msg* req, st CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts; CURR_DLG_STATUS = new_state; - dlg_run_event_route(dlg, req, old_state, new_state); + if(dlg_run_event_route(dlg, req, old_state, new_state)<0) { + /* dialog is gone */ + return; + } dlg0 = dlg_lookup(h_entry, h_id); if (dlg0==0) { @@ -1519,7 +1526,10 @@ void dlg_ontimeout(struct dlg_tl *tl) timeout_cb = (void *)CONFIRMED_DIALOG_STATE; } - dlg_run_event_route(dlg, NULL, old_state, new_state); + if(dlg_run_event_route(dlg, NULL, old_state, new_state)<0) { + /* dialog is gone */ + return; + } if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n", @@ -1607,17 +1617,22 @@ int pv_get_dlg_status(struct sip_msg *ms /*! * \brief Execute event routes based on new state * + * - returns: -1 if dialog doesn't exist after event route execution + * 0 if all ok */ -void dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate) +int dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate) { sip_msg_t *fmsg; int rt; int bkroute; + int h_entry=0; + int h_id=0; + dlg_cell_t *dlg0 = NULL; if(dlg==NULL) - return; + return -1; if(ostate==nstate) - return; + return 0; rt = -1; if(nstate==DLG_STATE_CONFIRMED_NA) { @@ -1630,7 +1645,7 @@ void dlg_run_event_route(dlg_cell_t *dlg } if(rt==-1 || event_rt.rlist[rt]==NULL) - return; + return 0; if(msg==NULL) fmsg = faked_msg_next(); @@ -1640,6 +1655,8 @@ void dlg_run_event_route(dlg_cell_t *dlg if (exec_pre_script_cb(fmsg, LOCAL_CB_TYPE)>0) { dlg_ref(dlg, 1); + h_entry = dlg->h_entry; + h_id = dlg->h_id; dlg_set_ctx_iuid(dlg); LM_DBG("executing event_route %d on state %d\n", rt, nstate); bkroute = get_route_type(); @@ -1647,9 +1664,19 @@ void dlg_run_event_route(dlg_cell_t *dlg run_top_route(event_rt.rlist[rt], fmsg, 0); dlg_reset_ctx_iuid(); exec_post_script_cb(fmsg, LOCAL_CB_TYPE); - dlg_unref(dlg, 1); set_route_type(bkroute); + /* re-lookup the dialog, execution of the route could take long time */ + dlg0 = dlg_lookup(h_entry, h_id); + if (dlg0==0) { + LM_ALERT("after event route - dialog not found [%u:%u] (%d/%d) (%p)\n", + h_entry, h_id, ostate, nstate, dlg); + return -1; + } else { + dlg_release(dlg0); + dlg_unref(dlg, 1); + } } + return 0; } int dlg_manage(sip_msg_t *msg) --- a/modules/dialog/dlg_hash.h +++ b/modules/dialog/dlg_hash.h @@ -582,7 +582,7 @@ static inline int match_downstream_dialo /*! * */ -void dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate); +int dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate); int dlg_ka_add(dlg_cell_t *dlg); --- a/modules/dialog/dlg_profile.c +++ b/modules/dialog/dlg_profile.c @@ -437,6 +437,10 @@ int profile_cleanup( struct sip_msg *msg { dlg_cell_t *dlg; + if(get_route_type()==LOCAL_ROUTE) { + return 1; + } + current_dlg_msg_id = 0; current_dlg_msg_pid = 0; dlg = dlg_get_ctx_dialog(); --- a/modules/dialog/dlg_var.c +++ b/modules/dialog/dlg_var.c @@ -47,6 +47,9 @@ int msg_id; int dlg_cfg_cb(sip_msg_t *msg, unsigned int flags, void *cbp) { dlg_cell_t *dlg; + if(get_route_type()==LOCAL_ROUTE) { + return 1; + } if(flags&POST_SCRIPT_CB) { dlg = dlg_get_ctx_dialog(); if(dlg!=NULL) { @@ -76,6 +79,9 @@ int dlg_cfg_cb(sip_msg_t *msg, unsigned int cb_dlg_cfg_reset(sip_msg_t *msg, unsigned int flags, void *cbp) { + if(get_route_type()==LOCAL_ROUTE) { + return 1; + } memset(&_dlg_ctx, 0, sizeof(dlg_ctx_t)); return 1; @@ -83,6 +89,9 @@ int cb_dlg_cfg_reset(sip_msg_t *msg, uns int cb_dlg_locals_reset(sip_msg_t *msg, unsigned int flags, void *cbp) { + if(get_route_type()==LOCAL_ROUTE) { + return 1; + } LM_DBG("resetting the local dialog shortcuts on script callback: %u\n", flags); cb_dlg_cfg_reset(msg, flags, cbp); cb_profile_reset(msg, flags, cbp); @@ -918,6 +927,9 @@ dlg_ctx_t* dlg_get_dlg_ctx(void) int spiral_detect_reset(struct sip_msg *foo, unsigned int flags, void *bar) { + if(get_route_type()==LOCAL_ROUTE) { + return 1; + } spiral_detected = -1; return 0;