From a0bbd60c366ed0137ee432ea2f23c0a1f75019c4 Mon Sep 17 00:00:00 2001 From: Bogdan-Andrei Iancu Date: Fri, 30 Jun 2023 12:17:42 +0300 Subject: [PATCH] [b2b_logic] fix crash on tracing expired b2b tuples When a tuple expires via timer, be sure to provide a processing context, otherwise the tracer (if enabled) will simply crash. As part of the fix, two new helper functions were added for pushing and poping new processing contexts - these are to be reused by some prev similar fix on uac_registrant. Related to #3110 Many thanks to @vtzan for helping with the troubleshooting and testing (cherry picked from commit 2a3eb1e2a8e609b6b7b37074c1d1fd4dffc76f5e) --- context.c | 39 +++++++++++++++++++++++++++++++++++ context.h | 6 ++++++ modules/b2b_logic/b2b_logic.c | 33 +++++++++++++++++++---------- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/context.c b/context.c index 85e651273c0..e98070847ba 100644 --- a/context.c +++ b/context.c @@ -143,6 +143,45 @@ int ensure_global_context(void) } +#define CTX_STACK_SIZE 8 +static context_p ctx_stack[CTX_STACK_SIZE]; +static unsigned int ctx_stack_idx = 0; + +int push_new_global_context(void) +{ + if (ctx_stack_idx==CTX_STACK_SIZE) { + LM_ERR("too many stacked contexts (%d)\n",ctx_stack_idx); + return -1; + } + + ctx_stack[ctx_stack_idx++] = current_processing_ctx; + + current_processing_ctx = context_alloc(CONTEXT_GLOBAL); + if (!current_processing_ctx) { + LM_ERR("oom\n"); + current_processing_ctx = ctx_stack[--ctx_stack_idx]; + return -1; + } + + memset(current_processing_ctx, 0, context_size(CONTEXT_GLOBAL)); + return 0; +} + +int pop_pushed_global_context(void) +{ + if (ctx_stack_idx==0) { + LM_ERR("nothing to pop form the stack\n"); + return -1; + } + + context_destroy(CONTEXT_GLOBAL, current_processing_ctx); + context_free(current_processing_ctx); + + current_processing_ctx = ctx_stack[--ctx_stack_idx]; + return 0; +} + + void clear_global_context(void) { if (current_processing_ctx) { diff --git a/context.h b/context.h index f5be91b4ccd..bc1d7eca538 100644 --- a/context.h +++ b/context.h @@ -86,6 +86,12 @@ context_p context_alloc(enum osips_context type); int ensure_global_context(void); +/* pushes or pops a context level from internal stack + */ +int push_new_global_context(void); +int pop_pushed_global_context(void); + + /* free and reset the global context */ void clear_global_context(void); diff --git a/modules/b2b_logic/b2b_logic.c b/modules/b2b_logic/b2b_logic.c index bfca40298d1..53530772c71 100644 --- a/modules/b2b_logic/b2b_logic.c +++ b/modules/b2b_logic/b2b_logic.c @@ -682,11 +682,12 @@ void b2bl_db_timer_update(unsigned int ticks, void* param) b2b_logic_dump(0); } -static void term_entity(b2bl_entity_id_t *entity, int hash_index) +static void term_entity(b2bl_entity_id_t *entity, int hash_index, str *key) { str bye = {BYE, BYE_LEN}; b2b_req_data_t req_data; b2b_rpl_data_t rpl_data; + struct b2b_context *ctx; if (entity->type == B2B_SERVER && entity->state != B2BL_ENT_CONFIRMED) { @@ -710,12 +711,22 @@ static void term_entity(b2bl_entity_id_t *entity, int hash_index) entity->key.s); b2bl_htable[hash_index].locked_by = -1; } else { - memset(&req_data, 0, sizeof(b2b_req_data_t)); - PREP_REQ_DATA(entity); - req_data.method =&bye; - b2bl_htable[hash_index].locked_by = process_no; - b2b_api.send_request(&req_data); - b2bl_htable[hash_index].locked_by = -1; + if ( key && ( !push_new_global_context() || + (ctx=b2b_api.get_context())==NULL || + pkg_str_dup(&ctx->b2bl_key, key)==0 ) + ) { + LM_ERR("preparing ctx for request failed, entity [%.*s]\n", + entity->key.len, entity->key.s); + } else { + memset(&req_data, 0, sizeof(b2b_req_data_t)); + PREP_REQ_DATA(entity); + req_data.method =&bye; + b2bl_htable[hash_index].locked_by = process_no; + b2b_api.send_request(&req_data); + b2bl_htable[hash_index].locked_by = -1; + if (key) + pop_pushed_global_context(); + } } } @@ -741,10 +752,10 @@ void b2bl_clean(unsigned int ticks, void* param) if(tuple->bridge_entities[0] && tuple->bridge_entities[1] && !tuple->to_del) { if(!tuple->bridge_entities[0]->disconnected) - term_entity(tuple->bridge_entities[0], i); + term_entity(tuple->bridge_entities[0], i, tuple->key); if(!tuple->bridge_entities[1]->disconnected) - term_entity(tuple->bridge_entities[1], i); + term_entity(tuple->bridge_entities[1], i, tuple->key); } b2bl_delete(tuple, i, 1, tuple->repl_flag != TUPLE_REPL_RECV); } @@ -1206,12 +1217,12 @@ static mi_response_t *mi_b2b_terminate_call(const mi_params_t *params, if(tuple->bridge_entities[0] && tuple->bridge_entities[1] && !tuple->to_del) { if(!tuple->bridge_entities[0]->disconnected) { - term_entity(tuple->bridge_entities[0], hash_index); + term_entity(tuple->bridge_entities[0], hash_index, &key); tuple->bridge_entities[0]->disconnected = 1; } if(!tuple->bridge_entities[1]->disconnected) { - term_entity(tuple->bridge_entities[1], hash_index); + term_entity(tuple->bridge_entities[1], hash_index, &key); tuple->bridge_entities[1]->disconnected = 1; } }