# HG changeset patch # User Matt Johnston # Date 1602994659 -28800 # Node ID d1b279aa5ed1dd5dad43c9c2760aed5c778f99bc # Parent dfbe947bdf0db8030bfe880dc557f47bc5211519 Get client fuzzer building and starting (fails straight away) diff -r dfbe947bdf0d -r d1b279aa5ed1 Makefile.in --- a/Makefile.in Thu Oct 15 22:46:24 2020 +0800 +++ b/Makefile.in Sun Oct 18 12:17:39 2020 +0800 @@ -268,7 +268,8 @@ ## 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_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) @@ -279,10 +280,7 @@ 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,28 @@ 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-%.options: Makefile echo "[libfuzzer]" > $@ diff -r dfbe947bdf0d -r d1b279aa5ed1 cli-main.c --- a/cli-main.c Thu Oct 15 22:46:24 2020 +0800 +++ b/cli-main.c Sun Oct 18 12:17:39 2020 +0800 @@ -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 @@ } #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 @@ kill_proxy_command(); _exit(1); } + #endif /* DROPBEAR_CLI_PROXYCMD */ diff -r dfbe947bdf0d -r d1b279aa5ed1 cli-session.c --- a/cli-session.c Thu Oct 15 22:46:24 2020 +0800 +++ b/cli-session.c Sun Oct 18 12:17:39 2020 +0800 @@ -407,3 +407,62 @@ /* 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(); + /* Avoid printing onwards from terminal cruft */ + fprintf(stderr, "\n"); + + dropbear_log(LOG_INFO, "%s", fullmsg); + +#if DROPBEAR_FUZZ + if (fuzz.do_jmp) { + longjmp(fuzz.jmp, 1); + } +#endif + + 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 -r dfbe947bdf0d -r d1b279aa5ed1 fuzz-common.c --- a/fuzz-common.c Thu Oct 15 22:46:24 2020 +0800 +++ b/fuzz-common.c Sun Oct 18 12:17:39 2020 +0800 @@ -16,6 +16,7 @@ static void load_fixed_hostkeys(void); void fuzz_common_setup(void) { + disallow_core(); fuzz.fuzzing = 1; fuzz.wrapfds = 1; fuzz.do_jmp = 1; @@ -69,37 +70,23 @@ 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(); } -#if 0 void fuzz_cli_setup(void) { fuzz_common_setup(); - _dropbear_exit = cli_dropbear_exit; + _dropbear_exit = cli_dropbear_exit; + _dropbear_log = cli_dropbear_log; char *argv[] = { - "-E", + "-y", + "localhost", }; int argc = sizeof(argv) / sizeof(*argv); cli_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(); } -#endif static void load_fixed_hostkeys(void) { #include "fuzz-hostkeys.c" @@ -198,7 +185,7 @@ } /* - get prefix. input format is + get prefix, allowing for future extensibility. input format is string prefix uint32 wrapfd seed ... to be extended later @@ -231,6 +218,52 @@ 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 -r dfbe947bdf0d -r d1b279aa5ed1 fuzz-harness.c --- a/fuzz-harness.c Thu Oct 15 22:46:24 2020 +0800 +++ b/fuzz-harness.c Sun Oct 18 12:17:39 2020 +0800 @@ -29,6 +29,7 @@ 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 -r dfbe947bdf0d -r d1b279aa5ed1 fuzz.h --- a/fuzz.h Thu Oct 15 22:46:24 2020 +0800 +++ b/fuzz.h Sun Oct 18 12:17:39 2020 +0800 @@ -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,6 +29,8 @@ 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); @@ -57,13 +60,6 @@ // 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 -r dfbe947bdf0d -r d1b279aa5ed1 fuzzer-client.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzzer-client.c Sun Oct 18 12:17:39 2020 +0800 @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_client(Data, Size, 0); +} + diff -r dfbe947bdf0d -r d1b279aa5ed1 session.h --- a/session.h Thu Oct 15 22:46:24 2020 +0800 +++ b/session.h Sun Oct 18 12:17:39 2020 +0800 @@ -64,6 +64,8 @@ /* 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);