From fb8fb7fed0bb822ccc11ed20229db51a3991a0e5 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Sun, 21 May 2017 10:54:11 +0800
Subject: [PATCH] add dbmalloc epoch cleanup

--HG--
branch : fuzz
---
 Makefile.in                               |   1 +
 dbmalloc.c                                | 128 ++++++++++++++++++++++
 dbmalloc.h                                |  17 +++
 dbutil.c                                  |  39 -------
 dbutil.h                                  |   5 +-
 fuzzer-preauth.c                          |   2 +
 libtomcrypt/src/headers/tomcrypt_custom.h |  11 ++
 libtommath/tommath_class.h                |  11 ++
 8 files changed, 171 insertions(+), 43 deletions(-)
 create mode 100644 dbmalloc.c
 create mode 100644 dbmalloc.h

diff --git a/Makefile.in b/Makefile.in
index 19c747f4..d2f2eeb3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,6 +34,7 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
 		queue.o \
 		atomicio.o compat.o fake-rfc2553.o \
 		ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
+		dbmalloc.o \
 		gensignkey.o gendss.o genrsa.o 
 
 SVROBJS=svr-kex.o svr-auth.o sshpty.o \
diff --git a/dbmalloc.c b/dbmalloc.c
new file mode 100644
index 00000000..e62e0201
--- /dev/null
+++ b/dbmalloc.c
@@ -0,0 +1,128 @@
+#include "dbmalloc.h"
+#include "dbutil.h"
+
+#define LIST_SIZE 1000
+
+struct dbmalloc_header {
+    unsigned int index;
+    unsigned int epoch;
+};
+
+static struct dbmalloc_header* dbmalloc_list[LIST_SIZE];
+
+unsigned int current_epoch = 0;
+
+void m_malloc_set_epoch(unsigned int epoch) {
+    current_epoch = epoch;
+}
+
+void m_malloc_free_epoch(unsigned int epoch) {
+    unsigned int i;
+    unsigned int freed = 0;
+    for (i = 0; i < LIST_SIZE; i++) {
+        if (dbmalloc_list[i] != NULL) {
+            assert(dbmalloc_list[i]->index == i);
+            if (dbmalloc_list[i]->epoch == epoch) {
+                free(dbmalloc_list[i]);
+                dbmalloc_list[i] = NULL;
+                freed++;
+            }
+        }
+    }
+    TRACE(("free_epoch freed %d", freed))
+}
+
+static void put_alloc(struct dbmalloc_header *header) {
+    unsigned int i;
+    for (i = 0; i < LIST_SIZE; i++) {
+        if (dbmalloc_list[i] == NULL) {
+            dbmalloc_list[i] = header;
+            header->index = i;
+            return;
+        }
+    }
+    dropbear_exit("ran out of dbmalloc entries");
+}
+
+static void remove_alloc(struct dbmalloc_header *header) {
+    assert(header->index < LIST_SIZE);
+    assert(dbmalloc_list[header->index] == header);
+    assert(header->epoch == current_epoch);
+    dbmalloc_list[header->index] = NULL;
+}
+
+static struct dbmalloc_header* get_header(void* ptr) {
+    char* bptr = ptr;
+    return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)];
+}
+
+void * m_malloc(size_t size) {
+    char* mem = NULL;
+    struct dbmalloc_header* header = NULL;
+
+    if (size == 0 || size > 1e9) {
+        dropbear_exit("m_malloc failed");
+    }
+
+    size = size + sizeof(struct dbmalloc_header);
+
+    mem = calloc(1, size);
+    if (mem == NULL) {
+        dropbear_exit("m_malloc failed");
+    }
+    header = (struct dbmalloc_header*)mem;
+    put_alloc(header);
+    header->epoch = current_epoch;
+    return &mem[sizeof(struct dbmalloc_header)];
+}
+
+void * m_calloc(size_t nmemb, size_t size) {
+    assert(nmemb <= 1000 && size <= 10000);
+    return m_malloc(nmemb*size);
+}
+
+void * m_realloc(void* ptr, size_t size) {
+    char* mem = NULL;
+    struct dbmalloc_header* header = NULL;
+    if (size == 0 || size > 1e9) {
+        dropbear_exit("m_realloc failed");
+    }
+
+    header = get_header(ptr);
+    remove_alloc(header);
+
+    size = size + sizeof(struct dbmalloc_header);
+    mem = realloc(header, size);
+    if (mem == NULL) {
+        dropbear_exit("m_realloc failed");
+    }
+
+    header = (struct dbmalloc_header*)mem;
+    put_alloc(header);
+    return &mem[sizeof(struct dbmalloc_header)];
+}
+
+void m_free_direct(void* ptr) {
+    struct dbmalloc_header* header = NULL;
+    if (!ptr) {
+        return;
+    }
+    header = get_header(ptr);
+    remove_alloc(header);
+    free(header);
+}
+
+void * m_strdup(const char * str) {
+    char* ret;
+    unsigned int len;
+    len = strlen(str);
+
+    ret = m_malloc(len+1);
+    if (ret == NULL) {
+        dropbear_exit("m_strdup failed");
+    }
+    memcpy(ret, str, len+1);
+    return ret;
+}
+
+
diff --git a/dbmalloc.h b/dbmalloc.h
new file mode 100644
index 00000000..f6cccbbe
--- /dev/null
+++ b/dbmalloc.h
@@ -0,0 +1,17 @@
+#ifndef DBMALLOC_H_
+#define DBMALLOC_H_
+
+#include "includes.h"
+
+void * m_malloc(size_t size);
+/* m_calloc is limited in size, enough for libtomcrypt */
+void * m_calloc(size_t nmemb, size_t size);
+void * m_strdup(const char * str);
+void * m_realloc(void* ptr, size_t size);
+void m_free_direct(void* ptr);
+#define m_free(X) do {m_free_direct(X); (X) = NULL;} while (0)
+
+void m_malloc_set_epoch(unsigned int epoch);
+void m_malloc_free_epoch(unsigned int epoch);
+
+#endif /* DBMALLOC_H_ */
diff --git a/dbutil.c b/dbutil.c
index 4c835a49..e7e486a9 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -520,45 +520,6 @@ void m_close(int fd) {
 	}
 }
 	
