From b6d36124cd33c24dae8b4a110008e31d63447972 Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Tue, 11 Dec 2012 23:59:09 +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 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@377910 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 e286705d94..9abd9bc8c4 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -26144,6 +26144,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); @@ -26191,20 +26209,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 -- 2.47.2