Pārlūkot izejas kodu

tm: onreply_route executed under lock to protect the avps

Quick fix for the onreply_route possible avp corruption: execute
the onreply route under lock.
Andrei Pelinescu-Onciul 15 gadi atpakaļ
vecāks
revīzija
07b90c04d3
1 mainītis faili ar 17 papildinājumiem un 3 dzēšanām
  1. 17 3
      modules/tm/t_reply.c

+ 17 - 3
modules/tm/t_reply.c

@@ -89,7 +89,9 @@
  * 2008-03-12  use cancel_b_method on 6xx (andrei)
  * 2008-05-30  make sure the wait timer is started after we don't need t
  *             anymore to allow safe calls from fr_timer (andrei)
- * 2009-06-01  Pre- and post-script callbacks of branch route are executed (Miklos)
+ * 2009-06-01  Pre- and post-script callbacks of branch route are 
+ *             executed (Miklos)
+ * 2009-12-10  reply route is executed under lock to protect the avps (andrei)
  *
  */
 
@@ -1861,6 +1863,7 @@ int reply_received( struct sip_msg  *p_msg )
 #ifdef WITH_XAVP
 	sr_xavp_t **backup_xavps;
 #endif
+	int replies_locked;
 #ifdef USE_DNS_FAILOVER
 	int branch_ret;
 	int prev_branch;
@@ -1888,6 +1891,7 @@ int reply_received( struct sip_msg  *p_msg )
 	tm_ctx_set_branch_index(branch);
 	cancel_bitmap=0;
 	msg_status=p_msg->REPLY_STATUS;
+	replies_locked=0;
 
 	uac=&t->uac[branch];
 	DBG("DEBUG: reply_received: org. status uas=%d, "
@@ -2015,6 +2019,9 @@ int reply_received( struct sip_msg  *p_msg )
 		/* Pre- and post-script callbacks have already
 		 * been executed by the core. (Miklos)
 		 */
+		/* lock onreply_route, for safe avp usage */
+		LOCK_REPLIES( t );
+		replies_locked=1;
 		run_top_route(onreply_rt.rlist[t->on_reply], p_msg, &ctx);
 		if ((ctx.run_flags&DROP_R_F)  && (msg_status<200)) {
 			goto done;
@@ -2071,15 +2078,22 @@ int reply_received( struct sip_msg  *p_msg )
 		 *  reply lock is held (the lock won't be held while sending the
 		 *   message)*/
 		if (cfg_get(core, core_cfg, use_dns_failover) && (msg_status==503)) {
-			branch_ret=add_uac_dns_fallback(t, t->uas.request, uac, 1);
+			branch_ret=add_uac_dns_fallback(t, t->uas.request,
+												uac, !replies_locked);
 			prev_branch=-1;
+			/* unlock replies to avoid sending() while holding a lock */
+			if (unlikely(replies_locked)) {
+				UNLOCK_REPLIES( t );
+				replies_locked = 0;
+			}
 			while((branch_ret>=0) &&(branch_ret!=prev_branch)){
 				prev_branch=branch_ret;
 				branch_ret=t_send_branch(t, branch_ret, t->uas.request , 0, 1);
 			}
 		}
 #endif
-	LOCK_REPLIES( t );
+	if (unlikely(!replies_locked))
+		LOCK_REPLIES( t );
 	if ( is_local(t) ) {
 		reply_status=local_reply( t, p_msg, branch, msg_status, &cancel_bitmap );
 		if (reply_status == RPS_COMPLETED) {