From df7cb6b30b7af0d0bfc59f7843081b9c2125ef6e Mon Sep 17 00:00:00 2001 From: Mark Michelson <mmichelson@digium.com> Date: Mon, 14 Apr 2008 16:25:09 +0000 Subject: [PATCH] Merged revisions 114112 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r114112 | mmichelson | 2008-04-14 11:24:22 -0500 (Mon, 14 Apr 2008) | 9 lines If the datastore has been moved to another channel due to a masquerade, then freeing the datastore here causes an eventual double free when the new channel hangs up. We should only free the datastore if we were able to successfully remove it from the channel we are referencing (i.e. the datastore was not moved). (closes issue #12359) Reported by: pguido ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@114113 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_dial.c | 10 ++++++++-- apps/app_queue.c | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/app_dial.c b/apps/app_dial.c index 9c2664aa6b..6d0c6a6e7f 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1600,8 +1600,14 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags time(&start_time); peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result); - ast_channel_datastore_remove(chan, datastore); - ast_channel_datastore_free(datastore); + /* The ast_channel_datastore_remove() function could fail here if the + * datastore was moved to another channel during a masquerade. If this is + * the case, don't free the datastore here because later, when the channel + * to which the datastore was moved hangs up, it will attempt to free this + * datastore again, causing a crash + */ + if (!ast_channel_datastore_remove(chan, datastore)) + ast_channel_datastore_free(datastore); if (!peer) { if (result) { res = result; diff --git a/apps/app_queue.c b/apps/app_queue.c index 7f01445df5..aef06aa2d6 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3252,8 +3252,13 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce if (use_weight) ao2_unlock(queues); lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed); - if (datastore) { - ast_channel_datastore_remove(qe->chan, datastore); + /* The ast_channel_datastore_remove() function could fail here if the + * datastore was moved to another channel during a masquerade. If this is + * the case, don't free the datastore here because later, when the channel + * to which the datastore was moved hangs up, it will attempt to free this + * datastore again, causing a crash + */ + if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) { ast_channel_datastore_free(datastore); } ao2_lock(qe->parent); -- GitLab