summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2020-10-15 22:46:24 +0800
committerMatt Johnston <matt@ucc.asn.au>2020-10-15 22:46:24 +0800
commit1c650c09bcb851abb19cb060aea4c905b514fea4 (patch)
treea59aeb4369f30868a4a3cba6b1e4c0bc3f8bd3b5
parent5057203a91f1a81b28b23749aa19cedc845e7d05 (diff)
downloaddropbear-1c650c09bcb851abb19cb060aea4c905b514fea4.tar.gz
Make wrapfd share a common buffer for all FDs
-rw-r--r--dbutil.c7
-rw-r--r--fuzz-common.c39
-rw-r--r--fuzz-harness.c1
-rw-r--r--fuzz-wrapfd.c61
-rw-r--r--fuzz-wrapfd.h10
-rw-r--r--fuzz.h1
6 files changed, 71 insertions, 48 deletions
diff --git a/dbutil.c b/dbutil.c
index 32920f7..5af6330 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -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..d099bff 100644
--- a/fuzz-common.c
+++ b/fuzz-common.c
@@ -36,7 +36,7 @@ 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();
+ wrapfd_setup(fuzz.input);
fuzz_seed();
@@ -78,6 +78,29 @@ void fuzz_svr_setup(void) {
load_fixed_hostkeys();
}
+#if 0
+void fuzz_cli_setup(void) {
+ fuzz_common_setup();
+
+ _dropbear_exit = cli_dropbear_exit;
+
+ char *argv[] = {
+ "-E",
+ };
+
+ 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"
@@ -151,6 +174,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) {
@@ -182,8 +216,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) {
diff --git a/fuzz-harness.c b/fuzz-harness.c
index be23d4e..eabc58a 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;
diff --git a/fuzz-wrapfd.c b/fuzz-wrapfd.c
index ed8968a..431c524 100644
--- a/fuzz-wrapfd.c
+++ b/fuzz-wrapfd.c
@@ -7,6 +7,8 @@
#include "fuzz.h"
#define IOWRAP_MAXFD (FD_SETSIZE-1)
+// hopefully above any real fd...
+static const int WRAPFD_STARTFD = 400;
static const int MAX_RANDOM_IN = 50000;
static const double CHANCE_CLOSE = 1.0 / 600;
static const double CHANCE_INTR = 1.0 / 900;
@@ -17,25 +19,21 @@ 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 unsigned short rand_state[3];
+static buffer *input_buf;
-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));
memset(rand_state, 0x0, sizeof(rand_state));
wrapfd_setseed(50);
+ input_buf = buf;
}
void wrapfd_setseed(uint32_t seed) {
@@ -43,39 +41,29 @@ 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);
-
- wrap_fds[fd].mode = mode;
- wrap_fds[fd].buf = buf;
- wrap_fds[fd].closein = 0;
- wrap_fds[fd].closeout = 0;
- wrap_used[nused] = fd;
-
- nused++;
+int wrapfd_new() {
+ int fd;
+ // Find a spare file descriptor to use
+ for (fd = WRAPFD_STARTFD; fd < IOWRAP_MAXFD; fd++) {
+ if (wrap_fds[fd].mode == UNUSED) {
+ // check real file descriptors haven't got as far as WRAPFD_STARTFD
+ assert(close(fd) == -1 && errno == EBADF);
+ wrap_fds[fd].mode = COMMONBUF;
+ wrap_fds[fd].closein = 0;
+ wrap_fds[fd].closeout = 0;
+ return fd;
+ }
+ }
+ errno = EMFILE;
+ return -1;
}
void wrapfd_remove(int fd) {
- unsigned int i, j;
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--;
}
int wrapfd_close(int fd) {
@@ -115,15 +103,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;
}
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);
diff --git a/fuzz.h b/fuzz.h
index dab6c37..cc98ed2 100644
--- a/fuzz.h
+++ b/fuzz.h
@@ -31,6 +31,7 @@ void fuzz_seed(void);
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