diff options
-rw-r--r-- | Makefile.in | 5 | ||||
-rw-r--r-- | fuzz-wrapfd.h | 4 | ||||
-rw-r--r-- | fuzz.h | 2 | ||||
-rw-r--r-- | fuzz/fuzz-common.c | 34 | ||||
-rw-r--r-- | fuzz/fuzz-wrapfd.c | 25 | ||||
-rw-r--r-- | fuzz/fuzzer-postauth_nomaths.c | 6 | ||||
-rw-r--r-- | fuzz/fuzzer-preauth.c | 2 | ||||
-rw-r--r-- | fuzz/fuzzer-preauth_nomaths.c | 2 | ||||
-rw-r--r-- | fuzz/fuzzer-pubkey.c | 2 | ||||
-rw-r--r-- | netio.c | 6 |
10 files changed, 72 insertions, 16 deletions
diff --git a/Makefile.in b/Makefile.in index 113a0fb..5d73db4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -269,7 +269,8 @@ lint: # list of fuzz targets FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \ - fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths + fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths \ + fuzzer-postauth_nomaths FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \ @@ -294,7 +295,7 @@ $(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS) # fuzzers that use the custom mutator - these expect a SSH network stream MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \ - fuzzer-preauth fuzzer-preauth_nomaths + fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths $(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o fuzzer-%.options: Makefile diff --git a/fuzz-wrapfd.h b/fuzz-wrapfd.h index 60c66a7..56bbc6e 100644 --- a/fuzz-wrapfd.h +++ b/fuzz-wrapfd.h @@ -6,12 +6,14 @@ enum wrapfd_mode { UNUSED = 0, COMMONBUF, // using the common buffer + DUMMY, // reads return fixed output, of random length }; // buf is a common buffer read by all wrapped FDs. doesn't take ownership of buf void wrapfd_setup(buffer *buf); void wrapfd_setseed(uint32_t seed); -int wrapfd_new(); +int wrapfd_new_fuzzinput(); +int wrapfd_new_dummy(); // called via #defines for read/write/select int wrapfd_read(int fd, void *out, size_t count); @@ -23,7 +23,7 @@ void fuzz_early_setup(void) __attribute__((constructor)); // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE int fuzz_set_input(const uint8_t *Data, size_t Size); -int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths); +int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int authdone); int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths); const void* fuzz_get_algo(const algo_type *algos, const char* name); diff --git a/fuzz/fuzz-common.c b/fuzz/fuzz-common.c index 18e8a29..d1ada9a 100644 --- a/fuzz/fuzz-common.c +++ b/fuzz/fuzz-common.c @@ -217,16 +217,31 @@ void fuzz_fake_send_kexdh_reply(void) { /* fake version of spawn_command() */ int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) { - *ret_writefd = wrapfd_new(); - *ret_readfd = wrapfd_new(); + *ret_writefd = wrapfd_new_dummy(); + *ret_readfd = wrapfd_new_dummy(); if (ret_errfd) { - *ret_errfd = wrapfd_new(); + *ret_errfd = wrapfd_new_dummy(); } *ret_pid = 999; return DROPBEAR_SUCCESS; } -int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { + +struct dropbear_progress_connection *fuzz_connect_remote(const char* UNUSED(remotehost), const char* UNUSED(remoteport), + connect_callback cb, void* cb_data, + const char* UNUSED(bind_address), const char* UNUSED(bind_port)) { + char r; + genrandom((void*)&r, 1); + if (r & 1) { + int sock = wrapfd_new_dummy(); + cb(DROPBEAR_SUCCESS, sock, cb_data, NULL); + } else { + cb(DROPBEAR_FAILURE, -1, cb_data, "errorstring"); + } + return NULL; +} + +int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int authdone) { static int once = 0; if (!once) { fuzz_svr_setup(); @@ -242,7 +257,13 @@ int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { genrandom((void*)&wrapseed, sizeof(wrapseed)); wrapfd_setseed(wrapseed); - int fakesock = wrapfd_new(); + int fakesock = wrapfd_new_fuzzinput(); + + if (authdone) { + ses.authstate.authdone = 1; + char *me = getpwuid(getuid())->pw_name; + fill_passwd(me); + } m_malloc_set_epoch(1); fuzz.do_jmp = 1; @@ -273,12 +294,13 @@ int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) { // Allow to proceed sooner ses.kexstate.donefirstkex = 1; + ses.kexstate.authdone = 1; uint32_t wrapseed; genrandom((void*)&wrapseed, sizeof(wrapseed)); wrapfd_setseed(wrapseed); - int fakesock = wrapfd_new(); + int fakesock = wrapfd_new_fuzzinput(); m_malloc_set_epoch(1); fuzz.do_jmp = 1; diff --git a/fuzz/fuzz-wrapfd.c b/fuzz/fuzz-wrapfd.c index c6d59fc..02f293d 100644 --- a/fuzz/fuzz-wrapfd.c +++ b/fuzz/fuzz-wrapfd.c @@ -35,7 +35,7 @@ void wrapfd_setup(buffer *buf) { // clean old ones int i; for (i = 0; i <= wrapfd_maxfd; i++) { - if (wrap_fds[i].mode == COMMONBUF) { + if (wrap_fds[i].mode != UNUSED) { wrapfd_remove(i); } } @@ -51,7 +51,7 @@ void wrapfd_setseed(uint32_t seed) { nrand48(rand_state); } -int wrapfd_new() { +int wrapfd_new_fuzzinput() { if (devnull_fd == -1) { devnull_fd = open("/dev/null", O_RDONLY); assert(devnull_fd != -1); @@ -68,6 +68,24 @@ int wrapfd_new() { return fd; } +int wrapfd_new_dummy() { + if (devnull_fd == -1) { + devnull_fd = open("/dev/null", O_RDONLY); + assert(devnull_fd != -1); + } + + int fd = dup(devnull_fd); + assert(fd != -1); + assert(wrap_fds[fd].mode == UNUSED); + wrap_fds[fd].mode = DUMMY; + wrap_fds[fd].closein = 0; + wrap_fds[fd].closeout = 0; + wrapfd_maxfd = MAX(fd, wrapfd_maxfd); + + return fd; +} + + static void wrapfd_remove(int fd) { TRACE(("wrapfd_remove %d", fd)) assert(fd >= 0); @@ -113,7 +131,7 @@ int wrapfd_read(int fd, void *out, size_t count) { return -1; } - if (input_buf) { + if (input_buf && wrap_fds[fd].mode == COMMONBUF) { maxread = MIN(input_buf->len - input_buf->pos, count); /* returns 0 if buf is EOF, as intended */ if (maxread > 0) { @@ -124,6 +142,7 @@ int wrapfd_read(int fd, void *out, size_t count) { return maxread; } + // return fixed output, of random length maxread = MIN(MAX_RANDOM_IN, count); maxread = nrand48(rand_state) % maxread + 1; memset(out, 0xef, maxread); diff --git a/fuzz/fuzzer-postauth_nomaths.c b/fuzz/fuzzer-postauth_nomaths.c new file mode 100644 index 0000000..b8b7c6b --- /dev/null +++ b/fuzz/fuzzer-postauth_nomaths.c @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_server(Data, Size, 1, 1); +} + diff --git a/fuzz/fuzzer-preauth.c b/fuzz/fuzzer-preauth.c index 3ac49f4..f3cbdcb 100644 --- a/fuzz/fuzzer-preauth.c +++ b/fuzz/fuzzer-preauth.c @@ -1,6 +1,6 @@ #include "fuzz.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - return fuzz_run_preauth(Data, Size, 0); + return fuzz_run_server(Data, Size, 0, 0); } diff --git a/fuzz/fuzzer-preauth_nomaths.c b/fuzz/fuzzer-preauth_nomaths.c index efdc2c3..bab5f2b 100644 --- a/fuzz/fuzzer-preauth_nomaths.c +++ b/fuzz/fuzzer-preauth_nomaths.c @@ -1,6 +1,6 @@ #include "fuzz.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - return fuzz_run_preauth(Data, Size, 1); + return fuzz_run_server(Data, Size, 1, 0); } diff --git a/fuzz/fuzzer-pubkey.c b/fuzz/fuzzer-pubkey.c index 7c12cdc..3b00478 100644 --- a/fuzz/fuzzer-pubkey.c +++ b/fuzz/fuzzer-pubkey.c @@ -27,7 +27,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { unsigned int algolen; char* algoname = buf_getstring(keyblob, &algolen); - if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) { + if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNATURE_NONE) { dropbear_exit("fuzzer imagined a bogus algorithm"); } @@ -179,6 +179,12 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons int err; struct addrinfo hints; +#if DROPBEAR_FUZZ + if (fuzz.fuzzing) { + return fuzz_connect_remote(remotehost, remoteport, cb, cb_data, bind_address, bind_port); + } +#endif + c = m_malloc(sizeof(*c)); c->remotehost = m_strdup(remotehost); c->remoteport = m_strdup(remoteport); |