summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2015-04-30 15:20:43 -0500
committerMark Michelson <mmichelson@digium.com>2015-04-30 15:42:01 -0500
commit077979618b5a472c4bd3612680f71275a18d3841 (patch)
tree92ef416e175610d387bc9470351e2a30f07ff4cb /main
parent415a0d0745f8ecb0c05e993e0b28b9e79f982cdf (diff)
Prevent potential crash on blond transfer.
Scenario: Alice calls Bob. Bob performs a blond transfer to Carol. Carol rejects the incoming call (or some other immediate circumstance causes Carol not to answer the call) What occurs in this case is that when the bridge between Alice and Bob breaks, Alice is told to masquerade into Bob's channel that had placed the call to Carol. The actual masquerade goes down without a hitch. However, a channel fixup callback that attempts to publish dial events over Stasis has a crash. The reason for this crash is that the datastore on Bob's channel that placed the outbound call to Carol only had a bare pointer to Carol's channel. Since Carol rejected the incoming call, Carol's channel has been hung up and freed, meaning accessing her channel results in a crash. The fix here is simple. The dial fixup code has been altered to hold references to the involved channels and to drop those references when freeing data. ASTERISK-25025 #close Reported by Chet Stevens Change-Id: I54eedda207b8ec7a69263353b43abe5746aea197
Diffstat (limited to 'main')
-rw-r--r--main/stasis_channels.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index 968afbd7d..9ed38c3ae 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -1326,6 +1326,7 @@ static void dial_target_free(struct dial_target *doomed)
return;
}
ast_free(doomed->dialstring);
+ ast_channel_cleanup(doomed->peer);
ast_free(doomed);
}
@@ -1348,7 +1349,7 @@ static void dial_masquerade_datastore_cleanup(struct dial_masquerade_datastore *
while ((cur = AST_LIST_REMOVE_HEAD(&masq_data->dialed_peers, list))) {
dial_target_free(cur);
}
- masq_data->caller = NULL;
+ masq_data->caller = ast_channel_cleanup(masq_data->caller);
}
static void dial_masquerade_datastore_remove_chan(struct dial_masquerade_datastore *masq_data, struct ast_channel *chan)
@@ -1556,7 +1557,7 @@ static struct dial_masquerade_datastore *dial_masquerade_datastore_add(
ast_datastore_free(datastore);
return NULL;
}
- masq_data->caller = chan;
+ masq_data->caller = ast_channel_ref(chan);
}
datastore->data = masq_data;
@@ -1604,7 +1605,7 @@ static int set_dial_masquerade(struct ast_channel *caller, struct ast_channel *p
return -1;
}
}
- target->peer = peer;
+ target->peer = ast_channel_ref(peer);
/* Put peer target into datastore */
ao2_lock(masq_data);