]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
segfault after SPINLOCK schedule delete
authorDavid Vossel <dvossel@digium.com>
Mon, 29 Jun 2009 17:04:04 +0000 (17:04 +0000)
committerDavid Vossel <dvossel@digium.com>
Mon, 29 Jun 2009 17:04:04 +0000 (17:04 +0000)
Using the SPINLOCK schedule delete macro can result in the iax_pvt lock
being given up.  This makes it possible for the iax_pvt to dissappear
when we thought we held the mutex the entire time.  To resolve this, the
iax_pvt's ref count is incremented.

(closes issue #15377)
Reported by: aragon
Patches:
      iax_spin_issue_1.4.diff uploaded by dvossel (license 671)
Tested by: aragon, dvossel

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@204067 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c

index a75d9b6d5630dda759be56db010b840cf86f6d50..fa178245393a6b7d52a15946e4693dcd86060556 100644 (file)
@@ -1358,10 +1358,20 @@ retry:
                        goto retry;
                }
        }
-       if (!owner && iaxs[callno]) {
-               AST_SCHED_DEL_SPINLOCK(sched, iaxs[callno]->lagid, &iaxsl[callno]);
-               AST_SCHED_DEL_SPINLOCK(sched, iaxs[callno]->pingid, &iaxsl[callno]);
-               iaxs[callno] = NULL;
+
+       /* SPINLOCK gives up the pvt lock so the scheduler and iax2_pvt don't deadlock. Since we
+        * give up the pvt lock, the pvt could be destroyed from underneath us. To guarantee
+        * the pvt stays around, a ref count is added to it. */
+       if (!owner && pvt) {
+               ao2_ref(pvt, +1);
+               AST_SCHED_DEL_SPINLOCK(sched, pvt->lagid, &iaxsl[pvt->callno]);
+               AST_SCHED_DEL_SPINLOCK(sched, pvt->pingid, &iaxsl[pvt->callno]);
+               ao2_ref(pvt, -1);
+               if (iaxs[callno]) {
+                       iaxs[callno] = NULL;
+               } else {
+                       pvt = NULL;
+               }
        }
 
        if (pvt) {