[asterisk-commits] mmichelson: trunk r114208 - in /trunk: ./ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 17 11:40:12 CDT 2008


Author: mmichelson
Date: Thu Apr 17 11:40:12 2008
New Revision: 114208

URL: http://svn.digium.com/view/asterisk?view=rev&rev=114208
Log:
Merged revisions 114207 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r114207 | mmichelson | 2008-04-17 11:28:03 -0500 (Thu, 17 Apr 2008) | 12 lines

It was possible for a reference to a frame which was part of a freed DSP to still be
referenced, leading to memory corruption and eventual crashes. This code change ensures
that the dsp is freed when we are finished with the frame. This change is very similar
to a change Russell made with translators back a month or so ago.

(closes issue #11999)
Reported by: destiny6628
Patches:
      11999.patch uploaded by putnopvut (license 60)
Tested by: destiny6628, victoryure


........

Modified:
    trunk/   (props changed)
    trunk/include/asterisk/dsp.h
    trunk/include/asterisk/frame.h
    trunk/main/dsp.c
    trunk/main/frame.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Modified: trunk/include/asterisk/dsp.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/dsp.h?view=diff&rev=114208&r1=114207&r2=114208
==============================================================================
--- trunk/include/asterisk/dsp.h (original)
+++ trunk/include/asterisk/dsp.h Thu Apr 17 11:40:12 2008
@@ -138,4 +138,16 @@
 
 int ast_dsp_init(void);
 
+/*!
+ * \brief Hint that a frame from a dsp was freed
+ *
+ * This is called from ast_frame_free if AST_FRFLAG_FROM_DSP is set. This occurs
+ * because it is possible for the dsp to be freed while someone still holds a reference
+ * to the frame that is in that dsp. This has been known to happen when the dsp on a Zap
+ * channel detects a busy signal. The channel is hung up, and the application that read the
+ * frame to begin with still has a reference to the frame.
+ *
+ * \return nothing
+ */
+void ast_dsp_frame_freed(struct ast_frame *fr);
 #endif /* _ASTERISK_DSP_H */

Modified: trunk/include/asterisk/frame.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/frame.h?view=diff&rev=114208&r1=114207&r2=114208
==============================================================================
--- trunk/include/asterisk/frame.h (original)
+++ trunk/include/asterisk/frame.h Thu Apr 17 11:40:12 2008
@@ -130,6 +130,10 @@
 	 *  The translator can not be free'd if the frame inside of it still has
 	 *  this flag set. */
 	AST_FRFLAG_FROM_TRANSLATOR = (1 << 1),
+	/*! This frame came from a dsp and is still the original frame.
+	 *  The dsp cannot be free'd if the frame inside of it still has
+	 *  this flag set. */
+	AST_FRFLAG_FROM_DSP = (1 << 2),
 };
 
 /*! \brief Data structure associated with a single frame of data

Modified: trunk/main/dsp.c
URL: http://svn.digium.com/view/asterisk/trunk/main/dsp.c?view=diff&rev=114208&r1=114207&r2=114208
==============================================================================
--- trunk/main/dsp.c (original)
+++ trunk/main/dsp.c Thu Apr 17 11:40:12 2008
@@ -388,6 +388,7 @@
 	digit_detect_state_t digit_state;
 	tone_detect_state_t cng_tone_state;
 	tone_detect_state_t ced_tone_state;
+	int destroy;
 };
 
 static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
@@ -1310,6 +1311,7 @@
 		memset(&dsp->f, 0, sizeof(dsp->f));
 		dsp->f.frametype = AST_FRAME_NULL;
 		ast_frfree(af);
+		ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
 		return &dsp->f;
 	}
 	if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
@@ -1319,6 +1321,7 @@
 		dsp->f.subclass = AST_CONTROL_BUSY;
 		ast_frfree(af);
 		ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
+		ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
 		return &dsp->f;
 	}
 
@@ -1424,6 +1427,7 @@
 		if (chan) 
 			ast_queue_frame(chan, af);
 		ast_frfree(af);
+		ast_set_flag(outf, AST_FRFLAG_FROM_DSP);
 		return outf;
 	} else {
 		return af;
@@ -1474,6 +1478,16 @@
 
 void ast_dsp_free(struct ast_dsp *dsp)
 {
+	if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
+		/* If this flag is still set, that means that the dsp's destruction 
+		 * been torn down, while we still have a frame out there being used.
+		 * When ast_frfree() gets called on that frame, this ast_trans_pvt
+		 * will get destroyed, too. */
+
+		dsp->destroy = 1;
+
+		return;
+	}
 	ast_free(dsp);
 }
 
@@ -1632,3 +1646,16 @@
 	return _dsp_init(1);
 }
 
+void ast_dsp_frame_freed(struct ast_frame *fr)
+{
+	struct ast_dsp *dsp;
+
+	ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
+
+	dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
+
+	if (!dsp->destroy)
+		return;
+	
+	ast_dsp_free(dsp);
+}

Modified: trunk/main/frame.c
URL: http://svn.digium.com/view/asterisk/trunk/main/frame.c?view=diff&rev=114208&r1=114207&r2=114208
==============================================================================
--- trunk/main/frame.c (original)
+++ trunk/main/frame.c Thu Apr 17 11:40:12 2008
@@ -37,6 +37,7 @@
 #include "asterisk/threadstorage.h"
 #include "asterisk/linkedlists.h"
 #include "asterisk/translate.h"
+#include "asterisk/dsp.h"
 
 #ifdef TRACE_FRAMES
 static int headers;
@@ -307,6 +308,8 @@
 {
 	if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR))
 		ast_translate_frame_freed(fr);
+	else if (ast_test_flag(fr, AST_FRFLAG_FROM_DSP))
+		ast_dsp_frame_freed(fr);
 
 	if (!fr->mallocd)
 		return;
@@ -356,6 +359,7 @@
 	void *newdata;
 
 	ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
+	ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
 
 	if (!(fr->mallocd & AST_MALLOCD_HDR)) {
 		/* Allocate a new header if needed */




More information about the asterisk-commits mailing list