[asterisk-commits] rmudgett: branch 1.8 r373424 - /branches/1.8/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Sep 24 10:40:26 CDT 2012


Author: rmudgett
Date: Mon Sep 24 10:40:22 2012
New Revision: 373424

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=373424
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

Modified:
    branches/1.8/channels/chan_sip.c

Modified: branches/1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/channels/chan_sip.c?view=diff&rev=373424&r1=373423&r2=373424
==============================================================================
--- branches/1.8/channels/chan_sip.c (original)
+++ branches/1.8/channels/chan_sip.c Mon Sep 24 10:40:22 2012
@@ -5746,9 +5746,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 */
@@ -5756,6 +5757,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;
 }
@@ -5849,6 +5851,7 @@
 	
 	if (p->mwi) {
 		p->mwi->call = NULL;
+		p->mwi = NULL;
 	}
 
 	if (dumphistory)
@@ -5859,29 +5862,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);
@@ -5932,6 +5943,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);
@@ -8238,7 +8250,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:
@@ -8256,6 +8270,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) {
@@ -10437,8 +10452,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) {
@@ -11811,19 +11824,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);
 	}
 }
@@ -12296,8 +12311,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;
@@ -18101,13 +18115,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) {
@@ -18116,10 +18135,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;
 	}
@@ -18150,6 +18171,7 @@
 		stats.txjitter
 	);
 	arg->numchans++;
+	sip_pvt_unlock(cur);
 
 	return 0;	/* don't care, we scan all channels */
 }
@@ -18485,8 +18507,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 */
@@ -18521,6 +18546,7 @@
 			);
 		arg->numchans++;
 	}
+	sip_pvt_unlock(cur);
 	return 0;	/* don't care, we scan all channels */
 }
 




More information about the asterisk-commits mailing list