From f770c9c92c03ceba971cd8ffa24fec1d2f81c092 Mon Sep 17 00:00:00 2001 From: George Joseph Date: Fri, 9 Feb 2024 09:15:13 -0700 Subject: [PATCH] pjsip show channelstats: Prevent possible segfault when faxing Under rare circumstances, it's possible for the original audio session in the active_media_state default_session to be corrupted instead of removed when switching to the t38/image media session during fax negotiation. This can cause a segfault when a "pjsip show channelstats" attempts to print that audio media session's rtp statistics. In these cases, the active_media_state topology is correctly showing only a single t38/image stream so we now check that there's an audio stream in the topology before attempting to use the audio media session to get the rtp statistics. Resolves: #592 (cherry picked from commit cb057a6381f61be5009e48ddaa872c9295724811) --- channels/pjsip/cli_commands.c | 20 +++++++++++++++++--- main/rtp_engine.c | 4 ++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/channels/pjsip/cli_commands.c b/channels/pjsip/cli_commands.c index 734b0e28e4..799a7beab5 100644 --- a/channels/pjsip/cli_commands.c +++ b/channels/pjsip/cli_commands.c @@ -343,6 +343,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags) struct ast_sip_session *session; struct ast_sip_session_media *media; struct ast_rtp_instance_stats stats; + struct ast_stream *stream; char *print_name = NULL; char *print_time = alloca(32); char codec_in_use[7]; @@ -359,16 +360,29 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags) cpvt = ast_channel_tech_pvt(channel); session = cpvt ? cpvt->session : NULL; - if (!session) { + + if (!session + || !session->active_media_state + || !session->active_media_state->topology) { ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name); ast_channel_unlock(channel); ao2_cleanup(channel); return 0; } + stream = ast_stream_topology_get_first_stream_by_type( + session->active_media_state->topology, AST_MEDIA_TYPE_AUDIO); + + if (!stream) { + ast_str_append(&context->output_buffer, 0, " %s no audio streams\n", snapshot->base->name); + ast_channel_unlock(channel); + ao2_cleanup(channel); + return 0; + } + media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]; - if (!media || !media->rtp) { - ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name); + if (!media || media->type != AST_MEDIA_TYPE_AUDIO || !media->rtp) { + ast_str_append(&context->output_buffer, 0, " %s corrupted default audio session\n", snapshot->base->name); ast_channel_unlock(channel); ao2_cleanup(channel); return 0; diff --git a/main/rtp_engine.c b/main/rtp_engine.c index e648a2b9ca..94141d08bd 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -2460,6 +2460,10 @@ int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp { int res; + if (!instance || !instance->engine || !stats) { + return -1; + } + if (instance->engine->get_stat) { ao2_lock(instance); res = instance->engine->get_stat(instance, stats, stat);