From 44aef0449a92b979c23db7f283f394da10bf6b51 Mon Sep 17 00:00:00 2001 From: George Joseph <gjoseph@digium.com> Date: Fri, 2 Apr 2021 06:21:33 -0600 Subject: [PATCH] bridge_channel_write_frame: Check for NULL channel There is a possibility, when bridge_channel_write_frame() is called, that the bridge_channel->chan will be NULL. The first thing bridge_channel_write_frame() does though is call ast_channel_is_multistream() which had no check for a NULL channel and therefore caused a segfault. Since it's still possible for bridge_channel_write_frame() to write the frame to the other channels in the bridge, we don't want to bail before we call ast_channel_is_multistream() but we can just skip the multi-channel stuff. So... bridge_channel_write_frame() only calls ast_channel_is_multistream() if bridge_channel->chan is not NULL. As a safety measure, ast_channel_is_multistream() now returns false if the supplied channel is NULL. ASTERISK-29379 Reported-by: Vyrva Igor Reported-by: Ross Beer Change-Id: Idfe62dbea8c69813ecfd58e113a6620dc42352ce --- main/bridge_channel.c | 12 ++++++++---- main/channel_internal_api.c | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 3c5e87b574..7e058af3c0 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -657,8 +657,13 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, ast_bridge_channel_lock_bridge(bridge_channel); - /* Map the frame to the bridge. */ - if (ast_channel_is_multistream(bridge_channel->chan)) { + /* + * Map the frame to the bridge. + * We need to lock the bridge_channel to make sure that bridge_channel->chan + * isn't NULL and keep it locked while we do multistream processing. + */ + ast_bridge_channel_lock(bridge_channel); + if (bridge_channel->chan && ast_channel_is_multistream(bridge_channel->chan)) { unmapped_stream_num = frame->stream_num; switch (frame->frametype) { case AST_FRAME_VOICE: @@ -672,12 +677,10 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, frame->stream_num = -1; break; } - ast_bridge_channel_lock(bridge_channel); if (frame->stream_num < (int)AST_VECTOR_SIZE(&bridge_channel->stream_map.to_bridge)) { frame->stream_num = AST_VECTOR_GET( &bridge_channel->stream_map.to_bridge, frame->stream_num); if (0 <= frame->stream_num) { - ast_bridge_channel_unlock(bridge_channel); break; } } @@ -703,6 +706,7 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, unmapped_stream_num = -1; frame->stream_num = -1; } + ast_bridge_channel_unlock(bridge_channel); deferred = bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame); if (deferred) { diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index fb62da5a95..a84534aabf 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -1642,7 +1642,7 @@ void ast_channel_internal_swap_stream_topology(struct ast_channel *chan1, int ast_channel_is_multistream(struct ast_channel *chan) { - return (chan->tech && chan->tech->read_stream && chan->tech->write_stream); + return (chan && chan->tech && chan->tech->read_stream && chan->tech->write_stream); } struct ast_channel_snapshot *ast_channel_snapshot(const struct ast_channel *chan) -- GitLab