[svn-commits] seanbright: branch 1.4 r323559 - /branches/1.4/main/manager.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jun 15 10:15:36 CDT 2011


Author: seanbright
Date: Wed Jun 15 10:15:30 2011
New Revision: 323559

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=323559
Log:
Resolve a segfault/bus error when we try to map memory that falls on a page
boundary.

The fix for ASTERISK-15359 was incorrect in that it added 1 to the length of the
mmap'd region.  The problem with this is that reading/writing to that extra byte
outside of the bounds of the underlying fd causes a bus error.

The real issue is that we are working with both a FILE * and the raw fd
underneath it and not synchronizing between them.  The code that was removed in
ASTERISK-15359 was correct, but we weren't flushing the FILE * before mapping
the fd.

Looking at the manager code in 1.4 reveals that the FILE * in 'struct
mansession' is never used except to create a temporary file that we immediately
fdopen.  This means we just need to write a 0 byte to the fd and everything will
just work.  The other branches require a call to fflush() which, while not a
guaranteed fix, should reduce the likelihood of a crash.

This all makes sense in my head.

(closes issue ASTERISK-16460)
Reported by: Ravelomanantsoa Hoby (hoby)
Patches:
		issue17747_1.4_svn_markII.patch uploaded by Sean Bright (license #5060)

Modified:
    branches/1.4/main/manager.c

Modified: branches/1.4/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/manager.c?view=diff&rev=323559&r1=323558&r2=323559
==============================================================================
--- branches/1.4/main/manager.c (original)
+++ branches/1.4/main/manager.c Wed Jun 15 10:15:30 2011
@@ -2895,6 +2895,7 @@
 	char *c = workspace;
 	char *retval = NULL;
 	struct ast_variable *v;
+	char template[] = "/tmp/ast-http-XXXXXX";
 
 	for (v = params; v; v = v->next) {
 		if (!strcasecmp(v->name, "mansession_id")) {
@@ -2942,8 +2943,9 @@
 	ss.session = s;
 	ast_mutex_unlock(&s->__lock);
 
-	ss.f = tmpfile();
-	ss.fd = fileno(ss.f);
+	if ((ss.fd = mkstemp(template)) > -1) {
+		unlink(template);
+	}
 
 	if (s) {
 		struct message m = { 0 };
@@ -2989,13 +2991,21 @@
 		if (ss.fd > -1) {
 			char *buf;
 			size_t l;
-
-			if ((l = lseek(ss.fd, 0, SEEK_END)) > 0) {
-				if (MAP_FAILED == (buf = mmap(NULL, l + 1, PROT_READ | PROT_WRITE, MAP_SHARED, ss.fd, 0))) {
+			ssize_t res;
+
+			/* Make sure that our buffer is NULL terminated */
+			while ((res = write(ss.fd, "", 1)) < 1) {
+				if (res == -1) {
+					ast_log(LOG_ERROR, "Failed to terminate manager response output: %s\n", strerror(errno));
+					break;
+				}
+			}
+
+			if (res == 1 && (l = lseek(ss.fd, 0, SEEK_END)) > 0) {
+				if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, ss.fd, 0))) {
 					ast_log(LOG_WARNING, "mmap failed.  Manager request output was not processed\n");
 				} else {
 					char *tmpbuf;
-					buf[l] = '\0';
 					if (format == FORMAT_XML)
 						tmpbuf = xml_translate(buf, params);
 					else if (format == FORMAT_HTML)
@@ -3016,11 +3026,10 @@
 						free(tmpbuf);
 					free(s->outputstr);
 					s->outputstr = NULL;
-					munmap(buf, l + 1);
+					munmap(buf, l);
 				}
 			}
-			fclose(ss.f);
-			ss.f = NULL;
+			close(ss.fd);
 			ss.fd = -1;
 		} else if (s->outputstr) {
 			char *tmp;




More information about the svn-commits mailing list