From ee7d72eb72f3a7fc9864e47c3264a353af4a80c8 Mon Sep 17 00:00:00 2001 From: George Joseph <gjoseph@digium.com> Date: Mon, 30 Dec 2019 10:04:23 -0700 Subject: [PATCH] sig_pri: Fix deadlock caused by sig_pri_queue_hangup The change to add setting hangupsource to sig_pri_queue_hangup() made in https://gerrit.asterisk.org/c/asterisk/+/12857 casued deadlocks when a hangup request was received from the core at the same time a hanguprequest was received from the remote end via the D channel. Although the PRI's channel private structure was being unlocked before setting the hangupsource, the PRI's own lock was still being held during the process. If channel actions were also coming from the core, a deadlock on the PRI could result. This deadlock could then escalate to the entire DAHDI subsystem via DAHDI's global interface list lock, especially if someone used the PRI CLI commands. Fix: * We now unlock the PRI as well as the PRI's channel private structure before setting the hangupsource, then relock both afterwards. ASTERISK-28605 Reported by: Dirk Wendland Change-Id: Id74aaa5d4e3746063dbe9deed188eb65193cb9c9 --- channels/sig_pri.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/channels/sig_pri.c b/channels/sig_pri.c index 4c70c6beaa..4bd5a5191f 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -1387,6 +1387,10 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas * \note Assumes the pri->lock is already obtained. * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained. * + * \note The unlocking/locking sequence now present has been stress tested + * without deadlocks. Please don't change it without consulting + * core development team members. + * * \return Nothing */ static void sig_pri_queue_hangup(struct sig_pri_span *pri, int chanpos) @@ -1404,9 +1408,11 @@ static void sig_pri_queue_hangup(struct sig_pri_span *pri, int chanpos) ast_queue_hangup(owner); ast_channel_unlock(owner); - /* Tell the CDR this DAHDI channel hung up */ sig_pri_unlock_private(pri->pvts[chanpos]); + ast_mutex_unlock(&pri->lock); + /* Tell the CDR this DAHDI channel hung up */ ast_set_hangupsource(owner, ast_channel_name(owner), 0); + ast_mutex_lock(&pri->lock); sig_pri_lock_private(pri->pvts[chanpos]); ao2_ref(owner, -1); -- GitLab