somewhat unified write_to_testcase

This commit is contained in:
Dominik Maier
2020-04-15 23:22:13 +02:00
parent 2ce6e7a7fb
commit 0f08b13fa0
6 changed files with 95 additions and 120 deletions

View File

@ -29,12 +29,9 @@
#include "config.h" #include "config.h"
/* __FUNCTION__ is non-iso */ /* __FUNCTION__ is non-iso */
#ifndef __FUNCTION__
#ifdef __func__ #ifdef __func__
#define __FUNCTION__ __func__ #define __FUNCTION__ __func__
#else #else
#define __FUNCTION__ "func_unknown"
#endif
#endif #endif
/******************* /*******************

View File

@ -51,6 +51,8 @@ typedef struct afl_forkserver {
fsrv_ctl_fd, /* Fork server control pipe (write) */ fsrv_ctl_fd, /* Fork server control pipe (write) */
fsrv_st_fd; /* Fork server status pipe (read) */ fsrv_st_fd; /* Fork server status pipe (read) */
u8 no_unlink; /* do not unlink cur_input */
u32 exec_tmout; /* Configurable exec timeout (ms) */ u32 exec_tmout; /* Configurable exec timeout (ms) */
u32 map_size; /* map size used by the target */ u32 map_size; /* map size used by the target */
u32 snapshot; /* is snapshot feature used */ u32 snapshot; /* is snapshot feature used */
@ -97,6 +99,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv);
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from); void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output); volatile u8 *stop_soon_p, u8 debug_child_output);
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len);
fsrv_run_result_t afl_fsrv_run_target( fsrv_run_result_t afl_fsrv_run_target(
afl_forkserver_t *fsrv, u32 timeout, afl_forkserver_t *fsrv, u32 timeout,
void(classify_counts_func)(afl_forkserver_t *fsrv), void(classify_counts_func)(afl_forkserver_t *fsrv),

View File

@ -8,7 +8,9 @@
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved.
@ -38,10 +40,12 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <fcntl.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/stat.h>
/** /**
* The correct fds for reading and writing pipes * The correct fds for reading and writing pipes
@ -64,15 +68,20 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
// this structure needs default so we initialize it if this was not done // this structure needs default so we initialize it if this was not done
// already // already
fsrv->use_stdin = 1;
fsrv->out_fd = -1; fsrv->out_fd = -1;
fsrv->out_dir_fd = -1; fsrv->out_dir_fd = -1;
fsrv->dev_null_fd = -1; fsrv->dev_null_fd = -1;
#ifndef HAVE_ARC4RANDOM #ifndef HAVE_ARC4RANDOM
fsrv->dev_urandom_fd = -1; fsrv->dev_urandom_fd = -1;
#endif #endif
/* Settings */
fsrv->use_stdin = 1;
fsrv->no_unlink = 0;
fsrv->exec_tmout = EXEC_TIMEOUT; fsrv->exec_tmout = EXEC_TIMEOUT;
fsrv->mem_limit = MEM_LIMIT; fsrv->mem_limit = MEM_LIMIT;
fsrv->out_file = NULL;
/* exec related stuff */
fsrv->child_pid = -1; fsrv->child_pid = -1;
fsrv->map_size = MAP_SIZE; fsrv->map_size = MAP_SIZE;
fsrv->use_fauxsrv = 0; fsrv->use_fauxsrv = 0;
@ -103,6 +112,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->child_pid = -1; fsrv_to->child_pid = -1;
fsrv_to->use_fauxsrv = 0; fsrv_to->use_fauxsrv = 0;
fsrv_to->last_run_timed_out = 0; fsrv_to->last_run_timed_out = 0;
fsrv_to->out_file = NULL;
fsrv_to->init_child_func = fsrv_exec_child; fsrv_to->init_child_func = fsrv_exec_child;
@ -640,6 +650,48 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
} }
/* Delete the current testcase and write the buf to the testcase file */
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
s32 fd = fsrv->out_fd;
if (fsrv->out_file) {
if (fsrv->no_unlink) {
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
} else {
unlink(fsrv->out_file); /* Ignore errors. */
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
}
if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file);
} else {
lseek(fd, 0, SEEK_SET);
}
ck_write(fd, buf, len, fsrv->out_file);
if (!fsrv->out_file) {
if (ftruncate(fd, len)) PFATAL("ftruncate() failed");
lseek(fd, 0, SEEK_SET);
} else {
close(fd);
}
}
/* Execute target application, monitoring for timeouts. Return status /* Execute target application, monitoring for timeouts. Return status
information. The called program will update afl->fsrv->trace_bits. */ information. The called program will update afl->fsrv->trace_bits. */

View File

