changeset 1358:6b89eb92f872 fuzz

glaring wrapfd problems fixed
author Matt Johnston <matt@ucc.asn.au>
date Sat, 20 May 2017 22:47:19 +0800
parents 08f4fa4dc6a0
children 665dd8957a67
files common-channel.c common-kex.c common-session.c dbrandom.c dbutil.c debug.h fuzz-common.c fuzz-harness.c fuzz-wrapfd.c fuzz.h fuzzer-preauth.c svr-session.c
diffstat 12 files changed, 72 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/common-channel.c	Sat May 20 13:23:16 2017 +0800
+++ b/common-channel.c	Sat May 20 22:47:19 2017 +0800
@@ -88,6 +88,10 @@
 
 	unsigned int i;
 
+	if (!ses.channels) {
+		return;
+	}
+
 	TRACE(("enter chancleanup"))
 	for (i = 0; i < ses.chansize; i++) {
 		if (ses.channels[i] != NULL) {
--- a/common-kex.c	Sat May 20 13:23:16 2017 +0800
+++ b/common-kex.c	Sat May 20 22:47:19 2017 +0800
@@ -403,6 +403,7 @@
 		ses.newkeys->recv.zstream->zfree = Z_NULL;
 		
 		if (inflateInit(ses.newkeys->recv.zstream) != Z_OK) {
+			m_free(ses.newkeys->recv.zstream);
 			dropbear_exit("zlib error");
 		}
 	} else {
--- a/common-session.c	Sat May 20 13:23:16 2017 +0800
+++ b/common-session.c	Sat May 20 22:47:19 2017 +0800
@@ -82,14 +82,18 @@
 	ses.last_packet_time_any_sent = 0;
 	ses.last_packet_time_keepalive_sent = 0;
 	
-	if (pipe(ses.signal_pipe) < 0) {
-		dropbear_exit("Signal pipe failed");
+#ifdef DROPBEAR_FUZZ
+	if (!fuzz.fuzzing)
+#endif
+	{
+		if (pipe(ses.signal_pipe) < 0) {
+			dropbear_exit("Signal pipe failed");
+		}
+		setnonblocking(ses.signal_pipe[0]);
+		setnonblocking(ses.signal_pipe[1]);
+		ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
+		ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
 	}
-	setnonblocking(ses.signal_pipe[0]);
-	setnonblocking(ses.signal_pipe[1]);
-
-	ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
-	ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
 	
 	ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
 	ses.transseq = 0;
@@ -311,6 +315,16 @@
 		buf_free(dequeue(&ses.writequeue));
 	}
 
+	m_free(ses.newkeys);
+#ifndef DISABLE_ZLIB
+	if (ses.keys->recv.zstream != NULL) {
+		if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
+			dropbear_exit("Crypto error");
+		}
+		m_free(ses.keys->recv.zstream);
+	}
+#endif
+
 	m_free(ses.remoteident);
 	m_free(ses.authstate.pw_dir);
 	m_free(ses.authstate.pw_name);
--- a/dbrandom.c	Sat May 20 13:23:16 2017 +0800
+++ b/dbrandom.c	Sat May 20 22:47:19 2017 +0800
@@ -181,7 +181,8 @@
 #endif
 }
 
-static void seedfuzz(void) {
+#ifdef DROPBEAR_FUZZ
+void seedfuzz(void) {
 	hash_state hs;
 	sha1_init(&hs);
 	sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
@@ -190,6 +191,7 @@
 	counter = 0;
 	donerandinit = 1;
 }
+#endif
 
 /* Initialise the prng from /dev/urandom or prngd. This function can
  * be called multiple times */
@@ -203,7 +205,6 @@
 
 #ifdef DROPBEAR_FUZZ
 	if (fuzz.fuzzing || fuzz.recordf) {
-		seedfuzz();
 		return;
 	}
 #endif
--- a/dbutil.c	Sat May 20 13:23:16 2017 +0800
+++ b/dbutil.c	Sat May 20 22:47:19 2017 +0800
@@ -569,7 +569,16 @@
 			 * can't be set to non-blocking */
 			TRACE(("ignoring ENODEV for setnonblocking"))
 		} else {
-			dropbear_exit("Couldn't set nonblocking");
+#ifdef DROPBEAR_FUZZ
+			if (fuzz.fuzzing) 
+			{
+				TRACE(("fuzzing ignore setnonblocking failure for %d", fd))
+			} 
+			else 
+#endif
+			{
+				dropbear_exit("Couldn't set nonblocking");
+			}
 		}
 	}
 	TRACE(("leave setnonblocking"))
--- a/debug.h	Sat May 20 13:23:16 2017 +0800
+++ b/debug.h	Sat May 20 22:47:19 2017 +0800
@@ -64,6 +64,7 @@
 
 /* you don't need to touch this block */
 #if DEBUG_TRACE
+extern int debug_trace;
 #define TRACE(X) dropbear_trace X;
 #define TRACE2(X) dropbear_trace2 X;
 #else /*DEBUG_TRACE*/
--- a/fuzz-common.c	Sat May 20 13:23:16 2017 +0800
+++ b/fuzz-common.c	Sat May 20 22:47:19 2017 +0800
@@ -27,6 +27,9 @@
     fuzz.input->len = Size;
     fuzz.input->pos = 0;
 
