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 cb057a6381)
This commit is contained in:
George Joseph 2024-02-09 09:15:13 -07:00 committed by Asterisk Development Team
parent 6df5fbee65
commit f770c9c92c
2 changed files with 21 additions and 3 deletions

View 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;

View 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);