aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-forkserver.c368
1 files changed, 267 insertions, 101 deletions
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 0a77d61c..1f796e53 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -389,7 +389,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
while (1) {
uint32_t was_killed;
- int status;
+ u32 status;
/* Wait for parent by reading from the pipe. Exit if read fails. */
@@ -524,7 +524,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output) {
int st_pipe[2], ctl_pipe[2];
- s32 status;
+ u32 status;
s32 rlen;
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
@@ -1017,69 +1017,95 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (rlen == 4) {
+ /*
+ * The new fork server model works like this:
+ * Client: sends "AFLx" in little endian, with x being the forkserver
+ * protocol version.
+ * Server: replies with XOR of the message or exits with an error if it
+ * is not a supported version.
+ * Client: sends 32 bit of options and then sends all parameters of
+ * the options, one after another, increasing by option number.
+ * Ends with "AFLx".
+ * After the initial protocol version confirmation the server does not
+ * send any data anymore - except a future option requires this.
+ */
+
if (status >= 0x41464c00 && status <= 0x41464cff) {
- FATAL(
- "Target uses the new forkserver model, you need to switch to a newer "
- "afl-fuzz too!");
+ u32 version = status - 0x41464c00;
- }
+ if (!version) {
- if (!be_quiet) { OKF("All right - fork server is up."); }
+ FATAL(
+ "Fork server version is not assigned, this should not happen. "
+ "Recompile target.");
- if (getenv("AFL_DEBUG")) {
+ } else if (version < FS_NEW_VERSION_MIN || version > FS_NEW_VERSION_MAX) {
- ACTF("Extended forkserver functions received (%08x).", status);
+ FATAL(
+ "Fork server version is not not supported. Recompile the target.");
- }
+ }
- if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
- report_error_and_exit(FS_OPT_GET_ERROR(status));
+ status ^= 0xffffffff;
+ if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
- if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
+ FATAL("Writing to forkserver failed.");
- // workaround for recent AFL++ versions
- if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
- status = (status & 0xf0ffffff);
+ }
- if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
+ if (!be_quiet) {
- if (fsrv->qemu_mode || fsrv->frida_mode) {
+ OKF("All right - new fork server model v%u is up.", version);
- report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
+ }
- } else {
+ rlen = read(fsrv->fsrv_st_fd, &status, 4);
- report_error_and_exit(FS_ERROR_OLD_CMPLOG);
+ if (getenv("AFL_DEBUG")) {
- }
+ ACTF("Forkserver options received: (%08x)", status);
}
- if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
+ if ((status & FS_NEW_OPT_MAPSIZE)) {
- fsrv->snapshot = 1;
- if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
+ u32 tmp_map_size;
+ rlen = read(fsrv->fsrv_st_fd, &tmp_map_size, 4);
- }
+ if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
- if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
+ fsrv->real_map_size = tmp_map_size;
- if (fsrv->support_shmem_fuzz) {
+ if (tmp_map_size % 64) {
- fsrv->use_shmem_fuzz = 1;
- if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
+ tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
+
+ }
- if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
+ if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); }
+ if (tmp_map_size > fsrv->map_size) {
- u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
- if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
+ FATAL(
+ "Target's coverage map size of %u is larger than the one this "
+ "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
+ "restart "
+ " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
+ "afl-fuzz",
+ tmp_map_size, fsrv->map_size, tmp_map_size);
- FATAL("Writing to forkserver failed.");
+ }
- }
+ fsrv->map_size = tmp_map_size;
- }
+ }
+
+ if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) {
+
+ if (fsrv->support_shmem_fuzz) {
+
+ fsrv->use_shmem_fuzz = 1;
+ if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
} else {
@@ -1091,134 +1117,274 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
- if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
+ if ((status & FS_NEW_OPT_AUTODICT)) {
- u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
+ u32 dict_size;
+ if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) {
- if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
+ FATAL("Reading from forkserver failed.");
- fsrv->real_map_size = tmp_map_size;
+ }
- if (tmp_map_size % 64) {
+ if (dict_size < 2 || dict_size > 0xffffff) {
- tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
+ FATAL("Dictionary has an illegal size: %d", dict_size);
}
- if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); }
- if (tmp_map_size > fsrv->map_size) {
+ u32 offset = 0, count = 0;
+ u8 *dict = ck_alloc(dict_size);
+ if (dict == NULL) {
- FATAL(
- "Target's coverage map size of %u is larger than the one this "
- "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
- " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
- "afl-fuzz",
- tmp_map_size, fsrv->map_size, tmp_map_size);
+ FATAL("Could not allocate %u bytes of autodictionary memory",
+ dict_size);
}
- fsrv->map_size = tmp_map_size;
+ while (dict_size != 0) {
+
+ rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size);
+ if (rlen > 0) {
+
+ dict_size -= rlen;
+ offset += rlen;
+
+ } else {
+
+ FATAL(
+ "Reading autodictionary fail at position %u with %u bytes "
+ "left.",
+ offset, dict_size);
+
+ }
+
+ }
+
+ offset = 0;
+ while (offset < dict_size && (u8)dict[offset] + offset < dict_size) {
+
+ fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
+ (u8)dict[offset]);
+ offset += (1 + dict[offset]);
+ count++;
+
+ }
+
+ if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
+ ck_free(dict);
}
- if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
+ u32 status2;
+ rlen = read(fsrv->fsrv_st_fd, &status2, 4);
- if (!ignore_autodict) {
+ if (status2 != status) { FATAL("Error in forkserver communication"); }
- if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
+ } else {
- // this is not afl-fuzz - or it is cmplog - we deny and return
- if (fsrv->use_shmem_fuzz) {
+ WARNF(
+ "Old fork server model is used by the target, this still works "
+ "though.");
- status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
+ if (!be_quiet) { OKF("All right - old fork server is up."); }
- } else {
+ if (getenv("AFL_DEBUG")) {
- status = (FS_OPT_ENABLED);
+ ACTF("Extended forkserver functions received (%08x).", status);
- }
+ }
- if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+ if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
+ report_error_and_exit(FS_OPT_GET_ERROR(status));
- FATAL("Writing to forkserver failed.");
+ if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
- }
+ // workaround for recent AFL++ versions
+ if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) ==
+ FS_OPT_OLD_AFLPP_WORKAROUND)
+ status = (status & 0xf0ffffff);
+
+ if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
+
+ if (fsrv->qemu_mode || fsrv->frida_mode) {
+
+ report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
+
+ } else {
- return;
+ report_error_and_exit(FS_ERROR_OLD_CMPLOG);
}
- if (!be_quiet) { ACTF("Using AUTODICT feature."); }
+ }
+
+ if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
+
+ fsrv->snapshot = 1;
+ if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
+
+ }
+
+ if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
+
+ if (fsrv->support_shmem_fuzz) {
+
+ fsrv->use_shmem_fuzz = 1;
+ if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
+
+ if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
- if (fsrv->use_shmem_fuzz) {
+ u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
+ if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
- status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
+ FATAL("Writing to forkserver failed.");
+
+ }
+
+ }
} else {
- status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
+ FATAL(
+ "Target requested sharedmem fuzzing, but we failed to enable "
+ "it.");
}
- if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+ }
- FATAL("Writing to forkserver failed.");
+ if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
- }
+ u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
- if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
+ if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
- FATAL("Reading from forkserver failed.");
+ fsrv->real_map_size = tmp_map_size;
+
+ if (tmp_map_size % 64) {
+
+ tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
}
- if (status < 2 || (u32)status > 0xffffff) {
+ if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); }
+ if (tmp_map_size > fsrv->map_size) {
- FATAL("Dictionary has an illegal size: %d", status);
+ FATAL(
+ "Target's coverage map size of %u is larger than the one this "
+ "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
+ "restart "
+ " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
+ "afl-fuzz",
+ tmp_map_size, fsrv->map_size, tmp_map_size);
}
- u32 offset = 0, count = 0;
- u32 len = status;
- u8 *dict = ck_alloc(len);
- if (dict == NULL) {
+ fsrv->map_size = tmp_map_size;
+
+ }
- FATAL("Could not allocate %u bytes of autodictionary memory", len);
+ if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
- }
+ if (!ignore_autodict) {
- while (len != 0) {
+ if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
- rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
- if (rlen > 0) {
+ // this is not afl-fuzz - or it is cmplog - we deny and return
+ if (fsrv->use_shmem_fuzz) {
- len -= rlen;
- offset += rlen;
+ status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
+
+ } else {
+
+ status = (FS_OPT_ENABLED);
+
+ }
+
+ if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+
+ FATAL("Writing to forkserver failed.");
+
+ }
+
+ return;
+
+ }
+
+ if (!be_quiet) { ACTF("Using AUTODICT feature."); }
+
+ if (fsrv->use_shmem_fuzz) {
+
+ status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
} else {
- FATAL(
- "Reading autodictionary fail at position %u with %u bytes "
- "left.",
- offset, len);
+ status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
}
- }
+ if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
- offset = 0;
- while (offset < (u32)status &&
- (u8)dict[offset] + offset < (u32)status) {
+ FATAL("Writing to forkserver failed.");
- fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
- (u8)dict[offset]);
- offset += (1 + dict[offset]);
- count++;
+ }
- }
+ if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
- if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
- ck_free(dict);
+ FATAL("Reading from forkserver failed.");
+
+ }
+
+ if (status < 2 || (u32)status > 0xffffff) {
+
+ FATAL("Dictionary has an illegal size: %d", status);
+
+ }
+
+ u32 offset = 0, count = 0;
+ u32 len = status;
+ u8 *dict = ck_alloc(len);
+ if (dict == NULL) {
+
+ FATAL("Could not allocate %u bytes of autodictionary memory",
+ len);
+
+ }
+
+ while (len != 0) {
+
+ rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
+ if (rlen > 0) {
+
+ len -= rlen;
+ offset += rlen;
+
+ } else {
+
+ FATAL(
+ "Reading autodictionary fail at position %u with %u bytes "
+ "left.",
+ offset, len);
+
+ }
+
+ }
+
+ offset = 0;
+ while (offset < (u32)status &&
+ (u8)dict[offset] + offset < (u32)status) {
+
+ fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
+ (u8)dict[offset]);
+ offset += (1 + dict[offset]);
+ count++;
+
+ }
+
+ if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
+ ck_free(dict);
+
+ }
}