[asterisk-commits] rmudgett: branch 10 r373466 - in /branches/10: ./ channels/chan_sip.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Sep 24 15:44:31 CDT 2012
Author: rmudgett
Date: Mon Sep 24 15:44:27 2012
New Revision: 373466
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=373466
Log:
Fix potential reentrancy problems in chan_sip.
Asterisk v1.8 and later was not as vulnerable to this issue.
* Made find_call() lock each private as it processes the found dialogs.
(Primary cause of ABE-2876)
* Made the other functions that traverse the dialogs container lock each
private as it examines them.
* Fix race condition in sip_call() if the thread that sent the INVITE is
held up long enough for a response to be processed. The p->initid for the
INVITE retransmission could be added after it was canceled by the response
processing.
* Made __sip_destroy() clean up resource pointers after freeing. This is
primarily defensive in case someone has a stale private pointer.
* Removed redundant memset() in reqprep(). The call to init_req() already
does the memset() and is the first reference to req in reqprep().
* Removed useless set of req.method in transmit_invite(). The calls to
initreqprep() and reqprep() have to do this because they memset() the req.
JIRA ABE-2876
..........
Merged -r373423 from https://origsvn.digium.com/svn/asterisk/be/branches/C.3-bier
........
Merged revisions 373424 from http://svn.asterisk.org/svn/asterisk/branches/1.8
Modified:
branches/10/ (props changed)
branches/10/channels/chan_sip.c
Propchange: branches/10/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.
Modified: branches/10/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/channels/chan_sip.c?view=diff&rev=373466&r1=373465&r2=373466
==============================================================================
--- branches/10/channels/chan_sip.c (original)
+++ branches/10/channels/chan_sip.c Mon Sep 24 15:44:27 2012
@@ -5779,9 +5779,10 @@
}
xmitres = transmit_invite(p, SIP_INVITE, 1, 2, uri);
- sip_pvt_unlock(p);
- if (xmitres == XMIT_ERROR)
+ if (xmitres == XMIT_ERROR) {
+ sip_pvt_unlock(p);
return -1;
+ }
p->invitestate = INV_CALLING;
/* Initialize auto-congest time */
@@ -5789,6 +5790,7 @@
dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"),
dialog_unref(p, "dialog ptr dec when SCHED_REPLACE add failed"),
dialog_ref(p, "dialog ptr inc when SCHED_REPLACE add succeeded") );
+ sip_pvt_unlock(p);
}
return res;
}
@@ -5882,6 +5884,7 @@
if (p->mwi) {
p->mwi->call = NULL;
+ p->mwi = NULL;
}
if (dumphistory)
@@ -5892,29 +5895,37 @@
ao2_ref(p->options->outboundproxy, -1);
}
ast_free(p->options);
+ p->options = NULL;
}
if (p->notify) {
ast_variables_destroy(p->notify->headers);
ast_free(p->notify->content);
ast_free(p->notify);
+ p->notify = NULL;
}
if (p->rtp) {
ast_rtp_instance_destroy(p->rtp);
+ p->rtp = NULL;
}
if (p->vrtp) {
ast_rtp_instance_destroy(p->vrtp);
+ p->vrtp = NULL;
}
if (p->trtp) {
ast_rtp_instance_destroy(p->trtp);
- }
- if (p->udptl)
+ p->trtp = NULL;
+ }
+ if (p->udptl) {
ast_udptl_destroy(p->udptl);
+ p->udptl = NULL;
+ }
if (p->refer) {
if (p->refer->refer_call) {
p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call");
}
ast_free(p->refer);
+ p->refer = NULL;
}
if (p->route) {
free_old_route(p->route);
@@ -5967,6 +5978,7 @@
ast_string_field_free_memory(p);
ast_cc_config_params_destroy(p->cc_params);
+ p->cc_params = NULL;
if (p->epa_entry) {
ao2_ref(p->epa_entry, -1);
@@ -8197,10 +8209,25 @@
static void forked_invite_init(struct sip_request *req, const char *new_theirtag, struct sip_pvt *original, struct ast_sockaddr *addr)
{
struct sip_pvt *p;
-
- if (!(p = sip_alloc(original->callid, addr, 1, SIP_INVITE, req))) {
+ const char *callid;
+
+ sip_pvt_lock(original);
+ callid = ast_strdupa(original->callid);
+ sip_pvt_unlock(original);
+
+ if (!(p = sip_alloc(callid, addr, 1, SIP_INVITE, req))) {
return; /* alloc error */
}
+
+ /* Lock p and original private structures. */
+ sip_pvt_lock(p);
+ while (sip_pvt_trylock(original)) {
+ /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */
+ sip_pvt_unlock(p);
+ sched_yield();
+ sip_pvt_lock(p);
+ }
+
p->invitestate = INV_TERMINATED;
p->ocseq = original->ocseq;
p->branch = original->branch;
@@ -8212,6 +8239,9 @@
ast_string_field_set(p, uri, original->uri);
ast_string_field_set(p, our_contact, original->our_contact);
ast_string_field_set(p, fullcontact, original->fullcontact);
+
+ sip_pvt_unlock(original);
+
parse_ok_contact(p, req);
build_route(p, req, 1, 0);
@@ -8219,6 +8249,7 @@
transmit_request(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
pvt_set_needdestroy(p, "forked request"); /* this dialog will terminate once the BYE is responed to or times out. */
+ sip_pvt_unlock(p);
dialog_unref(p, "setup forked invite termination");
}
@@ -8398,7 +8429,9 @@
/* Iterate a list of dialogs already matched by Call-id */
while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) {
+ sip_pvt_lock(sip_pvt_ptr);
found = match_req_to_dialog(sip_pvt_ptr, &args);
+ sip_pvt_unlock(sip_pvt_ptr);
switch (found) {
case SIP_REQ_MATCH:
@@ -8422,6 +8455,7 @@
case SIP_REQ_NOT_MATCH:
default:
dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search");
+ break;
}
}
if (iterator) {
@@ -10685,8 +10719,6 @@
int is_strict = FALSE; /*!< Strict routing flag */
int is_outbound = ast_test_flag(&p->flags[0], SIP_OUTGOING); /* Session direction */
- memset(req, 0, sizeof(struct sip_request));
-
snprintf(p->lastmsg, sizeof(p->lastmsg), "Tx: %s", sip_methods[sipmethod].text);
if (!seqno) {
@@ -12189,19 +12221,21 @@
/* copy the entire request then restore the original data and content
* members from the dst request */
- memcpy(dst, src, sizeof(*dst));
+ *dst = *src;
dst->data = duplicate;
dst->content = duplicate_content;
/* copy the data into the dst request */
- if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1)))
+ if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1))) {
return;
+ }
ast_str_copy_string(&dst->data, src->data);
/* copy the content into the dst request (if it exists) */
if (src->content) {
- if (!dst->content && !(dst->content = ast_str_create(ast_str_strlen(src->content) + 1)))
+ if (!dst->content && !(dst->content = ast_str_create(ast_str_strlen(src->content) + 1))) {
return;
+ }
ast_str_copy_string(&dst->content, src->content);
}
}
@@ -12674,8 +12708,7 @@
{
struct sip_request req;
struct ast_variable *var;
-
- req.method = sipmethod;
+
if (init) {/* Bump branch even on initial requests */
p->branch ^= ast_random();
p->invite_branch = p->branch;
@@ -18697,13 +18730,18 @@
char durbuf[10];
int duration;
int durh, durm, durs;
- struct ast_channel *c = cur->owner;
+ struct ast_channel *c;
struct __show_chan_arg *arg = __arg;
int fd = arg->fd;
-
- if (cur->subscribed != NONE) /* Subscriptions */
+ sip_pvt_lock(cur);
+ c = cur->owner;
+
+ if (cur->subscribed != NONE) {
+ /* Subscriptions */
+ sip_pvt_unlock(cur);
return 0; /* don't care, we scan all channels */
+ }
if (!cur->rtp) {
if (sipdebug) {
@@ -18712,10 +18750,12 @@
invitestate2string[cur->invitestate].desc,
"-- No RTP active");
}
+ sip_pvt_unlock(cur);
return 0; /* don't care, we scan all channels */
}
if (ast_rtp_instance_get_stats(cur->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
+ sip_pvt_unlock(cur);
ast_log(LOG_WARNING, "Could not get RTP stats.\n");
return 0;
}
@@ -18746,6 +18786,7 @@
stats.txjitter
);
arg->numchans++;
+ sip_pvt_unlock(cur);
return 0; /* don't care, we scan all channels */
}
@@ -19083,8 +19124,11 @@
{
struct sip_pvt *cur = __cur;
struct __show_chan_arg *arg = __arg;
- const struct ast_sockaddr *dst = sip_real_dst(cur);
-
+ const struct ast_sockaddr *dst;
+
+ sip_pvt_lock(cur);
+ dst = sip_real_dst(cur);
+
/* XXX indentation preserved to reduce diff. Will be fixed later */
if (cur->subscribed == NONE && !arg->subscriptions) {
/* set if SIP transfer in progress */
@@ -19119,6 +19163,7 @@
);
arg->numchans++;
}
+ sip_pvt_unlock(cur);
return 0; /* don't care, we scan all channels */
}
More information about the asterisk-commits
mailing list