glaring wrapfd problems fixed

--HG--
branch : fuzz
This commit is contained in:
Matt Johnston 2017-05-20 22:47:19 +08:00
parent fdc6f32392
commit c169423051
12 changed files with 72 additions and 21 deletions

View File

@ -88,6 +88,10 @@ void chancleanup() {
unsigned int i; unsigned int i;
if (!ses.channels) {
return;
}
TRACE(("enter chancleanup")) TRACE(("enter chancleanup"))
for (i = 0; i < ses.chansize; i++) { for (i = 0; i < ses.chansize; i++) {
if (ses.channels[i] != NULL) { if (ses.channels[i] != NULL) {

View File

@ -403,6 +403,7 @@ static void gen_new_zstream_recv() {
ses.newkeys->recv.zstream->zfree = Z_NULL; ses.newkeys->recv.zstream->zfree = Z_NULL;
if (inflateInit(ses.newkeys->recv.zstream) != Z_OK) { if (inflateInit(ses.newkeys->recv.zstream) != Z_OK) {
m_free(ses.newkeys->recv.zstream);
dropbear_exit("zlib error"); dropbear_exit("zlib error");
} }
} else { } else {

View File

@ -82,14 +82,18 @@ void common_session_init(int sock_in, int sock_out) {
ses.last_packet_time_any_sent = 0; ses.last_packet_time_any_sent = 0;
ses.last_packet_time_keepalive_sent = 0; ses.last_packet_time_keepalive_sent = 0;
if (pipe(ses.signal_pipe) < 0) { #ifdef DROPBEAR_FUZZ
dropbear_exit("Signal pipe failed"); if (!fuzz.fuzzing)
#endif
{
if (pipe(ses.signal_pipe) < 0) {
dropbear_exit("Signal pipe failed");
}
setnonblocking(ses.signal_pipe[0]);
setnonblocking(ses.signal_pipe[1]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
} }
setnonblocking(ses.signal_pipe[0]);
setnonblocking(ses.signal_pipe[1]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[0]);
ses.maxfd = MAX(ses.maxfd, ses.signal_pipe[1]);
ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN); ses.writepayload = buf_new(TRANS_MAX_PAYLOAD_LEN);
ses.transseq = 0; ses.transseq = 0;
@ -311,6 +315,16 @@ void session_cleanup() {
buf_free(dequeue(&ses.writequeue)); buf_free(dequeue(&ses.writequeue));
} }
m_free(ses.newkeys);
#ifndef DISABLE_ZLIB
if (ses.keys->recv.zstream != NULL) {
if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
dropbear_exit("Crypto error");
}
m_free(ses.keys->recv.zstream);
}
#endif
m_free(ses.remoteident); m_free(ses.remoteident);
m_free(ses.authstate.pw_dir); m_free(ses.authstate.pw_dir);
m_free(ses.authstate.pw_name); m_free(ses.authstate.pw_name);

View File

@ -181,7 +181,8 @@ static void write_urandom()
#endif #endif
} }
static void seedfuzz(void) { #ifdef DROPBEAR_FUZZ
void seedfuzz(void) {
hash_state hs; hash_state hs;
sha1_init(&hs); sha1_init(&hs);
sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz")); sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
@ -190,6 +191,7 @@ static void seedfuzz(void) {
counter = 0; counter = 0;
donerandinit = 1; donerandinit = 1;
} }
#endif
/* Initialise the prng from /dev/urandom or prngd. This function can /* Initialise the prng from /dev/urandom or prngd. This function can
* be called multiple times */ * be called multiple times */
@ -203,7 +205,6 @@ void seedrandom() {
#ifdef DROPBEAR_FUZZ #ifdef DROPBEAR_FUZZ
if (fuzz.fuzzing || fuzz.recordf) { if (fuzz.fuzzing || fuzz.recordf) {
seedfuzz();
return; return;
} }
#endif #endif

View File

@ -569,7 +569,16 @@ void setnonblocking(int fd) {
* can't be set to non-blocking */ * can't be set to non-blocking */
TRACE(("ignoring ENODEV for setnonblocking")) TRACE(("ignoring ENODEV for setnonblocking"))
} else { } else {
dropbear_exit("Couldn't set nonblocking"); #ifdef DROPBEAR_FUZZ
if (fuzz.fuzzing)
{
TRACE(("fuzzing ignore setnonblocking failure for %d", fd))
}
else
#endif
{
dropbear_exit("Couldn't set nonblocking");
}
} }
} }
TRACE(("leave setnonblocking")) TRACE(("leave setnonblocking"))

View File

@ -64,6 +64,7 @@
/* you don't need to touch this block */ /* you don't need to touch this block */
#if DEBUG_TRACE #if DEBUG_TRACE
extern int debug_trace;
#define TRACE(X) dropbear_trace X; #define TRACE(X) dropbear_trace X;
#define TRACE2(X) dropbear_trace2 X; #define TRACE2(X) dropbear_trace2 X;
#else /*DEBUG_TRACE*/ #else /*DEBUG_TRACE*/

View File

@ -27,6 +27,9 @@ int fuzzer_set_input(const uint8_t *Data, size_t Size) {
fuzz.input->len = Size; fuzz.input->len = Size;
fuzz.input->pos = 0; fuzz.input->pos = 0;
memset(&ses, 0x0, sizeof(ses));
memset(&svr_ses, 0x0, sizeof(svr_ses));
// get prefix. input format is // get prefix. input format is
// string prefix // string prefix
// uint32 wrapfd seed // uint32 wrapfd seed
@ -44,7 +47,7 @@ int fuzzer_set_input(const uint8_t *Data, size_t Size) {
uint32_t wrapseed = buf_getint(fuzz.input); uint32_t wrapseed = buf_getint(fuzz.input);
wrapfd_setup(wrapseed); wrapfd_setup(wrapseed);
seedrandom(); seedfuzz();
return DROPBEAR_SUCCESS; return DROPBEAR_SUCCESS;
} }

View File

@ -18,7 +18,9 @@ int main(int argc, char ** argv) {
buf_readfile(input, fn); buf_readfile(input, fn);
buf_setpos(input, 0); buf_setpos(input, 0);
printf("Running %s\n", fn); printf("Running %s once \n", fn);
LLVMFuzzerTestOneInput(input->data, input->len);
printf("Running %s twice \n", fn);
LLVMFuzzerTestOneInput(input->data, input->len); LLVMFuzzerTestOneInput(input->data, input->len);
printf("Done %s\n", fn); printf("Done %s\n", fn);
} }

View File

@ -16,6 +16,8 @@ static const double CHANCE_WRITE2 = 0.3;
struct fdwrap { struct fdwrap {
enum wrapfd_mode mode; enum wrapfd_mode mode;
buffer *buf; buffer *buf;
int closein;
int closeout;
}; };
static struct fdwrap wrap_fds[IOWRAP_MAXFD+1]; static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
@ -28,21 +30,25 @@ void wrapfd_setup(uint32_t seed) {
TRACE(("wrapfd_setup %x", seed)) TRACE(("wrapfd_setup %x", seed))
nused = 0; 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));
*((uint32_t*)rand_state) = seed; *((uint32_t*)rand_state) = seed;
nrand48(rand_state); nrand48(rand_state);
} }
void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) { 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 >= 0);
assert(fd <= IOWRAP_MAXFD); assert(fd <= IOWRAP_MAXFD);
assert(wrap_fds[fd].mode == UNUSED); assert(wrap_fds[fd].mode == UNUSED);
assert(buf || mode == RANDOMIN); assert(buf || mode == RANDOMIN);
TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
wrap_fds[fd].mode = mode; wrap_fds[fd].mode = mode;
wrap_fds[fd].buf = buf; wrap_fds[fd].buf = buf;
wrap_fds[fd].closein = 0;
wrap_fds[fd].closeout = 0;
wrap_used[nused] = fd; wrap_used[nused] = fd;
nused++; nused++;
@ -50,12 +56,12 @@ void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
void wrapfd_remove(int fd) { void wrapfd_remove(int fd) {
unsigned int i, j; unsigned int i, j;
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;
TRACE(("wrapfd_remove %d", fd))
// remove from used list // remove from used list
for (i = 0, j = 0; i < nused; i++) { for (i = 0, j = 0; i < nused; i++) {
@ -67,6 +73,9 @@ void wrapfd_remove(int fd) {
nused--; nused--;
} }
void wrapfd_close(int fd) {
wrapfd_remove(fd);
}
int wrapfd_read(int fd, void *out, size_t count) { int wrapfd_read(int fd, void *out, size_t count) {
size_t maxread; size_t maxread;
@ -85,9 +94,10 @@ int wrapfd_read(int fd, void *out, size_t count) {
assert(count != 0); assert(count != 0);
if (erand48(rand_state) < CHANCE_CLOSE) { if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) {
wrapfd_remove(fd); wrap_fds[fd].closein = 1;
return 0; errno = ECONNRESET;
return -1;
} }
if (erand48(rand_state) < CHANCE_INTR) { if (erand48(rand_state) < CHANCE_INTR) {
@ -135,9 +145,10 @@ int wrapfd_write(int fd, const void* in, size_t count) {
(void)volin[i]; (void)volin[i];
} }
if (erand48(rand_state) < CHANCE_CLOSE) { if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) {
wrapfd_remove(fd); wrap_fds[fd].closeout = 1;
return 0; errno = ECONNRESET;
return -1;
} }
if (erand48(rand_state) < CHANCE_INTR) { if (erand48(rand_state) < CHANCE_INTR) {

1
fuzz.h
View File

@ -23,6 +23,7 @@ void fuzz_kex_fakealgos(void);
wrapfd_select(nfds, readfds, writefds, exceptfds, timeout) wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
#define write(fd, buf, count) wrapfd_write(fd, buf, count) #define write(fd, buf, count) wrapfd_write(fd, buf, count)
#define read(fd, buf, count) wrapfd_read(fd, buf, count) #define read(fd, buf, count) wrapfd_read(fd, buf, count)
#define close(fd) wrapfd_close(fd)
#endif // FUZZ_SKIP_WRAP #endif // FUZZ_SKIP_WRAP
struct dropbear_fuzz_options { struct dropbear_fuzz_options {

View File

@ -2,9 +2,11 @@
#include "dbrandom.h" #include "dbrandom.h"
#include "session.h" #include "session.h"
#include "fuzz-wrapfd.h" #include "fuzz-wrapfd.h"
#include "debug.h"
static void setup_fuzzer(void) { static void setup_fuzzer(void) {
svr_setup_fuzzer(); svr_setup_fuzzer();
//debug_trace = 1;
} }
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {

View File

@ -245,7 +245,9 @@ void svr_dropbear_log(int priority, const char* format, va_list param) {
static void svr_remoteclosed() { static void svr_remoteclosed() {
m_close(ses.sock_in); m_close(ses.sock_in);
m_close(ses.sock_out); if (ses.sock_in != ses.sock_out) {
m_close(ses.sock_out);
}
ses.sock_in = -1; ses.sock_in = -1;
ses.sock_out = -1; ses.sock_out = -1;
dropbear_close("Exited normally"); dropbear_close("Exited normally");