diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c9d1d41f01ef2c55bc1cad746e733fe0c84066bf --- /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 0000000000000000000000000000000000000000..6768421d37de15b266e5c92b5bd437755313a514 --- /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 a4e843882c826429691c03f7171ba35d01a1dee6..072b1ceb496f6a8a25c0a20b62c059b3505bd8d6 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