diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/executor.cc | 34 | ||||
| -rw-r--r-- | executor/executor_bsd.h | 5 | ||||
| -rw-r--r-- | executor/executor_darwin.h | 5 | ||||
| -rw-r--r-- | executor/executor_linux.h | 18 | ||||
| -rw-r--r-- | executor/executor_test.h | 27 | ||||
| -rw-r--r-- | executor/nocover.h | 5 |
6 files changed, 62 insertions, 32 deletions
diff --git a/executor/executor.cc b/executor/executor.cc index a8cc2259f..458931684 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -997,6 +997,8 @@ void write_coverage_signal(cover_t* cov, uint32* signal_count_pos, uint32* cover for (uint32 i = 0; i < cov->size; i++) { cover_data_t pc = cover_data[i] + cov->pc_offset; uint64 sig = pc; + if (is_kernel_pc(pc) < 0) + exitf("got bad pc: 0x%llx", (uint64)pc); if (use_cover_edges(pc)) { // Only hash the lower 12 bits so the hash is independent of any module offsets. const uint64 mask = (1 << 12) - 1; @@ -1570,23 +1572,21 @@ bool kcov_comparison_t::ignore() const // Comparisons with 0 are not interesting, fuzzer should be able to guess 0's without help. if (arg1 == 0 && (arg2 == 0 || (type & KCOV_CMP_CONST))) return true; - if ((type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8) { - // This can be a pointer (assuming 64-bit kernel). - // First of all, we want avert fuzzer from our output region. - // Without this fuzzer manages to discover and corrupt it. - uint64 out_start = (uint64)output_data; - uint64 out_end = out_start + output_size; - if (arg1 >= out_start && arg1 <= out_end) - return true; - if (arg2 >= out_start && arg2 <= out_end) - return true; - // Filter out kernel physical memory addresses. - // These are internal kernel comparisons and should not be interesting. - bool kptr1 = is_kernel_data(arg1) || arg1 == 0; - bool kptr2 = is_kernel_data(arg2) || arg2 == 0; - if (kptr1 && kptr2) - return true; - } + // This can be a pointer (assuming 64-bit kernel). + // First of all, we want avert fuzzer from our output region. + // Without this fuzzer manages to discover and corrupt it. + uint64 out_start = (uint64)output_data; + uint64 out_end = out_start + output_size; + if (arg1 >= out_start && arg1 <= out_end) + return true; + if (arg2 >= out_start && arg2 <= out_end) + return true; + // Filter out kernel physical memory addresses. + // These are internal kernel comparisons and should not be interesting. + bool kptr1 = is_kernel_data(arg1) || arg1 == 0; + bool kptr2 = is_kernel_data(arg2) || arg2 == 0; + if (kptr1 && kptr2) + return true; return !coverage_filter(pc); } diff --git a/executor/executor_bsd.h b/executor/executor_bsd.h index 1f54e0f41..3ee4be80c 100644 --- a/executor/executor_bsd.h +++ b/executor/executor_bsd.h @@ -184,6 +184,11 @@ static bool is_kernel_data(uint64 addr) return false; } +static int is_kernel_pc(uint64 pc) +{ + return 0; +} + static bool use_cover_edges(uint64 pc) { return true; diff --git a/executor/executor_darwin.h b/executor/executor_darwin.h index 83fe90c45..11146acc3 100644 --- a/executor/executor_darwin.h +++ b/executor/executor_darwin.h @@ -127,6 +127,11 @@ static bool is_kernel_data(uint64 addr) return false; } +static int is_kernel_pc(uint64 pc) +{ + return 0; +} + static bool use_cover_edges(uint64 pc) { return true; diff --git a/executor/executor_linux.h b/executor/executor_linux.h index 445a278e2..984c0ba62 100644 --- a/executor/executor_linux.h +++ b/executor/executor_linux.h @@ -193,19 +193,23 @@ static bool is_kernel_data(uint64 addr) #endif } +// Returns >0 for yes, <0 for no, 0 for don't know. +static int is_kernel_pc(uint64 pc) +{ +#if GOARCH_386 || GOARCH_amd64 + // Text/modules range for x86_64. + return pc >= 0xffffffff80000000ull && pc < 0xffffffffff000000ull ? 1 : -1; +#else + return 0; +#endif +} + static bool use_cover_edges(uint64 pc) { #if GOARCH_amd64 || GOARCH_arm64 if (is_gvisor) return false; // gvisor coverage is not a trace, so producing edges won't work #endif -#if GOARCH_386 || GOARCH_amd64 - // Text/modules range for x86_64. - if (pc < 0xffffffff80000000ull || pc >= 0xffffffffff000000ull) { - debug("got bad pc: 0x%llx\n", pc); - doexit(0); - } -#endif return true; } diff --git a/executor/executor_test.h b/executor/executor_test.h index f796aed04..4d23f8162 100644 --- a/executor/executor_test.h +++ b/executor/executor_test.h @@ -5,6 +5,9 @@ #include <sys/mman.h> #include <unistd.h> +static uint64 kernel_text_start = 0xc0dec0dec0000000; +static uint64 kernel_text_mask = 0xffffff; + static void os_init(int argc, char** argv, void* data, size_t data_size) { void* got = mmap(data, data_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); @@ -18,9 +21,6 @@ static intptr_t execute_syscall(const call_t* c, intptr_t a[kMaxArgs]) return c->call(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); } -static __thread unsigned long* local_cover_start = NULL; -static __thread unsigned long* local_cover_end = NULL; - #ifdef __clang__ #define notrace #else @@ -30,10 +30,12 @@ static __thread unsigned long* local_cover_end = NULL; extern "C" notrace void __sanitizer_cov_trace_pc(void) { unsigned long ip = (unsigned long)__builtin_return_address(0); - unsigned long* start = local_cover_start; - unsigned long* end = local_cover_end; - if (start == NULL || end == NULL) + // Convert to what is_kernel_pc will accept as valid coverage; + ip = kernel_text_start | (ip & kernel_text_mask); + if (current_thread == nullptr || current_thread->cov.data == nullptr) return; + unsigned long* start = (unsigned long*)current_thread->cov.data; + unsigned long* end = (unsigned long*)current_thread->cov.data_end; int pos = start[0]; if (start + pos + 1 < end) { start[0] = pos + 1; @@ -48,8 +50,6 @@ static void cover_open(cover_t* cov, bool extra) static void cover_enable(cover_t* cov, bool collect_comps, bool extra) { - local_cover_start = (unsigned long*)cov->data; - local_cover_end = (unsigned long*)cov->data_end; } static void cover_reset(cover_t* cov) @@ -95,6 +95,17 @@ static bool is_kernel_data(uint64 addr) return addr >= 0xda1a0000 && addr <= 0xda1a1000; } +static int is_kernel_pc(uint64 pc) +{ + uint64 start = kernel_text_start; + uint64 end = kernel_text_start | kernel_text_mask; + if (!is_kernel_64_bit) { + start = (uint32)start; + end = (uint32)end; + } + return pc >= start && pc <= end ? 1 : -1; +} + static bool use_cover_edges(uint64 pc) { return true; diff --git a/executor/nocover.h b/executor/nocover.h index ba26dd1d5..b097e9f43 100644 --- a/executor/nocover.h +++ b/executor/nocover.h @@ -34,6 +34,11 @@ static bool is_kernel_data(uint64 addr) return false; } +static int is_kernel_pc(uint64 pc) +{ + return 0; +} + static bool use_cover_edges(uint64 pc) { return true; |
