From e55372f63e85a73f33ccf206607576310ec7f663 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Mon, 24 Apr 2017 17:17:45 +0200 Subject: [PATCH] TT#14953 dialog: more safety checks Change-Id: I22e8c4ad135777147438e79128d816a30fdcf844 --- debian/patches/series | 1 + ...ty-checks-to-detect-if-dialog-is-gon.patch | 188 ++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 debian/patches/upstream/dialog-more-safety-checks-to-detect-if-dialog-is-gon.patch diff --git a/debian/patches/series b/debian/patches/series index a645fa0d2..6306b25b1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -19,6 +19,7 @@ upstream/0037-tls-do-kerberos-and-zlib-init-checks-only-for-libssl.patch upstream/pv-new-function-pv_evalx-dst-fmt.patch upstream/pv_trans_cfg_line.patch upstream/dialog-check-if-dialog-exists-after-event-route-exec.patch +upstream/dialog-more-safety-checks-to-detect-if-dialog-is-gon.patch # ## no_lib64_on_64_bits.patch diff --git a/debian/patches/upstream/dialog-more-safety-checks-to-detect-if-dialog-is-gon.patch b/debian/patches/upstream/dialog-more-safety-checks-to-detect-if-dialog-is-gon.patch new file mode 100644 index 000000000..a91017c79 --- /dev/null +++ b/debian/patches/upstream/dialog-more-safety-checks-to-detect-if-dialog-is-gon.patch @@ -0,0 +1,188 @@ +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;