@ -6,7 +6,8 @@
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved.
@ -45,8 +46,6 @@ fsrv_run_result_t run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
s32 fd = afl->fsrv.out_fd;
#ifdef _AFL_DOCUMENT_MUTATIONS #ifdef _AFL_DOCUMENT_MUTATIONS
s32 doc_fd; s32 doc_fd;
char fn[PATH_MAX]; char fn[PATH_MAX];
@ -63,25 +62,6 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
#endif #endif
if (afl->fsrv.out_file) {
if (afl->no_unlink) {
fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
} else {
unlink(afl->fsrv.out_file); /* Ignore errors. */
fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
}
if (fd < 0) PFATAL("Unable to create '%s'", afl->fsrv.out_file);
} else
lseek(fd, 0, SEEK_SET);
if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) { if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) {
u8 *new_buf = NULL; u8 *new_buf = NULL;
@ -93,24 +73,15 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size); FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
/* everything as planned. use the new data. */ /* everything as planned. use the new data. */
ck_write(fd, new_buf, new_size, afl->fsrv.out_file); afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size);
} else { } else {
/* boring uncustom. */ /* boring uncustom. */
ck_write(fd, mem, len, afl->fsrv.out_file); afl_fsrv_write_to_testcase(&afl->fsrv, mem, len);
} }
if (!afl->fsrv.out_file) {
if (ftruncate(fd, len)) PFATAL("ftruncate() failed");
lseek(fd, 0, SEEK_SET);
} else
close(fd);
} }
/* The same, but with an adjustable gap. Used for trimming. */ /* The same, but with an adjustable gap. Used for trimming. */

View File

