From 2a9dea016d8375c34a14e1d80a4dc29733bcc61c Mon Sep 17 00:00:00 2001
From: Toby Murray <toby.murray@unimelb.edu.au>
Date: Fri, 6 Sep 2019 21:51:48 +1000
Subject: [PATCH] clag libFuzzer and coverage support from 2018. fix a bug
found by libfuzzer
---
src/Makefile | 48 ++++++++++++++++++++++++++++++++++
src/get_coverage.sh | 63 +++++++++++++++++++++++++++++++++++++++++++++
src/passbook.c | 32 ++++++++++++++++++++---
3 files changed, 140 insertions(+), 3 deletions(-)
create mode 100644 src/Makefile
create mode 100755 src/get_coverage.sh
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..c9d1d41
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,48 @@
+BINARY=passbook
+
+#VULNS=vuln1 vuln2 vuln3 vuln4 vuln5
+
+VBINARIES=$(BINARY) $(VULNS:%=${BINARY}-%)
+
+TARGETS=$(VBINARIES) $(VBINARIES:%=%-san) $(VBINARIES:%=%-fuzz) $(VBINARIES:%=%-cov)
+
+HEADERS=$(wildcard *.h)
+
+# allow the user to provide additional CFLAGS by doing e.g. CFLAGS=blah make
+CFLAGS += -W -Wall -Wpedantic -Wno-language-extension-token
+
+# allow the user to override what clang we use by doing e.g. CLANG=blah make
+CLANG ?= clang-6.0
+CC=$(CLANG)
+
+SAN_FLAGS ?= -fsanitize=address -fno-omit-frame-pointer
+FUZZ_FLAGS ?= -DPASSBOOK_LIBFUZZER -fsanitize=fuzzer,address -fno-omit-frame-pointer
+NO_STRICT_OVERFLOW_CFLAGS ?= -fwrapv -fno-strict-overflow -Wstrict-overflow
+COV_FLAGS ?= -fprofile-instr-generate -fcoverage-mapping
+
+default: $(TARGETS)
+
+.PHONY: default
+
+
+%: %.c $(HEADERS)
+ $(CC) $< $(CFLAGS) $(LDFLAGS) $(NO_STRICT_OVERFLOW_CFLAGS) -o $@
+
+
+%-san: %.c $(HEADERS)
+ $(CLANG) $< $(CFLAGS) $(LDFLAGS) $(SAN_FLAGS) $(NO_STRICT_OVERFLOW_CFLAGS) -o $@
+
+
+# build a self-fuzzing binary with libFuzzer
+# needs a recent clang version (e.g. clang-6.0)
+# then to run it:
+# ./passbook-fuzz ~/tmp/corpus/ ~/tmp/findings/ -timeout=5 -only-ascii=1 -dict=libfuzzer-dict -max_total_time=1200 -print_final_stats=1
+%-fuzz: %.c $(HEADERS)
+ $(CLANG) $< $(CFLAGS) $(LDFLAGS) $(FUZZ_FLAGS) $(NO_STRICT_OVERFLOW_CFLAGS) -o $@
+
+%-cov: %.c $(HEADERS)
+ $(CLANG) $< $(CFLAGS) $(LDFLAGS) $(COV_FLAGS) $(NO_STRICT_OVERFLOW_CFLAGS) -o $@
+
+clean:
+ rm -f $(TARGETS) *.profraw *.profdata
+
diff --git a/src/get_coverage.sh b/src/get_coverage.sh
new file mode 100755
index 0000000..6768421
--- /dev/null
+++ b/src/get_coverage.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+if [ -z ${TOOL_SUFFIX+x} ]
+then
+ # TOOL_SUFFIX not set
+ # try to intelligently set TOOL_SUFFIX
+ case $(uname) in
+ Linux)
+ TOOL_SUFFIX=-6.0
+ ;;
+ Darwin)
+ TOOL_SUFFIX=
+ ;;
+ *)
+ TOOL_SUFFIX=-6.0
+ esac
+fi
+
+
+CLANG=clang${TOOL_SUFFIX}
+LLVM_PROFDATA=llvm-profdata${TOOL_SUFFIX}
+LLVM_COV=llvm-cov${TOOL_SUFFIX}
+
+if [ -z "$(which ${CLANG})" ]
+then
+ echo "${CLANG} doesn't exist. Try setting TOOL_SUFFIX environment variable"
+ exit 1
+fi
+
+if [ -z "$(which ${LLVM_PROFDATA})" ]
+then
+ echo "${LLVM_PROFDATA} doesn't exist. Try setting TOOL_SUFFIX environment variable"
+ exit 1
+fi
+
+if [ -z "$(which ${LLVM_COV})" ]
+then
+ echo "${LLVM_COV} doesn't exist. Try setting TOOL_SUFFIX environment variable"
+ exit 1
+fi
+
+echo "using ${CLANG}, ${LLVM_PROFDATA} and ${LLVM_COV}"
+
+export LLVM_PROFILE_FILE="passbook-%m.profraw"
+
+if [ $# -lt 1 ]
+then
+ echo "Usage: $0 inputfile1 [inputfile2 ...]"
+ exit 1
+fi
+
+
+rm -f passbook*.profraw passbook.profdata
+
+echo "First re-building to make sure -DNDEBUG is turned on..."
+rm -f passbook-cov
+CLANG=${CLANG} CFLAGS="-DNDEBUG ${CFLAGS}" make passbook-cov
+
+./passbook-cov $*
+
+${LLVM_PROFDATA} merge -sparse passbook*.profraw -o passbook.profdata
+${LLVM_COV} show ./passbook-cov -instr-profile=passbook.profdata
+${LLVM_COV} report ./passbook-cov -instr-profile=passbook.profdata
diff --git a/src/passbook.c b/src/passbook.c
index a4e8438..072b1ce 100644
--- a/src/passbook.c
+++ b/src/passbook.c
@@ -5,6 +5,13 @@
#include "debug.h"
+#ifdef PASSBOOK_LIBFUZZER
+#include <stdint.h>
+const char LIBFUZZER_INPUT_FILE[] = "libFuzzerInput.tmp";
+/* turn off tracing to make it run faster */
+#define printf(...)
+#define fprintf(...)
+#endif
const char INSTRUCTION_PUT[] = "put";
@@ -88,12 +95,19 @@ static node_t * node_insert(node_t *p, node_t *q){
if (p == NULL){
return q;
}
-
+ if (q == NULL){
+ return p;
+ }
/* we store a pointer to a node pointer that remembers where in the
tree the new node needs to be added */
node_t ** new = NULL;
node_t * const start = p;
while (new == NULL) {
+ assert(q->url != NULL);
+ assert(p->url != NULL);
+ printf("Addr of dodgy node: %08x\n",(unsigned int)q);
+ strlen(q->url); // SEGV here
+ strlen(p->url);
int ret = strcmp(q->url,p->url);
if (ret == 0){
assert (q->left == NULL && q->right == NULL && "illegal insertion");
@@ -123,6 +137,7 @@ static node_t * node_insert(node_t *p, node_t *q){
/* returns a pointer to the tree with the node added or with the existing
node updated if it was already present */
static node_t * put(node_t *p, const char *url, const cred_t cred){
+ strlen(url);
return node_insert(p,node_new(url,cred));
}
@@ -529,7 +544,17 @@ static int run(FILE *f){
return 0;
}
-
+#ifdef PASSBOOK_LIBFUZZER
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ FILE *f = fopen(LIBFUZZER_INPUT_FILE,"w");
+ fwrite(Data,Size,1,f);
+ fclose(f);
+ f = fopen(LIBFUZZER_INPUT_FILE,"r");
+ run(f);
+ fclose(f);
+ return 0; /* libFuzzer wants 0 returned always */
+}
+#else
int main(const int argc, const char * argv[]){
cred_t cred1, cred2;
cred1.password = "asdfa";
@@ -553,6 +578,7 @@ int main(const int argc, const char * argv[]){
}
for (int i = 1; i<argc; i++){
+ printf("Running on input file %s\n",argv[i]);
FILE *f;
if (strcmp(argv[i],"-") == 0){
f = stdin;
@@ -566,7 +592,6 @@ int main(const int argc, const char * argv[]){
int ans = run(f);
if (ans < 0){
fprintf(stderr,"Error\n");
- exit(1);
}
/* do not close stdin */
if (f != stdin){
@@ -575,3 +600,4 @@ int main(const int argc, const char * argv[]){
}
return 0;
}
+#endif
--
GitLab