diff --git a/debian/patches/series b/debian/patches/series index 563103f35..74e958e22 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -35,3 +35,7 @@ sipwise/fix_db_redis_memory_issues.patch sipwise/rtpengine-balancing.patch sipwise/fix_db_redis_manual_key_issue.patch sipwise/tcap_add_tcap_var_extract.patch +## backport from kamailio upstream (5.2) +upstream/0001-tm-free-new-cell-in-case-of-error.patch +upstream/0002-tm-force-free-cell-if-transaction-is-unlinkled.patch +upstream/0003-tm-backup-and-restore-T-and-T_branch-in-t_continue.patch diff --git a/debian/patches/upstream/0001-tm-free-new-cell-in-case-of-error.patch b/debian/patches/upstream/0001-tm-free-new-cell-in-case-of-error.patch new file mode 100644 index 000000000..3badab38e --- /dev/null +++ b/debian/patches/upstream/0001-tm-free-new-cell-in-case-of-error.patch @@ -0,0 +1,32 @@ +From: f94770840029c1c73ab129f4b71fcb0cf146d808 +Author: Daniel-Constantin Mierla +Date: Wed Jun 6 10:24:18 2018 +0200 +Subject: tm: free new tm cell in case of error if it was not referenced + + - part of t_uac_prepare(), reported by GH #1554 +--- +--- a/src/modules/tm/uac.c ++++ b/src/modules/tm/uac.c +@@ -583,11 +583,18 @@ static inline int t_uac_prepare(uac_req_ + + error2: + #ifdef TM_DEL_UNREF +- if (!is_ack) { +- UNREF_FREE(new_cell); +- }else +-#endif ++ if (is_ack) { + free_cell(new_cell); ++ } else { ++ if(atomic_get_int(&new_cell->ref_count)==0) { ++ free_cell(new_cell); ++ } else { ++ UNREF_FREE(new_cell); ++ } ++ } ++#else ++ free_cell(new_cell); ++#endif + error3: + return ret; + } diff --git a/debian/patches/upstream/0002-tm-force-free-cell-if-transaction-is-unlinkled.patch b/debian/patches/upstream/0002-tm-force-free-cell-if-transaction-is-unlinkled.patch new file mode 100644 index 000000000..e640727b4 --- /dev/null +++ b/debian/patches/upstream/0002-tm-force-free-cell-if-transaction-is-unlinkled.patch @@ -0,0 +1,83 @@ +From: 72f5eaeeef0239ebd16a2d645b83e83eb1a2b506 +Author: Daniel-Constantin Mierla +Date: Mon Jun 11 12:36:22 2018 +0200 + + tm: force free cell in UNREF_FREE() if transaction is unlinkled from timers +--- +--- a/src/modules/tm/t_funcs.h ++++ b/src/modules/tm/t_funcs.h +@@ -96,13 +96,18 @@ int send_pr_buffer( struct retr_buf *rb, + + #ifdef TM_DEL_UNREF + +-#define UNREF_FREE(_T_cell) \ ++#define UNREF_FREE(_T_cell, _T_unlinked) \ + do{\ + if (atomic_dec_and_test(&(_T_cell)->ref_count)){ \ + unlink_timers((_T_cell)); \ + free_cell((_T_cell)); \ +- }else \ +- t_stats_delayed_free(); \ ++ }else{ \ ++ if(_T_unlinked){ \ ++ free_cell((_T_cell)); \ ++ }else{ \ ++ t_stats_delayed_free(); \ ++ } \ ++ } \ + }while(0) + + #define UNREF_NOSTATS(_T_cell) \ +--- a/src/modules/tm/timer.c ++++ b/src/modules/tm/timer.c +@@ -648,7 +648,11 @@ ticks_t wait_handler(ticks_t ti, struct + remove_from_hash_table_unsafe(p_cell); + UNLOCK_HASH(p_cell->hash_index); + p_cell->flags |= T_IN_AGONY; +- UNREF_FREE(p_cell); ++ if(t_linked_timers(p_cell)) { ++ UNREF_FREE(p_cell, 0); ++ } else { ++ UNREF_FREE(p_cell, 1); ++ } + ret = 0; + #else /* TM_DEL_UNREF */ + if(p_cell->flags & T_IN_AGONY) { +--- a/src/modules/tm/timer.h ++++ b/src/modules/tm/timer.h +@@ -375,5 +375,24 @@ inline static void unlink_timers(struct + cleanup_localcancel_timers(t); + } + ++inline static int t_linked_timers(tm_cell_t *t) ++{ ++ int i; ++ ++ if(t->uas.response.timer.next!=NULL || t->uas.response.timer.prev!=NULL) { ++ return 1; ++ } ++ for(i = 0; i < t->nr_of_outgoings; i++) { ++ if(t->uac[i].request.timer.next!=NULL ++ || t->uac[i].request.timer.prev!=NULL) { ++ return 1; ++ } ++ if(t->uac[i].local_cancel.timer.next!=NULL ++ || t->uac[i].local_cancel.timer.prev!=NULL) { ++ return 1; ++ } ++ } ++ return 0; ++} + + #endif +--- a/src/modules/tm/uac.c ++++ b/src/modules/tm/uac.c +@@ -589,7 +589,7 @@ error2: + if(atomic_get_int(&new_cell->ref_count)==0) { + free_cell(new_cell); + } else { +- UNREF_FREE(new_cell); ++ UNREF_FREE(new_cell, 0); + } + } + #else diff --git a/debian/patches/upstream/0003-tm-backup-and-restore-T-and-T_branch-in-t_continue.patch b/debian/patches/upstream/0003-tm-backup-and-restore-T-and-T_branch-in-t_continue.patch new file mode 100644 index 000000000..04a6e23e5 --- /dev/null +++ b/debian/patches/upstream/0003-tm-backup-and-restore-T-and-T_branch-in-t_continue.patch @@ -0,0 +1,83 @@ +From: 5fe2a1a1c67b550431dcae3c98701073f7edd953 +Author: Daniel-Constantin Mierla +Date: Mon Jun 11 12:10:16 2018 +0200 + + tm: backup and restore T and T_branch in t_continue() + + - it may be required to cleanup old T states after t_continue() is + finished +--- +--- a/src/modules/tm/t_suspend.c ++++ b/src/modules/tm/t_suspend.c +@@ -166,7 +166,9 @@ int t_suspend(struct sip_msg *msg, + int t_continue_helper(unsigned int hash_index, unsigned int label, + struct action *rtact, str *cbname, str *cbparam) + { +- struct cell *t; ++ tm_cell_t *t; ++ tm_cell_t *backup_T = T_UNDEFINED; ++ int backup_T_branch = T_BR_UNDEFINED; + sip_msg_t *faked_req; + sip_msg_t *brpl; + void *erpl; +@@ -187,13 +189,18 @@ int t_continue_helper(unsigned int hash_ + + cfg_update(); + ++ backup_T = get_t(); ++ backup_T_branch = get_t_branch(); ++ + if (t_lookup_ident(&t, hash_index, label) < 0) { ++ set_t(backup_T, backup_T_branch); + LM_ERR("transaction not found\n"); + return -1; + } + + if (!(t->flags & T_ASYNC_SUSPENDED)) { + LM_WARN("transaction is not suspended [%u:%u]\n", hash_index, label); ++ set_t(backup_T, backup_T_branch); + return -2; + } + +@@ -203,7 +210,7 @@ int t_continue_helper(unsigned int hash_ + * needless to continue */ + UNREF(t); /* t_unref would kill the transaction */ + /* reset T as we have no working T anymore */ +- set_t(T_UNDEFINED, T_BR_UNDEFINED); ++ set_t(backup_T, backup_T_branch); + return 1; + } + +@@ -248,6 +255,7 @@ int t_continue_helper(unsigned int hash_ + t->flags &= ~T_ASYNC_CONTINUE; + UNLOCK_ASYNC_CONTINUE(t); + UNREF(t); /* t_unref would kill the transaction */ ++ set_t(backup_T, backup_T_branch); + return 1; + } + +@@ -309,7 +317,6 @@ int t_continue_helper(unsigned int hash_ + if(keng->froute(faked_req, FAILURE_ROUTE, cbname, + &evname)<0) { + LM_ERR("error running event route kemi callback\n"); +- return -1; + } + } else { + LM_DBG("event callback (%.*s) set, but no cfg engine\n", +@@ -539,7 +546,7 @@ done: + sip_msg_free(brpl); + } + +- ++ set_t(backup_T, backup_T_branch); + return 0; + + kill_trans: +@@ -566,6 +573,7 @@ kill_trans: + /* response handling */ + t_unref(t->uac[branch].reply); + } ++ set_t(backup_T, backup_T_branch); + return ret; + } +