]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_stasis_device_state: Fix refcounting error. 97/2197/3
authorMark Michelson <mmichelson@digium.com>
Thu, 4 Feb 2016 17:39:10 +0000 (11:39 -0600)
committerMark Michelson <mmichelson@digium.com>
Thu, 4 Feb 2016 18:42:39 +0000 (12:42 -0600)
Device state subscription lifetimes were governed by when the
subscription was established and unsubscribed from. However, it is
possible that at the time of unsubscription, there could be device state
events still in flight. When those device state events occur, the device
state callback could attempt to dereference a freed pointer. Crash.

This change ensures that the lifetime of the device state subscription
does not end until the underlying stasis subscription has confirmed that
its final message has been sent.

Change-Id: I25a0f1472894c1a562252fb7129671478e25e9b2

res/res_stasis_device_state.c

index 8a1c230491864689ef70f8c84b0965666f754cf4..5e3d51a07e5cd69b7323a648a13ed4139417568d 100644 (file)
@@ -294,6 +294,12 @@ static void device_state_cb(void *data, struct stasis_subscription *sub,
 {
        struct ast_device_state_message *device_state;
 
+       if (stasis_subscription_final_message(sub, msg)) {
+               /* Remove stasis subscription's reference to device_state_subscription */
+               ao2_ref(data, -1);
+               return;
+       }
+
        if (ast_device_state_message_type() != stasis_message_type(msg)) {
                return;
        }
@@ -330,11 +336,13 @@ static int subscribe_device_state(struct stasis_app *app, void *obj)
                return 0;
        }
 
-       if (!(sub->sub = stasis_subscribe_pool(
-                       ast_device_state_topic(sub->device_name),
-                       device_state_cb, sub))) {
+       sub->sub = stasis_subscribe_pool(ast_device_state_topic(sub->device_name),
+                       device_state_cb, ao2_bump(sub));
+       if (!sub->sub) {
                ast_log(LOG_ERROR, "Unable to subscribe to device %s\n",
                        sub->device_name);
+               /* Reference we added when attempting to stasis_subscribe_pool */
+               ao2_ref(sub, -1);
                return -1;
        }