# HG changeset patch # User Matt Johnston # Date 1603723927 -28800 # Node ID b688c884dad706fb45a874091fce146b663b8392 # Parent a339b1c4b9f2608e532d382ecb0d975296fed48f Fix fuzz-sshpacketmutator to work diff -r a339b1c4b9f2 -r b688c884dad7 Makefile.in --- a/Makefile.in Mon Oct 26 22:51:44 2020 +0800 +++ b/Makefile.in Mon Oct 26 22:52:07 2020 +0800 @@ -273,7 +273,8 @@ fuzzer-client_mutator FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) -FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) +FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \ + fuzz/fuzz-sshpacketmutator.o list-fuzz-targets: @echo $(FUZZ_TARGETS) @@ -292,6 +293,8 @@ $(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS) $(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) -lcrypt +fuzzer-client_mutator: allobjs += fuzz/fuzz-sshpacketmutator.o + fuzzer-%.options: Makefile echo "[libfuzzer]" > $@ echo "max_len = 50000" >> $@ diff -r a339b1c4b9f2 -r b688c884dad7 buffer.c --- a/buffer.c Mon Oct 26 22:51:44 2020 +0800 +++ b/buffer.c Mon Oct 26 22:52:07 2020 +0800 @@ -188,6 +188,7 @@ unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len) { if (len > BUF_MAX_INCR || buf->pos + len > buf->size) { + abort(); dropbear_exit("Bad buf_getwriteptr"); } return &buf->data[buf->pos]; diff -r a339b1c4b9f2 -r b688c884dad7 fuzz/fuzz-common.c --- a/fuzz/fuzz-common.c Mon Oct 26 22:51:44 2020 +0800 +++ b/fuzz/fuzz-common.c Mon Oct 26 22:52:07 2020 +0800 @@ -45,9 +45,9 @@ else #endif { - fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n"); - fuzz.stderr = fopen("/dev/null", "w"); - assert(fuzz.stderr); + // fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n"); + // fuzz.stderr = fopen("/dev/null", "w"); + // assert(fuzz.stderr); } } diff -r a339b1c4b9f2 -r b688c884dad7 fuzz/fuzz-sshpacketmutator.c --- a/fuzz/fuzz-sshpacketmutator.c Mon Oct 26 22:51:44 2020 +0800 +++ b/fuzz/fuzz-sshpacketmutator.c Mon Oct 26 22:52:07 2020 +0800 @@ -1,4 +1,5 @@ #include "fuzz.h" +#include "dbutil.h" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); @@ -11,7 +12,7 @@ buf_incrpos(inp, version - inp->data); unsigned char* newline = memchr(&inp->data[inp->pos], '\n', inp->len - inp->pos); if (newline) { - buf_incrpos(inp, newline - &inp->data[inp->pos]); + buf_incrpos(inp, newline - &inp->data[inp->pos]+1); } else { /* Give up on any version string */ buf_setpos(inp, 0); @@ -32,8 +33,11 @@ } /* Read packet */ + //printf("at %d\n", inp->pos); + //printhex("lenget", buf_getptr(inp, 48), 48); unsigned int packet_len = buf_getint(inp); - if (packet_len <= RECV_MAX_PACKET_LEN) { + // printf("len %u\n", packet_len); + if (packet_len > RECV_MAX_PACKET_LEN-4) { /* Bad length, try skipping a single byte */ buf_decrpos(inp, 3); continue; @@ -45,11 +49,11 @@ buf_putint(new_packet, packet_len); buf_putbytes(new_packet, buf_getptr(inp, packet_len), packet_len); buf_incrpos(inp, packet_len); + // printf("incr pos %d to %d\n", packet_len, inp->pos); out_packets[*num_out_packets] = new_packet; (*num_out_packets)++; } - } /* Mutate in-place */ @@ -76,22 +80,51 @@ size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) { - int i; + + /* Avoid some allocations */ + /* XXX perhaps this complication isn't worthwhile */ + static buffer buf_oup, buf_alloc_packetA, buf_alloc_packetB; + static buffer *oup = &buf_oup; + static buffer *alloc_packetA = &buf_alloc_packetA; + static buffer *alloc_packetB = &buf_alloc_packetB; + static int once = 1; + if (once) { + once = 0; + // malloc doesn't get intercepted by epoch deallocator + oup->size = MAX_OUT_SIZE; + alloc_packetA->size = RECV_MAX_PACKET_LEN; + alloc_packetB->size = RECV_MAX_PACKET_LEN; + oup->data = malloc(oup->size); + alloc_packetA->data = malloc(alloc_packetA->size); + alloc_packetB->data = malloc(alloc_packetB->size); + } + alloc_packetA->pos = 0; + alloc_packetA->len = 0; + alloc_packetB->pos = 0; + alloc_packetB->len = 0; + oup->pos = 0; + oup->len = 0; + + unsigned int i; unsigned short randstate[3] = {0,0,0}; memcpy(randstate, &Seed, sizeof(Seed)); + // printhex("mutator input", Data, Size); + #if 0 /* 1% chance straight llvm mutate */ if (nrand48(randstate) % 100 == 0) { return LLVMFuzzerMutate(Data, Size, MaxSize); } + #endif buffer inp_buf = {.data = Data, .size = Size, .len = Size, .pos = 0}; buffer *inp = &inp_buf; /* Parse packets */ - buffer* packets[MAX_FUZZ_PACKETS] = {0}; + buffer* packets[MAX_FUZZ_PACKETS]; unsigned int num_packets = MAX_FUZZ_PACKETS; fuzz_get_packets(inp, packets, &num_packets); + // printf("%d packets\n", num_packets); if (num_packets == 0) { // gotta do something @@ -100,7 +133,6 @@ } /* Start output */ - buffer *oup = buf_new(MAX_OUT_SIZE); /* Put a new banner to output */ buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION)); @@ -108,42 +140,46 @@ for (i = 0; i < num_packets+1; i++) { // These are pointers to output buffer *out_packetA = NULL, *out_packetB = NULL; - // These need to be freed - buffer *alloc_packetA = NULL, *alloc_packetB = NULL; + alloc_packetA->pos = 0; + alloc_packetA->len = 0; + alloc_packetB->pos = 0; + alloc_packetB->len = 0; /* 5% chance each */ const int optA = nrand48(randstate) % 20; - const int other = nrand48(randstate) % num_packets; if (optA == 0) { /* Copy another */ - out_packetA = packets[nrand48(randstate) % num_packets]; + unsigned int other = nrand48(randstate) % num_packets; + out_packetA = packets[other]; + // printf("%d copy another %d\n", i, other); } if (optA == 1) { /* Mutate another */ - alloc_packetA = buf_new(RECV_MAX_PACKET_LEN); - buffer *from = packets[nrand48(randstate) % num_packets]; + unsigned int other = nrand48(randstate) % num_packets; + buffer *from = packets[other]; buf_putbytes(alloc_packetA, from->data, from->len); out_packetA = alloc_packetA; buf_llvm_mutate(out_packetA); + // printf("%d mutate another %d\n", i, other); } - /* 10% chance each of mutate or drop */ if (i < num_packets) { int optB = nrand48(randstate) % 10; - if (optB == 0) { - /* Copy as-is */ - out_packetB = packets[i]; - } if (optB == 1) { + /* 10% chance of drop */ /* Drop it */ - } - if (optB == 2) { - /* Mutate it */ - alloc_packetB = buf_new(RECV_MAX_PACKET_LEN); + // printf("%d drop\n", i); + } else if (optB <= 6) { + /* Mutate it, 50% chance */ + // printf("%d mutate\n", i); buffer *from = packets[nrand48(randstate) % num_packets]; buf_putbytes(alloc_packetB, from->data, from->len); out_packetB = alloc_packetB; buf_llvm_mutate(out_packetB); + } else { + /* Copy as-is */ + out_packetB = packets[i]; + // printf("%d as-is\n", i); } } @@ -153,14 +189,6 @@ if (out_packetB && oup->len + out_packetB->len <= oup->size) { buf_putbytes(oup, out_packetB->data, out_packetB->len); } - if (alloc_packetA) { - buf_free(alloc_packetA); - alloc_packetA = NULL; - } - if (alloc_packetB) { - buf_free(alloc_packetB); - alloc_packetB = NULL; - } } for (i = 0; i < num_packets; i++) { @@ -169,7 +197,8 @@ size_t ret_len = MIN(MaxSize, oup->len); memcpy(Data, oup->data, ret_len); - buf_free(oup); + // printhex("mutator done", Data, ret_len); return ret_len; } + diff -r a339b1c4b9f2 -r b688c884dad7 fuzz/fuzzer-client_mutator.c --- a/fuzz/fuzzer-client_mutator.c Mon Oct 26 22:51:44 2020 +0800 +++ b/fuzz/fuzzer-client_mutator.c Mon Oct 26 22:52:07 2020 +0800 @@ -1,7 +1,5 @@ #include "fuzz.h" -#include "fuzz-sshpacketmutator.c" - int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return fuzz_run_client(Data, Size, 0); }