[svn-commits] russell: branch 1.8 r406566 - in /branches/1.8: include/asterisk/ main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sun Jan 26 19:07:10 CST 2014


Author: russell
Date: Sun Jan 26 19:07:07 2014
New Revision: 406566

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=406566
Log:
Protect ast_filestream object when on a channel

The ast_filestream object gets tacked on to a channel via
chan->timingdata.  It's a reference counted object, but the reference
count isn't used when putting it on a channel.  It's theoretically
possible for another thread to interfere with the channel while it's
unlocked and cause the filestream to get destroyed.

Use the astobj2 reference count to make sure that as long as this code
path is holding on the ast_filestream and passing it into the file.c
playback code, that it knows it's valid.

Bug reported by Leif Madsen.

Review: https://reviewboard.asterisk.org/r/3135/


Modified:
    branches/1.8/include/asterisk/channel.h
    branches/1.8/main/channel.c
    branches/1.8/main/file.c

Modified: branches/1.8/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/include/asterisk/channel.h?view=diff&rev=406566&r1=406565&r2=406566
==============================================================================
--- branches/1.8/include/asterisk/channel.h (original)
+++ branches/1.8/include/asterisk/channel.h Sun Jan 26 19:07:07 2014
@@ -951,6 +951,10 @@
 	 * to continue.
 	 */
 	AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT = (1 << 22),
+	/*!
+	 * The data on chan->timingdata is an astobj2 object.
+	 */
+	AST_FLAG_TIMINGDATA_IS_AO2_OBJ = (1 << 23),
 };
 
 /*! \brief ast_bridge_config flags */
@@ -2260,6 +2264,7 @@
  * \version 1.6.1 changed samples parameter to rate, accomodates new timing methods
  */
 int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data);
+int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data, unsigned int is_ao2_obj);
 
 /*!
  * \brief Transfer a channel (if supported).

Modified: branches/1.8/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/channel.c?view=diff&rev=406566&r1=406565&r2=406566
==============================================================================
--- branches/1.8/main/channel.c (original)
+++ branches/1.8/main/channel.c Sun Jan 26 19:07:07 2014
@@ -3545,6 +3545,11 @@
 
 int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data)
 {
+	return ast_settimeout_full(c, rate, func, data, 0);
+}
+
+int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data, unsigned int is_ao2_obj)
+{
 	int res;
 	unsigned int real_rate = rate, max_rate;
 
@@ -3568,8 +3573,19 @@
 
 	res = ast_timer_set_rate(c->timer, real_rate);
 
+	if (c->timingdata && ast_test_flag(c, AST_FLAG_TIMINGDATA_IS_AO2_OBJ)) {
+		ao2_ref(c->timingdata, -1);
+	}
+
 	c->timingfunc = func;
 	c->timingdata = data;
+
+	if (data && is_ao2_obj) {
+		ao2_ref(data, 1);
+		ast_set_flag(c, AST_FLAG_TIMINGDATA_IS_AO2_OBJ);
+	} else {
+		ast_clear_flag(c, AST_FLAG_TIMINGDATA_IS_AO2_OBJ);
+	}
 
 	if (func == NULL && rate == 0 && c->fdno == AST_TIMING_FD) {
 		/* Clearing the timing func and setting the rate to 0
@@ -3877,9 +3893,17 @@
 				/* save a copy of func/data before unlocking the channel */
 				int (*func)(const void *) = chan->timingfunc;
 				void *data = chan->timingdata;
+				int got_ref = 0;
+				if (data && ast_test_flag(chan, AST_FLAG_TIMINGDATA_IS_AO2_OBJ)) {
+					ao2_ref(data, 1);
+					got_ref = 1;
+				}
 				chan->fdno = -1;
 				ast_channel_unlock(chan);
 				func(data);
+				if (got_ref) {
+					ao2_ref(data, -1);
+				}
 			} else {
 				ast_timer_set_rate(chan->timer, 0);
 				chan->fdno = -1;

Modified: branches/1.8/main/file.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/main/file.c?view=diff&rev=406566&r1=406565&r2=406566
==============================================================================
--- branches/1.8/main/file.c (original)
+++ branches/1.8/main/file.c Sun Jan 26 19:07:07 2014
@@ -782,7 +782,7 @@
 
 			rate = (unsigned int) roundf(samp_rate / ((float) whennext));
 
-			ast_settimeout(s->owner, rate, ast_fsread_audio, s);
+			ast_settimeout_full(s->owner, rate, ast_fsread_audio, s, 1);
 		} else {
 			s->owner->streamid = ast_sched_add(s->owner->sched, 
 				whennext / (ast_format_rate(s->fmt->format) / 1000), ast_fsread_audio, s);




More information about the svn-commits mailing list