]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
pjsip show channelstats: Prevent possible segfault when faxing
authorGeorge Joseph <gjoseph@sangoma.com>
Fri, 9 Feb 2024 16:15:13 +0000 (09:15 -0700)
committerAsterisk Development Team <asteriskteam@digium.com>
Thu, 7 Mar 2024 14:18:41 +0000 (14:18 +0000)
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 adcfbcd50ea1b05580b3a6ee4c7ffbd09411ebb0)

channels/pjsip/cli_commands.c
main/rtp_engine.c

index 734b0e28e4f21625b3f3d7a10b92977f45e8fcbf..799a7beab5a3b78e03163176e5bd66af49038abb 100644 (file)
@@ -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;
index 8c513fd9f002101ad8c724e933025b220c75faa5..7009ad73fa9a7395b4916c027d5ee654aa2d637d 100644 (file)
@@ -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);