-void * m_malloc(size_t size) {
-
-	void* ret;
-
-	if (size == 0) {
-		dropbear_exit("m_malloc failed");
-	}
-	ret = calloc(1, size);
-	if (ret == NULL) {
-		dropbear_exit("m_malloc failed");
-	}
-	return ret;
-
-}
-
-void * m_strdup(const char * str) {
-	char* ret;
-
-	ret = strdup(str);
-	if (ret == NULL) {
-		dropbear_exit("m_strdup failed");
-	}
-	return ret;
-}
-
-void * m_realloc(void* ptr, size_t size) {
-
-	void *ret;
-
-	if (size == 0) {
-		dropbear_exit("m_realloc failed");
-	}
-	ret = realloc(ptr, size);
-	if (ret == NULL) {
-		dropbear_exit("m_realloc failed");
-	}
-	return ret;
-}
-
 void setnonblocking(int fd) {
 
 	TRACE(("setnonblocking: %d", fd))
diff --git a/dbutil.h b/dbutil.h
index d83b20a9..3b3705e5 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -30,6 +30,7 @@
 #include "buffer.h"
 #include "queue.h"
 #include "dbhelpers.h"
+#include "dbmalloc.h"
 
 #ifndef DISABLE_SYSLOG
 void startsyslog(const char *ident);
@@ -66,10 +67,6 @@ int buf_readfile(buffer* buf, const char* filename);
 int buf_getline(buffer * line, FILE * authfile);
 
 void m_close(int fd);
-void * m_malloc(size_t size);
-void * m_strdup(const char * str);
-void * m_realloc(void* ptr, size_t size);
-#define m_free(X) do {free(X); (X) = NULL;} while (0)
 void setnonblocking(int fd);
 void disallow_core(void);
 int m_str_to_uint(const char* str, unsigned int *val);
diff --git a/fuzzer-preauth.c b/fuzzer-preauth.c
index 9ca7b842..7f0e1365 100644
--- a/fuzzer-preauth.c
+++ b/fuzzer-preauth.c
@@ -23,9 +23,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
 	int fakesock = 1;
 	wrapfd_add(fakesock, fuzz.input, PLAIN);
 
+	m_malloc_set_epoch(1);
 	if (setjmp(fuzz.jmp) == 0) {
 		svr_session(fakesock, fakesock);
 	} else {
+		m_malloc_free_epoch(1);
 		TRACE(("dropbear_exit longjmped"))
 		// dropbear_exit jumped here
 	}
diff --git a/libtomcrypt/src/headers/tomcrypt_custom.h b/libtomcrypt/src/headers/tomcrypt_custom.h
index 82cb26e5..7f13dbd5 100644
--- a/libtomcrypt/src/headers/tomcrypt_custom.h
+++ b/libtomcrypt/src/headers/tomcrypt_custom.h
@@ -4,6 +4,17 @@
 /* compile options depend on Dropbear options.h */
 #include "options.h"
 
+void * m_malloc(size_t size);
+/* m_calloc is limited in size, enough for libtomcrypt */
+void * m_calloc(size_t nmemb, size_t size);
+void * m_realloc(void* ptr, size_t size);
+void m_free_direct(void* ptr);
+
+#define XMALLOC m_malloc
+#define XFREE m_free_direct
+#define XREALLOC m_realloc
+#define XCALLOC m_calloc
+
 /* macros for various libc functions you can change for embedded targets */
 #ifndef XMALLOC
    #ifdef malloc 
diff --git a/libtommath/tommath_class.h b/libtommath/tommath_class.h
index a4e275a3..ea7fa5c0 100644
--- a/libtommath/tommath_class.h
+++ b/libtommath/tommath_class.h
@@ -1000,6 +1000,17 @@
 #undef BN_MP_TOOM_MUL_C
 #undef BN_MP_TOOM_SQR_C
 
+void * m_malloc(size_t size);
+/* m_calloc is limited in size, enough for libtomcrypt */
+void * m_calloc(size_t nmemb, size_t size);
+void * m_realloc(void* ptr, size_t size);
+void m_free_direct(void* ptr);
+
+#define XMALLOC m_malloc
+#define XFREE m_free_direct
+#define XREALLOC m_realloc
+#define XCALLOC m_calloc
+
 /* $Source: /cvs/libtom/libtommath/tommath_class.h,v $ */
 /* $Revision: 1.3 $ */
 /* $Date: 2005/07/28 11:59:32 $ */
-- 
GitLab