From 607a5d898cc52b3f1b4d45e1e95ed07fe1f7dc32 Mon Sep 17 00:00:00 2001
From: Mark Michelson <mmichelson@digium.com>
Date: Wed, 12 Dec 2012 00:02:31 +0000
Subject: [PATCH] Fix a potential deadlock in chan_sip during transfers.

The issue comes from the fact that transfers may perform
a redirecting update on a channel. The issue is that lock
inversion between the channel and its tech_pvt occurs since
the channel lock is released during the transfer process.

The fix is to move when the redirecting update occurs to a
place where neither the tech_pvt or the channel is locked so
that the two can be locked in the proper order.

(closes issue ASTERISK-20708)
reported by Mark Michelson
patches:
	ASTERISK-20708-3.patch uploaded by Mark Michelson (License #5049)

Tested by:
	Tim Ringenbach at Asteria Solutions Group
........

Merged revisions 377910 from http://svn.asterisk.org/svn/asterisk/branches/11


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@377911 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channels/chan_sip.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index fa70dc807c..793e141794 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -26331,6 +26331,24 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, uint
 		if (!ast_strlen_zero(referred_by)) {
 			pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", referred_by);
 		}
+
+		/* When a call is transferred to voicemail from a Digium phone, there may be
+		 * a Diversion header present in the REFER with an appropriate reason parameter
+		 * set. We need to update the redirecting information appropriately.
+		 */
+		ast_channel_lock(p->owner);
+		sip_pvt_lock(p);
+		ast_party_redirecting_init(&redirecting);
+		memset(&update_redirecting, 0, sizeof(update_redirecting));
+		change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE);
+
+		/* Do not hold the pvt lock during a call that causes an indicate or an async_goto.
+		 * Those functions lock channels which will invalidate locking order if the pvt lock
+		 * is held.*/
+		sip_pvt_unlock(p);
+		ast_channel_unlock(p->owner);
+		ast_channel_update_redirecting(current.chan2, &redirecting, &update_redirecting);
+		ast_party_redirecting_free(&redirecting);
 	}
 
 	sip_pvt_lock(p);
@@ -26378,20 +26396,7 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, uint
 	}
 	ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
 
-	/* When a call is transferred to voicemail from a Digium phone, there may be
-	 * a Diversion header present in the REFER with an appropriate reason parameter
-	 * set. We need to update the redirecting information appropriately.
-	 */
-	ast_party_redirecting_init(&redirecting);
-	memset(&update_redirecting, 0, sizeof(update_redirecting));
-	change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE);
-
-	/* Do not hold the pvt lock during a call that causes an indicate or an async_goto.
-	 * Those functions lock channels which will invalidate locking order if the pvt lock
-	 * is held.*/
 	sip_pvt_unlock(p);
-	ast_channel_update_redirecting(current.chan2, &redirecting, &update_redirecting);
-	ast_party_redirecting_free(&redirecting);
 
 	/* For blind transfers, move the call to the new extensions. For attended transfers on multiple
 	 * servers - generate an INVITE with Replaces. Either way, let the dial plan decided
-- 
GitLab