diff options
Diffstat (limited to 'qemu_mode')
-rwxr-xr-x | qemu_mode/build_qemu_support.sh | 1 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-common.h | 10 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-inl.h | 85 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-translate-inl.h | 3 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-tcg-runtime-inl.h | 2 | ||||
-rw-r--r-- | qemu_mode/patches/bsd-elfload.diff | 44 | ||||
-rw-r--r-- | qemu_mode/patches/mmap_fixes.diff | 165 |
7 files changed, 293 insertions, 17 deletions
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 1828528e..a7bfe20d 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -193,6 +193,7 @@ patch -p1 <../patches/tcg-runtime-head.diff || exit 1 patch -p1 <../patches/translator.diff || exit 1 patch -p1 <../patches/__init__.py.diff || exit 1 patch -p1 <../patches/make_strncpy_safe.diff || exit 1 +patch -p1 <../patches/mmap_fixes.diff || exit 1 echo "[+] Patching done." diff --git a/qemu_mode/patches/afl-qemu-common.h b/qemu_mode/patches/afl-qemu-common.h index 057e1b62..6fac32ef 100644 --- a/qemu_mode/patches/afl-qemu-common.h +++ b/qemu_mode/patches/afl-qemu-common.h @@ -54,7 +54,7 @@ #if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO) #define INC_AFL_AREA(loc) \ asm volatile( \ - "incb (%0, %1, 1)\n" \ + "addb $1, (%0, %1, 1)\n" \ "adcb $0, (%0, %1, 1)\n" \ : /* no out */ \ : "r"(afl_area_ptr), "r"(loc) \ @@ -63,7 +63,9 @@ #define INC_AFL_AREA(loc) afl_area_ptr[loc]++ #endif -typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base); +typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base, + uint8_t *input_buf, + uint32_t input_buf_len); /* Declared in afl-qemu-cpu-inl.h */ @@ -81,6 +83,10 @@ extern unsigned char persistent_save_gpr; extern uint64_t persistent_saved_gpr[AFL_REGS_NUM]; extern int persisent_retaddr_offset; +extern u8 * shared_buf; +extern u32 *shared_buf_len; +extern u8 sharedmem_fuzzing; + extern afl_persistent_hook_fn afl_persistent_hook_ptr; extern __thread abi_ulong afl_prev_loc; diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index e4ebaf88..5f579687 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -83,6 +83,10 @@ unsigned char persistent_save_gpr; uint64_t persistent_saved_gpr[AFL_REGS_NUM]; int persisent_retaddr_offset; +u8 * shared_buf; +u32 *shared_buf_len; +u8 sharedmem_fuzzing; + afl_persistent_hook_fn afl_persistent_hook_ptr; /* Instrumentation ratio: */ @@ -128,6 +132,7 @@ static inline TranslationBlock *tb_find(CPUState *, TranslationBlock *, int, static inline void tb_add_jump(TranslationBlock *tb, int n, TranslationBlock *tb_next); int open_self_maps(void *cpu_env, int fd); +static void afl_map_shm_fuzz(void); /************************* * ACTUAL IMPLEMENTATION * @@ -135,6 +140,42 @@ int open_self_maps(void *cpu_env, int fd); /* Set up SHM region and initialize other stuff. */ +static void afl_map_shm_fuzz(void) { + + char *id_str = getenv(SHM_FUZZ_ENV_VAR); + + if (id_str) { + + u32 shm_id = atoi(id_str); + u8 *map = (u8 *)shmat(shm_id, NULL, 0); + /* Whooooops. */ + + if (!map || map == (void *)-1) { + + perror("[AFL] ERROR: could not access fuzzing shared memory"); + exit(1); + + } + + shared_buf_len = (u32 *)map; + shared_buf = map + sizeof(u32); + + if (getenv("AFL_DEBUG")) { + + fprintf(stderr, "[AFL] DEBUG: successfully got fuzzing shared memory\n"); + + } + + } else { + + fprintf(stderr, + "[AFL] ERROR: variable for fuzzing shared memory is not set\n"); + exit(1); + + } + +} + void afl_setup(void) { char *id_str = getenv(SHM_ENV_VAR), *inst_r = getenv("AFL_INST_RATIO"); @@ -248,6 +289,11 @@ void afl_setup(void) { } + int (*afl_persistent_hook_init_ptr)(void) = + dlsym(plib, "afl_persistent_hook_init"); + if (afl_persistent_hook_init_ptr) + sharedmem_fuzzing = afl_persistent_hook_init_ptr(); + afl_persistent_hook_ptr = dlsym(plib, "afl_persistent_hook"); if (!afl_persistent_hook_ptr) { @@ -278,7 +324,7 @@ void afl_setup(void) { void afl_forkserver(CPUState *cpu) { - u32 map_size = 0; + // u32 map_size = 0; unsigned char tmp[4] = {0}; if (forkserver_installed == 1) return; @@ -291,15 +337,17 @@ void afl_forkserver(CPUState *cpu) { pid_t child_pid; int t_fd[2]; u8 child_stopped = 0; + u32 was_killed; + int status = 0; - // if in the future qemu has non-collding coverage then switch MAP_SIZE // with the max ID value - if (MAP_SIZE <= 0x800000) { - - map_size = (FS_OPT_ENABLED | FS_OPT_MAPSIZE | FS_OPT_SET_MAPSIZE(MAP_SIZE)); - memcpy(tmp, &map_size, 4); - - } + if (MAP_SIZE <= FS_OPT_MAX_MAPSIZE) + status |= (FS_OPT_SET_MAPSIZE(MAP_SIZE) | FS_OPT_MAPSIZE); + if (sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ; + if (status) status |= (FS_OPT_ENABLED); + if (getenv("AFL_DEBUG")) + fprintf(stderr, "Debug: Sending status %08x\n", status); + memcpy(tmp, &status, 4); /* Tell the parent that we're alive. If the parent doesn't want to talk, assume that we're not running in forkserver mode. */ @@ -310,13 +358,28 @@ void afl_forkserver(CPUState *cpu) { int first_run = 1; + if (sharedmem_fuzzing) { + + if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); + + if ((was_killed & (0xffffffff & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))) == + (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) + afl_map_shm_fuzz(); + else { + + fprintf(stderr, + "[AFL] ERROR: afl-fuzz is old and does not support" + " shmem input"); + exit(1); + + } + + } + /* All right, let's await orders... */ while (1) { - int status; - u32 was_killed; - /* Whoops, parent dead? */ if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); diff --git a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h index 083c27e5..8553f194 100644 --- a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h @@ -161,7 +161,8 @@ static void log_x86_sp_content(void) { static void callback_to_persistent_hook(void) { - afl_persistent_hook_ptr(persistent_saved_gpr, guest_base); + afl_persistent_hook_ptr(persistent_saved_gpr, guest_base, shared_buf, + *shared_buf_len); } diff --git a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h index a0246198..400ebf24 100644 --- a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h +++ b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h @@ -215,7 +215,7 @@ void HELPER(afl_cmplog_rtn)(CPUArchState *env) { #else - // dumb code to make it compile + // stupid code to make it compile void *ptr1 = NULL; void *ptr2 = NULL; return; diff --git a/qemu_mode/patches/bsd-elfload.diff b/qemu_mode/patches/bsd-elfload.diff index 6b021bb6..19e44f5b 100644 --- a/qemu_mode/patches/bsd-elfload.diff +++ b/qemu_mode/patches/bsd-elfload.diff @@ -11,7 +11,37 @@ index 7cccf3eb..195875af 100644 /* from personality.h */ /* -@@ -1522,6 +1524,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, +@@ -737,9 +739,13 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss) + end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss); + end_addr = HOST_PAGE_ALIGN(elf_bss); + if (end_addr1 < end_addr) { +- mmap((void *)g2h(end_addr1), end_addr - end_addr1, ++ void *p = mmap((void *)g2h(end_addr1), end_addr - end_addr1, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); ++ if (p == MAP_FAILED) { ++ perror("padzero: cannot mmap"); ++ exit(-1); ++ } + } + } + +@@ -979,9 +985,13 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, + + /* Map the last of the bss segment */ + if (last_bss > elf_bss) { +- target_mmap(elf_bss, last_bss-elf_bss, ++ void *p = target_mmap(elf_bss, last_bss-elf_bss, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); ++ if (p == MAP_FAILED) { ++ perror("load_elf_interp: cannot mmap"); ++ exit(-1); ++ } + } + free(elf_phdata); + +@@ -1522,6 +1532,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, info->start_data = start_data; info->end_data = end_data; info->start_stack = bprm->p; @@ -20,7 +50,17 @@ index 7cccf3eb..195875af 100644 /* Calling set_brk effectively mmaps the pages that we need for the bss and break sections */ -@@ -1549,6 +1553,20 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, +@@ -1544,11 +1556,29 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, + and some applications "depend" upon this behavior. + Since we do not have the power to recompile these, we + emulate the SVr4 behavior. Sigh. */ +- target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, ++ void *p = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, -1, 0); ++ if (p == MAP_FAILED) { ++ perror("load_elf_binary: cannot mmap"); ++ exit(-1); ++ } } info->entry = elf_entry; diff --git a/qemu_mode/patches/mmap_fixes.diff b/qemu_mode/patches/mmap_fixes.diff new file mode 100644 index 00000000..1882bd40 --- /dev/null +++ b/qemu_mode/patches/mmap_fixes.diff @@ -0,0 +1,165 @@ +diff --git a/exec.c b/exec.c +index df5571e..d484098 100644 +--- a/exec.c ++++ b/exec.c +@@ -2457,7 +2457,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) + area = mmap(vaddr, length, PROT_READ | PROT_WRITE, + flags, -1, 0); + } +- if (area != vaddr) { ++ if (area == MAP_FAILED || area != vaddr) { + error_report("Could not remap addr: " + RAM_ADDR_FMT "@" RAM_ADDR_FMT "", + length, addr); +diff --git a/linux-user/mmap.c b/linux-user/mmap.c +index 41e0983..0a8b8e5 100644 +--- a/linux-user/mmap.c ++++ b/linux-user/mmap.c +@@ -612,9 +612,13 @@ static void mmap_reserve(abi_ulong start, abi_ulong size) + real_end -= qemu_host_page_size; + } + if (real_start != real_end) { +- mmap(g2h(real_start), real_end - real_start, PROT_NONE, ++ void *p = mmap(g2h(real_start), real_end - real_start, PROT_NONE, + MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, + -1, 0); ++ if (p == MAP_FAILED) { ++ perror("mmap_reserve: cannot mmap"); ++ exit(-1); ++ } + } + } + +diff --git a/roms/SLOF/tools/sloffs.c b/roms/SLOF/tools/sloffs.c +index 9a1eace..10366f0 100644 +--- a/roms/SLOF/tools/sloffs.c ++++ b/roms/SLOF/tools/sloffs.c +@@ -308,6 +308,10 @@ sloffs_append(const int file, const char *name, const char *dest) + + fstat(fd, &stat); + append = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ if (append == MAP_FAILED) { ++ perror("sloffs_append: cannot mmap for read"); ++ exit(1); ++ } + header = sloffs_header(file); + + if (!header) +@@ -331,6 +335,10 @@ sloffs_append(const int file, const char *name, const char *dest) + write(out, "", 1); + write_start = mmap(NULL, new_len, PROT_READ | PROT_WRITE, + MAP_SHARED, out, 0); ++ if (write_start == MAP_FAILED) { ++ perror("sloffs_append: cannot mmap for read/write"); ++ exit(1); ++ } + + memset(write_start, 0, new_len); + memset(&new_file, 0, sizeof(struct sloffs)); +diff --git a/roms/skiboot/core/test/run-trace.c b/roms/skiboot/core/test/run-trace.c +index 9801688..236b51d 100644 +--- a/roms/skiboot/core/test/run-trace.c ++++ b/roms/skiboot/core/test/run-trace.c +@@ -178,6 +178,10 @@ static void test_parallel(void) + i = (CPUS*len + getpagesize()-1)&~(getpagesize()-1); + p = mmap(NULL, i, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_SHARED, -1, 0); ++ if (p == MAP_FAILED) { ++ perror("test_parallel: cannot mmap"); ++ exit(-1); ++ } + + for (i = 0; i < CPUS; i++) { + fake_cpus[i].trace = p + i * len; +diff --git a/roms/skiboot/external/ffspart/ffspart.c b/roms/skiboot/external/ffspart/ffspart.c +index 7703477..efbbd5b 100644 +--- a/roms/skiboot/external/ffspart/ffspart.c ++++ b/roms/skiboot/external/ffspart/ffspart.c +@@ -379,7 +379,7 @@ int main(int argc, char *argv[]) + } + + data_ptr = mmap(NULL, pactual, PROT_READ, MAP_SHARED, data_fd, 0); +- if (!data_ptr) { ++ if (data_ptr == MAP_FAILED) { + fprintf(stderr, "Couldn't mmap data file for partition '%s': %s\n", + name, strerror(errno)); + rc = -1; +diff --git a/roms/skiboot/extract-gcov.c b/roms/skiboot/extract-gcov.c +index 3d31d1b..ebc03e6 100644 +--- a/roms/skiboot/extract-gcov.c ++++ b/roms/skiboot/extract-gcov.c +@@ -229,7 +229,11 @@ int main(int argc, char *argv[]) + } + + addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); +- assert(addr != NULL); ++ assert(addr != MAP_FAILED); ++ if (addr == MAP_FAILED) { ++ perror("main: cannot mmap"); ++ exit(-1); ++ } + skiboot_dump_size = sb.st_size; + + printf("Skiboot memory dump %p - %p\n", +diff --git a/roms/skiboot/libstb/create-container.c b/roms/skiboot/libstb/create-container.c +index 5cf80a0..64699ad 100644 +--- a/roms/skiboot/libstb/create-container.c ++++ b/roms/skiboot/libstb/create-container.c +@@ -96,7 +96,11 @@ void getSigRaw(ecc_signature_t *sigraw, char *inFile) + assert(r==0); + + infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0); +- assert(infile); ++ assert(infile != MAP_FAILED); ++ if (infile == MAP_FAILED) { ++ perror("getSigRaw: cannot mmap"); ++ exit(-1); ++ } + + signature = d2i_ECDSA_SIG(NULL, (const unsigned char **) &infile, 7 + 2*EC_COORDBYTES); + +@@ -356,7 +360,11 @@ int main(int argc, char* argv[]) + r = fstat(fdin, &s); + assert(r==0); + infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0); +- assert(infile); ++ assert(infile != MAP_FAILED); ++ if (infile == MAP_FAILED) { ++ perror("main: cannot mmap"); ++ exit(-1); ++ } + fdout = open(params.imagefn, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + assert(fdout > 0); + +diff --git a/tests/tcg/multiarch/test-mmap.c b/tests/tcg/multiarch/test-mmap.c +index 11d0e77..14f5919 100644 +--- a/tests/tcg/multiarch/test-mmap.c ++++ b/tests/tcg/multiarch/test-mmap.c +@@ -203,6 +203,7 @@ void check_aligned_anonymous_fixed_mmaps(void) + p1 = mmap(addr, pagesize, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0); ++ fail_unless (p1 != MAP_FAILED); + /* Make sure we get pages aligned with the pagesize. + The target expects this. */ + p = (uintptr_t) p1; +@@ -234,6 +235,7 @@ void check_aligned_anonymous_fixed_mmaps_collide_with_host(void) + p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0); ++ fail_unless (p1 != MAP_FAILED); + /* Make sure we get pages aligned with the pagesize. + The target expects this. */ + p = (uintptr_t) p1; +@@ -401,6 +403,10 @@ void check_file_fixed_mmaps(void) + p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ, + MAP_PRIVATE | MAP_FIXED, + test_fd, pagesize * 3); ++ fail_unless (p1 != MAP_FAILED); ++ fail_unless (p2 != MAP_FAILED); ++ fail_unless (p3 != MAP_FAILED); ++ fail_unless (p4 != MAP_FAILED); + + /* Make sure we get pages aligned with the pagesize. + The target expects this. */ + |