diff options
author | Matt Johnston <matt@ucc.asn.au> | 2020-10-18 22:53:44 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2020-10-18 22:53:44 +0800 |
commit | 6ca24af24afe3a3572e9d043df3f8342d38c84b1 (patch) | |
tree | b06b58a6f94bd2827d023f0de10e7f3843a6e28c | |
parent | 17873e8c922eded2cec86184673a6d110df6403f (diff) | |
parent | 400c7c161f8fd4859f557339f77025044ec950e0 (diff) |
Merge fuzz branch
-rw-r--r-- | Makefile.in | 28 | ||||
-rw-r--r-- | cli-kex.c | 13 | ||||
-rw-r--r-- | cli-main.c | 57 | ||||
-rw-r--r-- | cli-session.c | 65 | ||||
-rw-r--r-- | common-kex.c | 6 | ||||
-rw-r--r-- | dbutil.c | 7 | ||||
-rw-r--r-- | fuzz-common.c | 89 | ||||
-rw-r--r-- | fuzz-harness.c | 2 | ||||
-rw-r--r-- | fuzz-wrapfd.c | 72 | ||||
-rw-r--r-- | fuzz-wrapfd.h | 10 | ||||
-rw-r--r-- | fuzz.h | 11 | ||||
-rw-r--r-- | fuzzer-client.c | 6 | ||||
-rw-r--r-- | fuzzer-client_nomaths.c | 6 | ||||
-rw-r--r-- | session.h | 2 |
14 files changed, 244 insertions, 130 deletions
diff --git a/Makefile.in b/Makefile.in index 145617b..fae4cf3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -268,7 +268,8 @@ lint: ## Fuzzing targets # list of fuzz targets -FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 +FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \ + fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) @@ -279,10 +280,7 @@ list-fuzz-targets: fuzzstandalone: FUZZLIB=fuzz-harness.o fuzzstandalone: fuzz-harness.o fuzz-targets -# exclude svr-main.o to avoid duplicate main -svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs)) - -fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o +fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(allobjs) fuzz-common.o # build all the fuzzers. This will require fail to link unless built with # make fuzz-targets FUZZLIB=-lFuzzer.a @@ -290,25 +288,31 @@ fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) fuzz-common.o fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS) fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-verify: fuzzer-verify.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + +fuzzer-client: fuzzer-client.o fuzz-harness.o + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + +fuzzer-client_nomaths: fuzzer-client_nomaths.o fuzz-harness.o + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ fuzzer-%.options: Makefile echo "[libfuzzer]" > $@ @@ -46,6 +46,13 @@ void send_msg_kexdh_init() { TRACE(("send_msg_kexdh_init()")) CHECKCLEARTOWRITE(); + +#if DROPBEAR_FUZZ + if (fuzz.fuzzing && fuzz.skip_kexmaths) { + return; + } +#endif + buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); switch (ses.newkeys->algo_kex->mode) { #if DROPBEAR_NORMAL_DH @@ -98,6 +105,12 @@ void recv_msg_kexdh_reply() { unsigned char* keyblob = NULL; TRACE(("enter recv_msg_kexdh_reply")) + +#if DROPBEAR_FUZZ + if (fuzz.fuzzing && fuzz.skip_kexmaths) { + return; + } +#endif if (cli_ses.kex_state != KEXDH_INIT_SENT) { dropbear_exit("Received out-of-order kexdhreply"); @@ -31,9 +31,7 @@ #include "dbrandom.h" #include "crypto_desc.h" #include "netio.h" - -static void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN; -static void cli_dropbear_log(int priority, const char* format, va_list param); +#include "fuzz.h" #if DROPBEAR_CLI_PROXYCMD static void cli_proxy_cmd(int *sock_in, int *sock_out, pid_t *pid_out); @@ -98,58 +96,6 @@ int main(int argc, char ** argv) { } #endif /* DBMULTI stuff */ -static void cli_dropbear_exit(int exitcode, const char* format, va_list param) { - char exitmsg[150]; - char fullmsg[300]; - - /* Note that exit message must be rendered before session cleanup */ - - /* Render the formatted exit message */ - vsnprintf(exitmsg, sizeof(exitmsg), format, param); - TRACE(("Exited, cleaning up: %s", exitmsg)) - - /* Add the prefix depending on session/auth state */ - if (!ses.init_done) { - snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg); - } else { - snprintf(fullmsg, sizeof(fullmsg), - "Connection to %s@%s:%s exited: %s", - cli_opts.username, cli_opts.remotehost, - cli_opts.remoteport, exitmsg); - } - - /* Do the cleanup first, since then the terminal will be reset */ - session_cleanup(); - /* Avoid printing onwards from terminal cruft */ - fprintf(stderr, "\n"); - - dropbear_log(LOG_INFO, "%s", fullmsg); - exit(exitcode); -} - -static void cli_dropbear_log(int priority, - const char* format, va_list param) { - - char printbuf[1024]; - const char *name; - - name = cli_opts.progname; - if (!name) { - name = "dbclient"; - } - - vsnprintf(printbuf, sizeof(printbuf), format, param); - -#ifndef DISABLE_SYSLOG - if (opts.usingsyslog) { - syslog(priority, "%s", printbuf); - } -#endif - - fprintf(stderr, "%s: %s\n", name, printbuf); - fflush(stderr); -} - static void exec_proxy_cmd(const void *user_data_cmd) { const char *cmd = user_data_cmd; char *usershell; @@ -199,4 +145,5 @@ static void kill_proxy_sighandler(int UNUSED(signo)) { kill_proxy_command(); _exit(1); } + #endif /* DROPBEAR_CLI_PROXYCMD */ diff --git a/cli-session.c b/cli-session.c index f42ea90..5e5af22 100644 --- a/cli-session.c +++ b/cli-session.c @@ -352,6 +352,11 @@ static void cli_session_cleanup(void) { (void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags); (void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags); + /* Don't leak */ + m_close(cli_ses.stdincopy); + m_close(cli_ses.stdoutcopy); + m_close(cli_ses.stderrcopy); + cli_tty_cleanup(); if (cli_ses.server_sig_algs) { buf_free(cli_ses.server_sig_algs); @@ -407,3 +412,63 @@ static void recv_msg_global_request_cli(void) { /* Send a proper rejection */ send_msg_request_failure(); } + +void cli_dropbear_exit(int exitcode, const char* format, va_list param) { + char exitmsg[150]; + char fullmsg[300]; + + /* Note that exit message must be rendered before session cleanup */ + + /* Render the formatted exit message */ + vsnprintf(exitmsg, sizeof(exitmsg), format, param); + TRACE(("Exited, cleaning up: %s", exitmsg)) + + /* Add the prefix depending on session/auth state */ + if (!ses.init_done) { + snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg); + } else { + snprintf(fullmsg, sizeof(fullmsg), + "Connection to %s@%s:%s exited: %s", + cli_opts.username, cli_opts.remotehost, + cli_opts.remoteport, exitmsg); + } + + /* Do the cleanup first, since then the terminal will be reset */ + session_cleanup(); + +#if DROPBEAR_FUZZ + if (fuzz.do_jmp) { + longjmp(fuzz.jmp, 1); + } +#endif + + /* Avoid printing onwards from terminal cruft */ + fprintf(stderr, "\n"); + + dropbear_log(LOG_INFO, "%s", fullmsg); + + exit(exitcode); +} + +void cli_dropbear_log(int priority, const char* format, va_list param) { + + char printbuf[1024]; + const char *name; + + name = cli_opts.progname; + if (!name) { + name = "dbclient"; + } + + vsnprintf(printbuf, sizeof(printbuf), format, param); + +#ifndef DISABLE_SYSLOG + if (opts.usingsyslog) { + syslog(priority, "%s", printbuf); + } +#endif + + fprintf(stderr, "%s: %s\n", name, printbuf); + fflush(stderr); +} + diff --git a/common-kex.c b/common-kex.c index 4caa06e..39d916b 100644 --- a/common-kex.c +++ b/common-kex.c @@ -487,6 +487,12 @@ void recv_msg_kexinit() { TRACE(("continue recv_msg_kexinit: sent kexinit")) } + /* "Once a party has sent a SSH_MSG_KEXINIT message ... + further SSH_MSG_KEXINIT messages MUST NOT be sent" */ + if (ses.kexstate.recvkexinit) { + dropbear_exit("Unexpected KEXINIT"); + } + /* start the kex hash */ local_ident_len = strlen(LOCAL_IDENT); remote_ident_len = strlen(ses.remoteident); @@ -121,7 +121,6 @@ static void generic_dropbear_exit(int exitcode, const char* format, _dropbear_log(LOG_INFO, fmtbuf, param); #if DROPBEAR_FUZZ - /* longjmp before cleaning up svr_opts */ if (fuzz.do_jmp) { longjmp(fuzz.jmp, 1); } @@ -258,6 +257,12 @@ int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data, const int FDIN = 0; const int FDOUT = 1; +#if DROPBEAR_FUZZ + if (fuzz.fuzzing) { + return fuzz_spawn_command(ret_writefd, ret_readfd, ret_errfd, ret_pid); + } +#endif + /* redirect stdin/stdout/stderr */ if (pipe(infds) != 0) { return DROPBEAR_FAILURE; diff --git a/fuzz-common.c b/fuzz-common.c index c14fa66..95b3937 100644 --- a/fuzz-common.c +++ b/fuzz-common.c @@ -16,6 +16,7 @@ static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list static void load_fixed_hostkeys(void); void fuzz_common_setup(void) { + disallow_core(); fuzz.fuzzing = 1; fuzz.wrapfds = 1; fuzz.do_jmp = 1; @@ -36,7 +37,8 @@ int fuzz_set_input(const uint8_t *Data, size_t Size) { memset(&ses, 0x0, sizeof(ses)); memset(&svr_ses, 0x0, sizeof(svr_ses)); - wrapfd_setup(); + memset(&cli_ses, 0x0, sizeof(cli_ses)); + wrapfd_setup(fuzz.input); fuzz_seed(); @@ -63,21 +65,32 @@ void fuzz_svr_setup(void) { _dropbear_exit = svr_dropbear_exit; char *argv[] = { + "dropbear", "-E", }; int argc = sizeof(argv) / sizeof(*argv); svr_getopts(argc, argv); - /* user lookups might be slow, cache it */ - fuzz.pw_name = m_strdup("person"); - fuzz.pw_dir = m_strdup("/tmp"); - fuzz.pw_shell = m_strdup("/bin/zsh"); - fuzz.pw_passwd = m_strdup("!!zzznope"); - load_fixed_hostkeys(); } +void fuzz_cli_setup(void) { + fuzz_common_setup(); + + _dropbear_exit = cli_dropbear_exit; + _dropbear_log = cli_dropbear_log; + + char *argv[] = { + "dbclient", + "-y", + "localhost", + }; + + int argc = sizeof(argv) / sizeof(*argv); + cli_getopts(argc, argv); +} + static void load_fixed_hostkeys(void) { #include "fuzz-hostkeys.c" @@ -151,6 +164,17 @@ void fuzz_fake_send_kexdh_reply(void) { finish_kexhashbuf(); } +/* 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(); + if (ret_errfd) { + *ret_errfd = wrapfd_new(); + } + *ret_pid = 999; + return DROPBEAR_SUCCESS; +} + int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { static int once = 0; if (!once) { @@ -164,7 +188,7 @@ int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { } /* - get prefix. input format is + get prefix, allowing for future extensibility. input format is string prefix uint32 wrapfd seed ... to be extended later @@ -182,8 +206,7 @@ int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { uint32_t wrapseed = buf_getint(fuzz.input); wrapfd_setseed(wrapseed); - int fakesock = 20; - wrapfd_add(fakesock, fuzz.input, PLAIN); + int fakesock = wrapfd_new(); m_malloc_set_epoch(1); if (setjmp(fuzz.jmp) == 0) { @@ -198,6 +221,52 @@ int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { return 0; } +int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) { + static int once = 0; + if (!once) { + fuzz_cli_setup(); + fuzz.skip_kexmaths = skip_kexmaths; + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + /* + get prefix, allowing for future extensibility. input format is + string prefix + uint32 wrapfd seed + ... to be extended later + [bytes] ssh input stream + */ + + /* be careful to avoid triggering buffer.c assertions */ + if (fuzz.input->len < 8) { + return 0; + } + size_t prefix_size = buf_getint(fuzz.input); + if (prefix_size != 4) { + return 0; + } + uint32_t wrapseed = buf_getint(fuzz.input); + wrapfd_setseed(wrapseed); + + int fakesock = wrapfd_new(); + + m_malloc_set_epoch(1); + if (setjmp(fuzz.jmp) == 0) { + cli_session(fakesock, fakesock, NULL, 0); + m_malloc_free_epoch(1, 0); + } else { + m_malloc_free_epoch(1, 1); + TRACE(("dropbear_exit longjmped")) + /* dropbear_exit jumped here */ + } + + return 0; +} + const void* fuzz_get_algo(const algo_type *algos, const char* name) { const algo_type *t; for (t = algos; t->name; t++) { diff --git a/fuzz-harness.c b/fuzz-harness.c index be23d4e..ced707c 100644 --- a/fuzz-harness.c +++ b/fuzz-harness.c @@ -9,7 +9,6 @@ int main(int argc, char ** argv) { buffer *input = buf_new(100000); for (i = 1; i < argc; i++) { - printf("arg %s\n", argv[i]); #if DEBUG_TRACE if (strcmp(argv[i], "-v") == 0) { debug_trace = 1; @@ -30,6 +29,7 @@ int main(int argc, char ** argv) { buf_readfile(input, fn); buf_setpos(input, 0); + /* Run twice to catch problems with statefulness */ fuzz.wrapfds = old_fuzz_wrapfds; printf("Running %s once \n", fn); LLVMFuzzerTestOneInput(input->data, input->len); diff --git a/fuzz-wrapfd.c b/fuzz-wrapfd.c index ed8968a..dfae3c1 100644 --- a/fuzz-wrapfd.c +++ b/fuzz-wrapfd.c @@ -17,25 +17,33 @@ static const double CHANCE_WRITE2 = 0.5; struct fdwrap { enum wrapfd_mode mode; - buffer *buf; int closein; int closeout; }; -static struct fdwrap wrap_fds[IOWRAP_MAXFD+1]; -/* for quick selection of in-use descriptors */ -static int wrap_used[IOWRAP_MAXFD+1]; -static unsigned int nused; +static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {0}; +static int wrapfd_maxfd = -1; static unsigned short rand_state[3]; +static buffer *input_buf; +static int devnull_fd = -1; + +static void wrapfd_remove(int fd); -void wrapfd_setup(void) { +void wrapfd_setup(buffer *buf) { TRACE(("wrapfd_setup")) - nused = 0; - memset(wrap_fds, 0x0, sizeof(wrap_fds)); - memset(wrap_used, 0x0, sizeof(wrap_used)); + + // clean old ones + int i; + for (i = 0; i <= wrapfd_maxfd; i++) { + if (wrap_fds[i].mode == COMMONBUF) { + wrapfd_remove(i); + } + } + wrapfd_maxfd = -1; memset(rand_state, 0x0, sizeof(rand_state)); wrapfd_setseed(50); + input_buf = buf; } void wrapfd_setseed(uint32_t seed) { @@ -43,39 +51,30 @@ void wrapfd_setseed(uint32_t seed) { nrand48(rand_state); } -void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) { - TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode)) - assert(fd >= 0); - assert(fd <= IOWRAP_MAXFD); - assert(wrap_fds[fd].mode == UNUSED); - assert(buf || mode == RANDOMIN); +int wrapfd_new() { + if (devnull_fd == -1) { + devnull_fd = open("/dev/null", O_RDONLY); + assert(devnull_fd != -1); + } - wrap_fds[fd].mode = mode; - wrap_fds[fd].buf = buf; + int fd = dup(devnull_fd); + assert(fd != -1); + assert(wrap_fds[fd].mode == UNUSED); + wrap_fds[fd].mode = COMMONBUF; wrap_fds[fd].closein = 0; wrap_fds[fd].closeout = 0; - wrap_used[nused] = fd; + wrapfd_maxfd = MAX(fd, wrapfd_maxfd); - nused++; + return fd; } -void wrapfd_remove(int fd) { - unsigned int i, j; +static void wrapfd_remove(int fd) { TRACE(("wrapfd_remove %d", fd)) assert(fd >= 0); assert(fd <= IOWRAP_MAXFD); assert(wrap_fds[fd].mode != UNUSED); wrap_fds[fd].mode = UNUSED; - - - /* remove from used list */ - for (i = 0, j = 0; i < nused; i++) { - if (wrap_used[i] != fd) { - wrap_used[j] = wrap_used[i]; - j++; - } - } - nused--; + m_close(fd); } int wrapfd_close(int fd) { @@ -115,15 +114,14 @@ int wrapfd_read(int fd, void *out, size_t count) { return -1; } - buf = wrap_fds[fd].buf; - if (buf) { - maxread = MIN(buf->len - buf->pos, count); + if (input_buf) { + maxread = MIN(input_buf->len - input_buf->pos, count); /* returns 0 if buf is EOF, as intended */ if (maxread > 0) { maxread = nrand48(rand_state) % maxread + 1; } - memcpy(out, buf_getptr(buf, maxread), maxread); - buf_incrpos(buf, maxread); + memcpy(out, buf_getptr(input_buf, maxread), maxread); + buf_incrpos(input_buf, maxread); return maxread; } @@ -175,8 +173,6 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, int ret = 0; int fdlist[IOWRAP_MAXFD+1]; - memset(fdlist, 0x0, sizeof(fdlist)); - if (!fuzz.wrapfds) { return select(nfds, readfds, writefds, exceptfds, timeout); } diff --git a/fuzz-wrapfd.h b/fuzz-wrapfd.h index 7aed43a..60c66a7 100644 --- a/fuzz-wrapfd.h +++ b/fuzz-wrapfd.h @@ -5,15 +5,13 @@ enum wrapfd_mode { UNUSED = 0, - PLAIN, - INPROGRESS, - RANDOMIN + COMMONBUF, // using the common buffer }; -void wrapfd_setup(void); +// 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); -// doesn't take ownership of buf. buf is optional. -void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode); +int wrapfd_new(); // called via #defines for read/write/select int wrapfd_read(int fd, void *out, size_t count); @@ -13,6 +13,7 @@ // once per process void fuzz_common_setup(void); void fuzz_svr_setup(void); +void fuzz_cli_setup(void); // must be called once per fuzz iteration. // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE @@ -28,9 +29,12 @@ int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename, const unsigned char* keyblob, unsigned int keybloblen); extern const char * const * fuzz_signkey_names; void fuzz_seed(void); + +// helpers void fuzz_get_socket_address(int fd, char **local_host, char **local_port, char **remote_host, char **remote_port, int host_lookup); void fuzz_fake_send_kexdh_reply(void); +int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid); // fake IO wrappers #ifndef FUZZ_SKIP_WRAP @@ -56,13 +60,6 @@ struct dropbear_fuzz_options { // dropbear_exit() jumps back int do_jmp; sigjmp_buf jmp; - - uid_t pw_uid; - gid_t pw_gid; - char* pw_name; - char* pw_dir; - char* pw_shell; - char* pw_passwd; }; extern struct dropbear_fuzz_options fuzz; diff --git a/fuzzer-client.c b/fuzzer-client.c new file mode 100644 index 0000000..eb59f46 --- /dev/null +++ b/fuzzer-client.c @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_client(Data, Size, 0); +} + diff --git a/fuzzer-client_nomaths.c b/fuzzer-client_nomaths.c new file mode 100644 index 0000000..e0910a7 --- /dev/null +++ b/fuzzer-client_nomaths.c @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_client(Data, Size, 1); +} + @@ -64,6 +64,8 @@ void svr_dropbear_log(int priority, const char* format, va_list param); /* Client */ void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) ATTRIB_NORETURN; void cli_connected(int result, int sock, void* userdata, const char *errstring); +void cli_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN; +void cli_dropbear_log(int priority, const char* format, va_list param); void cleantext(char* dirtytext); void kill_proxy_command(void); |