chan_dahdi/sig_pri: Fix crash on ISDN call hangup collision.
authorRichard Mudgett <rmudgett@digium.com>
Tue, 12 May 2015 22:34:45 +0000 (17:34 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 12 May 2015 22:43:35 +0000 (17:43 -0500)
If an ISDN call is hungup by both sides at the same time a crash could
happen.

* Added missing NULL checks for the owner channel after calling
pri_queue_pvt_cause_data() in two places.  Code after those calls need to
check the owner channel pointer for NULL before use because
pri_queue_pvt_cause_data() needs to do deadlock avoidance to lock the
owner and the owner may get hung up.

ASTERISK-21893 #close
Reported by:  Alexandr Gordeev

Change-Id: Ica3e266ebc7a894b41d762326f08653e1904bb9a

channels/sig_pri.c

index c58a3f3..71e7e23 100644 (file)
@@ -7090,10 +7090,11 @@ static void *pri_dchannel(void *vpri)
                                                break;
                                        }
                                        if (pri->pvts[chanpos]->owner) {
-                                               int do_hangup = 0;
-
                                                snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP (%d)", e->hangup.cause);
                                                pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->hangup.cause);
+                                       }
+                                       if (pri->pvts[chanpos]->owner) {
+                                               int do_hangup = 0;
 
                                                /* Queue a BUSY instead of a hangup if our cause is appropriate */
                                                ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
@@ -7234,10 +7235,11 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                if (pri->pvts[chanpos]->owner) {
-                                       int do_hangup = 0;
-
                                        snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP_REQ (%d)", e->hangup.cause);
                                        pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->hangup.cause);
+                               }
+                               if (pri->pvts[chanpos]->owner) {
+                                       int do_hangup = 0;
 
                                        ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
                                        switch (ast_channel_state(pri->pvts[chanpos]->owner)) {