diff --git a/csource/common.go b/csource/common.go index 48d645cc..da5c7c91 100644 --- a/csource/common.go +++ b/csource/common.go @@ -116,8 +116,14 @@ __thread jmp_buf segv_env; static void segv_handler(int sig, siginfo_t* info, void* uctx) { - if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED)) + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1<<20; + const uintptr_t prog_end = 100<<20; + if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { + debug("SIGSEGV on %p, skipping\n", addr); _longjmp(segv_env, 1); + } + debug("SIGSEGV on %p, exiting\n", addr); doexit(sig); for (;;) { } @@ -711,7 +717,7 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin (void)text_count; int text_type = 0; const void* text = 0; - int text_size = 0; + uintptr_t text_size = 0; NONFAILING(text_type = text_array_ptr[0].typ); NONFAILING(text = text_array_ptr[0].text); NONFAILING(text_size = text_array_ptr[0].size); diff --git a/executor/common.h b/executor/common.h index 987cad84..10b3ea5b 100644 --- a/executor/common.h +++ b/executor/common.h @@ -132,8 +132,20 @@ __thread jmp_buf segv_env; static void segv_handler(int sig, siginfo_t* info, void* uctx) { - if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED)) + // Generated programs can contain bad (unmapped/protected) addresses, + // which cause SIGSEGVs during copyin/copyout. + // This handler ignores such crashes to allow the program to proceed. + // We additionally opportunistically check that the faulty address + // is not within executable data region, because such accesses can corrupt + // output region and then fuzzer will fail on corrupted data. + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1 << 20; + const uintptr_t prog_end = 100 << 20; + if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { + debug("SIGSEGV on %p, skipping\n", addr); _longjmp(segv_env, 1); + } + debug("SIGSEGV on %p, exiting\n", addr); doexit(sig); for (;;) { } diff --git a/executor/common_kvm_amd64.h b/executor/common_kvm_amd64.h index 558026d5..f5d061bb 100644 --- a/executor/common_kvm_amd64.h +++ b/executor/common_kvm_amd64.h @@ -287,7 +287,7 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin (void)text_count; // fuzzer can spoof count and we need just 1 text, so ignore text_count int text_type = 0; const void* text = 0; - int text_size = 0; + uintptr_t text_size = 0; NONFAILING(text_type = text_array_ptr[0].typ); NONFAILING(text = text_array_ptr[0].text); NONFAILING(text_size = text_array_ptr[0].size); diff --git a/executor/executor.cc b/executor/executor.cc index 9ef2248b..03999559 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -139,7 +139,7 @@ int main(int argc, char** argv) } prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); - if (mmap(&input_data[0], kMaxInput, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0]) + if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0]) fail("mmap of input file failed"); if (mmap(&output_data[0], kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0) != &output_data[0]) fail("mmap of output file failed");