mirror of
https://github.com/clearml/dropbear
synced 2025-06-23 02:06:55 +00:00
Make wrapfd share a common buffer for all FDs
--HG-- branch : fuzz
This commit is contained in:
parent
0e3e8db5bf
commit
cc1b07dcf1
7
dbutil.c
7
dbutil.c
@ -121,7 +121,6 @@ static void generic_dropbear_exit(int exitcode, const char* format,
|
|||||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||||
|
|
||||||
#if DROPBEAR_FUZZ
|
#if DROPBEAR_FUZZ
|
||||||
/* longjmp before cleaning up svr_opts */
|
|
||||||
if (fuzz.do_jmp) {
|
if (fuzz.do_jmp) {
|
||||||
longjmp(fuzz.jmp, 1);
|
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 FDIN = 0;
|
||||||
const int FDOUT = 1;
|
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 */
|
/* redirect stdin/stdout/stderr */
|
||||||
if (pipe(infds) != 0) {
|
if (pipe(infds) != 0) {
|
||||||
return DROPBEAR_FAILURE;
|
return DROPBEAR_FAILURE;
|
||||||
|
@ -36,7 +36,7 @@ int fuzz_set_input(const uint8_t *Data, size_t Size) {
|
|||||||
|
|
||||||
memset(&ses, 0x0, sizeof(ses));
|
memset(&ses, 0x0, sizeof(ses));
|
||||||
memset(&svr_ses, 0x0, sizeof(svr_ses));
|
memset(&svr_ses, 0x0, sizeof(svr_ses));
|
||||||
wrapfd_setup();
|
wrapfd_setup(fuzz.input);
|
||||||
|
|
||||||
fuzz_seed();
|
fuzz_seed();
|
||||||
|
|
||||||
@ -78,6 +78,29 @@ void fuzz_svr_setup(void) {
|
|||||||
load_fixed_hostkeys();
|
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) {
|
static void load_fixed_hostkeys(void) {
|
||||||
#include "fuzz-hostkeys.c"
|
#include "fuzz-hostkeys.c"
|
||||||
|
|
||||||
@ -151,6 +174,17 @@ void fuzz_fake_send_kexdh_reply(void) {
|
|||||||
finish_kexhashbuf();
|
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) {
|
int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) {
|
||||||
static int once = 0;
|
static int once = 0;
|
||||||
if (!once) {
|
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);
|
uint32_t wrapseed = buf_getint(fuzz.input);
|
||||||
wrapfd_setseed(wrapseed);
|
wrapfd_setseed(wrapseed);
|
||||||
|
|
||||||
int fakesock = 20;
|
int fakesock = wrapfd_new();
|
||||||
wrapfd_add(fakesock, fuzz.input, PLAIN);
|
|
||||||
|
|
||||||
m_malloc_set_epoch(1);
|
m_malloc_set_epoch(1);
|
||||||
if (setjmp(fuzz.jmp) == 0) {
|
if (setjmp(fuzz.jmp) == 0) {
|
||||||
|
@ -9,7 +9,6 @@ int main(int argc, char ** argv) {
|
|||||||
buffer *input = buf_new(100000);
|
buffer *input = buf_new(100000);
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
printf("arg %s\n", argv[i]);
|
|
||||||
#if DEBUG_TRACE
|
#if DEBUG_TRACE
|
||||||
if (strcmp(argv[i], "-v") == 0) {
|
if (strcmp(argv[i], "-v") == 0) {
|
||||||
debug_trace = 1;
|
debug_trace = 1;
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "fuzz.h"
|
#include "fuzz.h"
|
||||||
|
|
||||||
#define IOWRAP_MAXFD (FD_SETSIZE-1)
|
#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 int MAX_RANDOM_IN = 50000;
|
||||||
static const double CHANCE_CLOSE = 1.0 / 600;
|
static const double CHANCE_CLOSE = 1.0 / 600;
|
||||||
static const double CHANCE_INTR = 1.0 / 900;
|
static const double CHANCE_INTR = 1.0 / 900;
|
||||||
@ -17,25 +19,21 @@ static const double CHANCE_WRITE2 = 0.5;
|
|||||||
|
|
||||||
struct fdwrap {
|
struct fdwrap {
|
||||||
enum wrapfd_mode mode;
|
enum wrapfd_mode mode;
|
||||||
buffer *buf;
|
|
||||||
int closein;
|
int closein;
|
||||||
int closeout;
|
int closeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
|
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 unsigned short rand_state[3];
|
||||||
|
static buffer *input_buf;
|
||||||
|
|
||||||
void wrapfd_setup(void) {
|
void wrapfd_setup(buffer *buf) {
|
||||||
TRACE(("wrapfd_setup"))
|
TRACE(("wrapfd_setup"))
|
||||||
nused = 0;
|
|
||||||
memset(wrap_fds, 0x0, sizeof(wrap_fds));
|
memset(wrap_fds, 0x0, sizeof(wrap_fds));
|
||||||
memset(wrap_used, 0x0, sizeof(wrap_used));
|
|
||||||
|
|
||||||
memset(rand_state, 0x0, sizeof(rand_state));
|
memset(rand_state, 0x0, sizeof(rand_state));
|
||||||
wrapfd_setseed(50);
|
wrapfd_setseed(50);
|
||||||
|
input_buf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrapfd_setseed(uint32_t seed) {
|
void wrapfd_setseed(uint32_t seed) {
|
||||||
@ -43,39 +41,29 @@ void wrapfd_setseed(uint32_t seed) {
|
|||||||
nrand48(rand_state);
|
nrand48(rand_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
|
int wrapfd_new() {
|
||||||
TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
|
int fd;
|
||||||
assert(fd >= 0);
|
// Find a spare file descriptor to use
|
||||||
assert(fd <= IOWRAP_MAXFD);
|
for (fd = WRAPFD_STARTFD; fd < IOWRAP_MAXFD; fd++) {
|
||||||
assert(wrap_fds[fd].mode == UNUSED);
|
if (wrap_fds[fd].mode == UNUSED) {
|
||||||
assert(buf || mode == RANDOMIN);
|
// check real file descriptors haven't got as far as WRAPFD_STARTFD
|
||||||
|
assert(close(fd) == -1 && errno == EBADF);
|
||||||
wrap_fds[fd].mode = mode;
|
wrap_fds[fd].mode = COMMONBUF;
|
||||||
wrap_fds[fd].buf = buf;
|
wrap_fds[fd].closein = 0;
|
||||||
wrap_fds[fd].closein = 0;
|
wrap_fds[fd].closeout = 0;
|
||||||
wrap_fds[fd].closeout = 0;
|
return fd;
|
||||||
wrap_used[nused] = fd;
|
}
|
||||||
|
}
|
||||||
nused++;
|
errno = EMFILE;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrapfd_remove(int fd) {
|
void wrapfd_remove(int fd) {
|
||||||
unsigned int i, j;
|
|
||||||
TRACE(("wrapfd_remove %d", fd))
|
TRACE(("wrapfd_remove %d", fd))
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert(fd <= IOWRAP_MAXFD);
|
assert(fd <= IOWRAP_MAXFD);
|
||||||
assert(wrap_fds[fd].mode != UNUSED);
|
assert(wrap_fds[fd].mode != UNUSED);
|
||||||
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) {
|
int wrapfd_close(int fd) {
|
||||||
@ -115,15 +103,14 @@ int wrapfd_read(int fd, void *out, size_t count) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = wrap_fds[fd].buf;
|
if (input_buf) {
|
||||||
if (buf) {
|
maxread = MIN(input_buf->len - input_buf->pos, count);
|
||||||
maxread = MIN(buf->len - buf->pos, count);
|
|
||||||
/* returns 0 if buf is EOF, as intended */
|
/* returns 0 if buf is EOF, as intended */
|
||||||
if (maxread > 0) {
|
if (maxread > 0) {
|
||||||
maxread = nrand48(rand_state) % maxread + 1;
|
maxread = nrand48(rand_state) % maxread + 1;
|
||||||
}
|
}
|
||||||
memcpy(out, buf_getptr(buf, maxread), maxread);
|
memcpy(out, buf_getptr(input_buf, maxread), maxread);
|
||||||
buf_incrpos(buf, maxread);
|
buf_incrpos(input_buf, maxread);
|
||||||
return maxread;
|
return maxread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,13 @@
|
|||||||
|
|
||||||
enum wrapfd_mode {
|
enum wrapfd_mode {
|
||||||
UNUSED = 0,
|
UNUSED = 0,
|
||||||
PLAIN,
|
COMMONBUF, // using the common buffer
|
||||||
INPROGRESS,
|
|
||||||
RANDOMIN
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
void wrapfd_setseed(uint32_t seed);
|
||||||
// doesn't take ownership of buf. buf is optional.
|
int wrapfd_new();
|
||||||
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode);
|
|
||||||
|
|
||||||
// called via #defines for read/write/select
|
// called via #defines for read/write/select
|
||||||
int wrapfd_read(int fd, void *out, size_t count);
|
int wrapfd_read(int fd, void *out, size_t count);
|
||||||
|
1
fuzz.h
1
fuzz.h
@ -31,6 +31,7 @@ void fuzz_seed(void);
|
|||||||
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
|
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
|
||||||
char **remote_host, char **remote_port, int host_lookup);
|
char **remote_host, char **remote_port, int host_lookup);
|
||||||
void fuzz_fake_send_kexdh_reply(void);
|
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
|
// fake IO wrappers
|
||||||
#ifndef FUZZ_SKIP_WRAP
|
#ifndef FUZZ_SKIP_WRAP
|
||||||
|
Loading…
Reference in New Issue
Block a user