+    memset(&ses, 0x0, sizeof(ses));
+    memset(&svr_ses, 0x0, sizeof(svr_ses));
+
     // get prefix. input format is
     // string prefix
     //     uint32 wrapfd seed
@@ -44,7 +47,7 @@
     uint32_t wrapseed = buf_getint(fuzz.input);
     wrapfd_setup(wrapseed);
 
-    seedrandom();
+    seedfuzz();
 
     return DROPBEAR_SUCCESS;
 }
--- a/fuzz-harness.c	Sat May 20 13:23:16 2017 +0800
+++ b/fuzz-harness.c	Sat May 20 22:47:19 2017 +0800
@@ -18,7 +18,9 @@
         buf_readfile(input, fn);
         buf_setpos(input, 0);
 
-        printf("Running %s\n", fn);
+        printf("Running %s once \n", fn);
+        LLVMFuzzerTestOneInput(input->data, input->len);
+        printf("Running %s twice \n", fn);
         LLVMFuzzerTestOneInput(input->data, input->len);
         printf("Done %s\n", fn);
     }
--- a/fuzz-wrapfd.c	Sat May 20 13:23:16 2017 +0800
+++ b/fuzz-wrapfd.c	Sat May 20 22:47:19 2017 +0800
@@ -16,6 +16,8 @@
 struct fdwrap {
 	enum wrapfd_mode mode;
 	buffer *buf;
+	int closein;
+	int closeout;
 };
 
 static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
@@ -28,21 +30,25 @@
 	TRACE(("wrapfd_setup %x", seed))
 	nused = 0;
 	memset(wrap_fds, 0x0, sizeof(wrap_fds));
+	memset(wrap_used, 0x0, sizeof(wrap_used));
 
+	memset(rand_state, 0x0, sizeof(rand_state));
 	*((uint32_t*)rand_state) = seed;
 	nrand48(rand_state);
 }
 
 void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
+	TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
 	assert(fd >= 0);
 	assert(fd <= IOWRAP_MAXFD);
 	assert(wrap_fds[fd].mode == UNUSED);
 	assert(buf || mode == RANDOMIN);
 
-	TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
 
 	wrap_fds[fd].mode = mode;
 	wrap_fds[fd].buf = buf;
+	wrap_fds[fd].closein = 0;
+	wrap_fds[fd].closeout = 0;
 	wrap_used[nused] = fd;
 
 	nused++;
@@ -50,12 +56,12 @@
 
 void wrapfd_remove(int fd) {
 	unsigned int i, j;
+	TRACE(("wrapfd_remove %d", fd))
 	assert(fd >= 0);
 	assert(fd <= IOWRAP_MAXFD);
 	assert(wrap_fds[fd].mode != UNUSED);
 	wrap_fds[fd].mode = UNUSED;
 
-	TRACE(("wrapfd_remove %d", fd))
 
 	// remove from used list
 	for (i = 0, j = 0; i < nused; i++) {
@@ -67,6 +73,9 @@
 	nused--;
 }
 
+void wrapfd_close(int fd) {
+	wrapfd_remove(fd);
+}
 
 int wrapfd_read(int fd, void *out, size_t count) {
 	size_t maxread;
@@ -85,9 +94,10 @@
 
 	assert(count != 0);
 
-	if (erand48(rand_state) < CHANCE_CLOSE) {
-		wrapfd_remove(fd);
-		return 0;
+	if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) {
+		wrap_fds[fd].closein = 1;
+		errno = ECONNRESET;
+		return -1;
 	}
 
 	if (erand48(rand_state) < CHANCE_INTR) {
@@ -135,9 +145,10 @@
 		(void)volin[i];
 	}
 
-	if (erand48(rand_state) < CHANCE_CLOSE) {
-		wrapfd_remove(fd);
-		return 0;
+	if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) {
+		wrap_fds[fd].closeout = 1;
+		errno = ECONNRESET;
+		return -1;
 	}
 
 	if (erand48(rand_state) < CHANCE_INTR) {
--- a/fuzz.h	Sat May 20 13:23:16 2017 +0800
+++ b/fuzz.h	Sat May 20 22:47:19 2017 +0800
@@ -23,6 +23,7 @@
         wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
 #define write(fd, buf, count) wrapfd_write(fd, buf, count)
 #define read(fd, buf, count) wrapfd_read(fd, buf, count)
+#define close(fd) wrapfd_close(fd)
 #endif // FUZZ_SKIP_WRAP
 
 struct dropbear_fuzz_options {
--- a/fuzzer-preauth.c	Sat May 20 13:23:16 2017 +0800
+++ b/fuzzer-preauth.c	Sat May 20 22:47:19 2017 +0800
@@ -2,9 +2,11 @@
 #include "dbrandom.h"
 #include "session.h"
 #include "fuzz-wrapfd.h"
+#include "debug.h"
 
 static void setup_fuzzer(void) {
 	svr_setup_fuzzer();
+	//debug_trace = 1;
 }
 
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
--- a/svr-session.c	Sat May 20 13:23:16 2017 +0800
+++ b/svr-session.c	Sat May 20 22:47:19 2017 +0800
@@ -245,7 +245,9 @@
 static void svr_remoteclosed() {
 
 	m_close(ses.sock_in);
-	m_close(ses.sock_out);
+	if (ses.sock_in != ses.sock_out) {
+		m_close(ses.sock_out);
+	}
 	ses.sock_in = -1;
 	ses.sock_out = -1;
 	dropbear_close("Exited normally");