From 98d10d0a1612220d1aeaa28c0dcc025844714902 Mon Sep 17 00:00:00 2001
From: "Joshua C. Colp" <jcolp@sangoma.com>
Date: Thu, 12 Mar 2020 11:22:06 -0300
Subject: [PATCH] audiohook: Don't allow audiohooks to attach to hung up
 channels.

Given a scenario where MixMonitor was initiated over AMI it
was possible for the channel and MixMonitor thread to remain
alive past hang up of the channel. This scenario required
the AMI initiated MixMonitor to retrieve the channel, a
hangup to occur on the channel in another thread, and then
for MixMonitor to actually start. If this occurred the
MixMonitor thread would remain alive indefinitely and
the channel reference would remain.

This change ensures that audiohooks are never able to
be attached to channels that have been hung up. An
additional fix has also been done in app_mixmonitor to
properly release the channel reference if this occurs.

ASTERISK-28780

Change-Id: I8044c06daa06f0f16607788c596f55623be26f58
---
 apps/app_mixmonitor.c | 1 +
 main/audiohook.c      | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index 9911bc4ecc..bb1bc51d0c 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -990,6 +990,7 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
 	if (startmon(chan, &mixmonitor->audiohook)) {
 		ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
 			mixmonitor_spy_type, ast_channel_name(chan));
+		ast_autochan_destroy(mixmonitor->autochan);
 		ast_audiohook_destroy(&mixmonitor->audiohook);
 		mixmonitor_free(mixmonitor);
 		return -1;
diff --git a/main/audiohook.c b/main/audiohook.c
index 4db32ea7c0..ed16897be0 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -502,6 +502,15 @@ int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audioho
 {
 	ast_channel_lock(chan);
 
+	/* Don't allow an audiohook to be attached to a channel that is already hung up.
+	 * The hang up process is what actually notifies the audiohook that it should
+	 * stop.
+	 */
+	if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)) {
+		ast_channel_unlock(chan);
+		return -1;
+	}
+
 	if (!ast_channel_audiohooks(chan)) {
 		struct ast_audiohook_list *ahlist;
 		/* Whoops... allocate a new structure */
-- 
GitLab