@ -8,7 +8,8 @@
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved.
@ -61,7 +62,8 @@
static char *stdin_file; /* stdin file */ static char *stdin_file; /* stdin file */
static u8 *in_dir, /* input folder */ static u8 *in_dir = NULL, /* input folder */
*out_file = NULL,
*at_file = NULL; /* Substitution string for @@ */ *at_file = NULL; /* Substitution string for @@ */
static u8 *in_data; /* Input data */ static u8 *in_data; /* Input data */
@ -157,7 +159,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
fd = open(outfile, O_WRONLY); fd = open(outfile, O_WRONLY);
if (fd < 0) PFATAL("Unable to open '%s'", fsrv->out_file); if (fd < 0) PFATAL("Unable to open '%s'", out_file);
} else if (!strcmp(outfile, "-")) { } else if (!strcmp(outfile, "-")) {
@ -215,33 +217,12 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
} }
/* Write results. */
static u32 write_results(afl_forkserver_t *fsrv) {
return write_results_to_file(fsrv, fsrv->out_file);
}
/* Write modified data to file for testing. If use_stdin is clear, the old file
is unlinked and a new one is created. Otherwise, out_fd is rewound and
truncated. */
static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
lseek(fsrv->out_fd, 0, SEEK_SET);
ck_write(fsrv->out_fd, mem, len, fsrv->out_file);
if (ftruncate(fsrv->out_fd, len)) PFATAL("ftruncate() failed");
lseek(fsrv->out_fd, 0, SEEK_SET);
}
/* Execute target application. */ /* Execute target application. */
void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
u32 len) { u32 len) {
write_to_testcase(fsrv, mem, len); afl_fsrv_write_to_testcase(fsrv, mem, len);
if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts,
&stop_soon) == FSRV_RUN_ERROR) { &stop_soon) == FSRV_RUN_ERROR) {
@ -632,8 +613,8 @@ int main(int argc, char **argv_orig, char **envp) {
case 'o': case 'o':
if (fsrv->out_file) FATAL("Multiple -o options not supported"); if (out_file) FATAL("Multiple -o options not supported");
fsrv->out_file = optarg; out_file = optarg;
break; break;
case 'm': { case 'm': {
@ -780,7 +761,7 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (optind == argc || !fsrv->out_file) usage(argv[0]); if (optind == argc || !out_file) usage(argv[0]);
check_environment_vars(envp); check_environment_vars(envp);
@ -831,7 +812,7 @@ int main(int argc, char **argv_orig, char **envp) {
DIR * dir_in, *dir_out; DIR * dir_in, *dir_out;
struct dirent *dir_ent; struct dirent *dir_ent;
int done = 0; int done = 0;
u8 infile[4096], outfile[4096]; u8 infile[PATH_MAX], outfile[PATH_MAX];
#if !defined(DT_REG) #if !defined(DT_REG)
struct stat statbuf; struct stat statbuf;
#endif #endif
@ -841,9 +822,9 @@ int main(int argc, char **argv_orig, char **envp) {
if (!(dir_in = opendir(in_dir))) PFATAL("cannot open directory %s", in_dir); if (!(dir_in = opendir(in_dir))) PFATAL("cannot open directory %s", in_dir);
if (!(dir_out = opendir(fsrv->out_file))) if (!(dir_out = opendir(out_file)))
if (mkdir(fsrv->out_file, 0700)) if (mkdir(out_file, 0700))
PFATAL("cannot create output directory %s", fsrv->out_file); PFATAL("cannot create output directory %s", out_file);
u8 *use_dir = "."; u8 *use_dir = ".";
@ -858,7 +839,7 @@ int main(int argc, char **argv_orig, char **envp) {
unlink(stdin_file); unlink(stdin_file);
atexit(at_exit_handler); atexit(at_exit_handler);
fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600); fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file);
if (arg_offset && argv[arg_offset] != stdin_file) { if (arg_offset && argv[arg_offset] != stdin_file) {
@ -897,7 +878,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue; if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
#endif #endif
snprintf(outfile, sizeof(outfile), "%s/%s", fsrv->out_file, snprintf(outfile, sizeof(outfile), "%s/%s", out_file,
dir_ent->d_name); dir_ent->d_name);
if (read_file(infile)) { if (read_file(infile)) {
@ -918,7 +899,9 @@ int main(int argc, char **argv_orig, char **envp) {
} else { } else {
run_target(fsrv, use_argv); run_target(fsrv, use_argv);
tcnt = write_results(fsrv); tcnt = write_results_to_file(fsrv, out_file);
} }
@ -926,7 +909,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!tcnt) FATAL("No instrumentation detected" cRST); if (!tcnt) FATAL("No instrumentation detected" cRST);
OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST, OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST,
tcnt, highest, total, fsrv->out_file); tcnt, highest, total, out_file);
} }

View File

@ -8,7 +8,8 @@
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved.
@ -61,6 +62,7 @@
static u8 *mask_bitmap; /* Mask for trace bits (-B) */ static u8 *mask_bitmap; /* Mask for trace bits (-B) */
static u8 *in_file, /* Minimizer input test case */ static u8 *in_file, /* Minimizer input test case */
*out_file,
*output_file; /* Minimizer output file */ *output_file; /* Minimizer output file */
static u8 *in_data; /* Input data for trimming */ static u8 *in_data; /* Input data for trimming */
@ -214,46 +216,13 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
} }
/* Write modified data to file for testing. If use_stdin is clear, the old file
is unlinked and a new one is created. Otherwise, out_fd is rewound and
truncated. */
static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
s32 fd = fsrv->out_fd;
if (!fsrv->use_stdin) {
unlink(fsrv->out_file); /* Ignore errors. */
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file);
} else
lseek(fd, 0, SEEK_SET);
ck_write(fd, mem, len, fsrv->out_file);
if (fsrv->use_stdin) {
if (ftruncate(fd, len)) PFATAL("ftruncate() failed");
lseek(fd, 0, SEEK_SET);
} else
close(fd);
}
/* Execute target application. Returns 0 if the changes are a dud, or /* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */ 1 if they should be kept. */
static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
u8 first_run) { u8 first_run) {
write_to_testcase(fsrv, mem, len); afl_fsrv_write_to_testcase(fsrv, mem, len);
fsrv_run_result_t ret = fsrv_run_result_t ret =
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, &stop_soon); afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, &stop_soon);
@ -613,7 +582,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
fsrv->dev_null_fd = open("/dev/null", O_RDWR); fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null"); if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null");
if (!fsrv->out_file) { if (!out_file) {
u8 *use_dir = "."; u8 *use_dir = ".";
@ -624,15 +593,15 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
} }
fsrv->out_file = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid()); out_file = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid());
} }
unlink(fsrv->out_file); unlink(out_file);
fsrv->out_fd = open(fsrv->out_file, O_RDWR | O_CREAT | O_EXCL, 0600); fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file);
/* Set sane defaults... */ /* Set sane defaults... */
@ -888,9 +857,9 @@ int main(int argc, char **argv_orig, char **envp) {
case 'f': case 'f':
if (fsrv->out_file) FATAL("Multiple -f options not supported"); if (out_file) FATAL("Multiple -f options not supported");
fsrv->use_stdin = 0; fsrv->use_stdin = 0;
fsrv->out_file = optarg; out_file = optarg;
break; break;
case 'e': case 'e':
@ -1035,7 +1004,7 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv); set_up_environment(fsrv);
find_binary(fsrv, argv[optind]); find_binary(fsrv, argv[optind]);
detect_file_args(argv + optind, fsrv->out_file, &fsrv->use_stdin); detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
@ -1105,9 +1074,9 @@ int main(int argc, char **argv_orig, char **envp) {
ACTF("Writing output to '%s'...", output_file); ACTF("Writing output to '%s'...", output_file);
unlink(fsrv->out_file); unlink(out_file);
if (fsrv->out_file) ck_free(fsrv->out_file); if (out_file) ck_free(out_file);
fsrv->out_file = NULL; out_file = NULL;
close(write_to_file(output_file, in_data, in_len)); close(write_to_file(output_file, in_data, in_len));