From fa36f9c01b654fc86b59bee52d6f3019e98d6ac7 Mon Sep 17 00:00:00 2001
From: Richard Mudgett <rmudgett@digium.com>
Date: Wed, 27 Dec 2017 22:36:58 -0600
Subject: [PATCH] bridge_native_rtp.c: Fix reentrancy framehook crash.

If two channels enter different native rtp bridges at the same time it is
possible that the framehook interface data pointer can be corrupted
because the struct variable was declared static.

* Fixed the reentrancy corruption by changing the framehook interface
struct static variable to a stack local variable.

* Moved the hook.data assignment outside of the channel lock.  It did not
need the lock's protection.  It probably was giving a false sense of
security.

The testsuite
channels/pjsip/basic_calls/two_parties/nominal/alice_initiated/bob_hangs_up
test caught this with MALLOC_DEBUG and DO_CRASH enabled.

Change-Id: If9e35b97d19209b0f984941c1d8eb5f7c55eea91
---
 bridges/bridge_native_rtp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c
index edbfe5858e..e07f7faccb 100644
--- a/bridges/bridge_native_rtp.c
+++ b/bridges/bridge_native_rtp.c
@@ -753,7 +753,7 @@ static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
 static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
 {
 	struct native_rtp_bridge_channel_data *data = bridge_channel->tech_pvt;
-	static struct ast_framehook_interface hook = {
+	struct ast_framehook_interface hook = {
 		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
 		.event_cb = native_rtp_framehook,
 		.destroy_cb = __ao2_cleanup,
@@ -771,9 +771,10 @@ static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_
 	ast_debug(2, "Bridge '%s'.  Attaching hook data %p to '%s'\n",
 		bridge_channel->bridge->uniqueid, data, ast_channel_name(bridge_channel->chan));
 
-	ast_channel_lock(bridge_channel->chan);
 	/* We're giving 1 ref to the framehook and keeping the one from the alloc for ourselves */
 	hook.data = ao2_bump(data->hook_data);
+
+	ast_channel_lock(bridge_channel->chan);
 	data->hook_data->id = ast_framehook_attach(bridge_channel->chan, &hook);
 	ast_channel_unlock(bridge_channel->chan);
 	if (data->hook_data->id < 0) {
-- 
GitLab