diff options
| author | Kaipeng Zeng <kaipeng94@gmail.com> | 2020-08-06 01:32:00 -0400 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-12-06 11:57:18 +0100 |
| commit | c521566d3f377ad8c69075d3de190738fd12368c (patch) | |
| tree | 6254ab407c8225d2145723420811239b5ff20a8a /executor | |
| parent | 6d371461fd1b83fcfcb86578f504c52134e2df25 (diff) | |
syz-manager/manager.go, executor/executor.cc: support coverage filter
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/cov_filter.h | 58 | ||||
| -rw-r--r-- | executor/executor.cc | 11 | ||||
| -rw-r--r-- | executor/test.h | 34 |
3 files changed, 101 insertions, 2 deletions
diff --git a/executor/cov_filter.h b/executor/cov_filter.h new file mode 100644 index 000000000..66cb0bcdc --- /dev/null +++ b/executor/cov_filter.h @@ -0,0 +1,58 @@ +// Copyright 2020 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +#include <fcntl.h> +#include <stdio.h> + +#if GOOS_linux || GOOS_freebsd || GOOS_netbsd || GOOS_openbsd || GOOS_akaros +#include <sys/mman.h> +#include <sys/stat.h> +#endif + +struct cov_filter_t { + uint32 pcstart; + uint32 pcsize; + uint8 bitmap[]; +}; + +static cov_filter_t* cov_filter; + +static void init_coverage_filter() +{ +#if SYZ_EXECUTOR_USES_SHMEM + int f = open("/syz-cover-bitmap", O_RDONLY); + if (f < 0) { + // We don't fail here because we don't know yet if we should use coverage filter or not. + // We will receive the flag only in execute flags and will fail in coverage_filter if necessary. + debug("bitmap is no found, coverage filter disabled\n"); + return; + } + struct stat st; + if (fstat(f, &st)) + fail("faied to stat coverage filter"); + // A random address for bitmap. Don't corrupt output_data. + void* preferred = (void*)0x110f230000ull; + cov_filter = (cov_filter_t*)mmap(preferred, st.st_size, PROT_READ, MAP_PRIVATE, f, 0); + if (cov_filter != preferred) + fail("failed to initialize coverage filter bitmap at %p", preferred); + if ((uint32)st.st_size != sizeof(uint32) * 2 + ((cov_filter->pcsize >> 4) + 7) / 8) + fail("bad coverage filter bitmap size"); + close(f); +#endif +} + +static bool coverage_filter(uint64 pc) +{ + if (cov_filter == NULL) + fail("coverage filter was enabled but bitmap initialization failed"); + // Prevent out of bound while searching bitmap. + uint32 pc32 = (uint32)(pc & 0xffffffff); + if (pc32 < cov_filter->pcstart || pc32 > cov_filter->pcstart + cov_filter->pcsize) + return false; + // For minimizing the size of bitmap, the lowest 4-bit will be dropped. + pc32 -= cov_filter->pcstart; + pc32 = pc32 >> 4; + uint32 idx = pc32 / 8; + uint32 shift = pc32 % 8; + return (cov_filter->bitmap[idx] & (1 << shift)) > 0; +} diff --git a/executor/executor.cc b/executor/executor.cc index 2f90e4092..7c31f9cc2 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -141,6 +141,7 @@ static bool flag_collect_cover; static bool flag_dedup_cover; static bool flag_threaded; static bool flag_collide; +static bool flag_coverage_filter; // If true, then executor should write the comparisons data to fuzzer. static bool flag_comparisons; @@ -350,6 +351,8 @@ static void setup_features(char** enable, int n); #error "unknown OS" #endif +#include "cov_filter.h" + #include "test.h" int main(int argc, char** argv) @@ -428,6 +431,7 @@ int main(int argc, char** argv) // Don't enable comps because we don't use them in the fuzzer yet. cover_enable(&extra_cov, false, true); } + init_coverage_filter(); } int status = 0; @@ -547,14 +551,15 @@ void receive_execute() flag_comparisons = req.exec_flags & (1 << 3); flag_threaded = req.exec_flags & (1 << 4); flag_collide = req.exec_flags & (1 << 5); + flag_coverage_filter = req.exec_flags & (1 << 6); flag_fault_call = req.fault_call; flag_fault_nth = req.fault_nth; if (!flag_threaded) flag_collide = false; - debug("[%llums] exec opts: procid=%llu threaded=%d collide=%d cover=%d comps=%d dedup=%d fault=%d/%d/%d prog=%llu\n", + debug("[%llums] exec opts: procid=%llu threaded=%d collide=%d cover=%d comps=%d dedup=%d fault=%d/%d/%d prog=%llu filter=%d\n", current_time_ms() - start_time_ms, procid, flag_threaded, flag_collide, flag_collect_cover, flag_comparisons, flag_dedup_cover, flag_fault, - flag_fault_call, flag_fault_nth, req.prog_size); + flag_fault_call, flag_fault_nth, req.prog_size, flag_coverage_filter); if (SYZ_EXECUTOR_USES_SHMEM) { if (req.prog_size) fail("need_prog: no program"); @@ -873,6 +878,8 @@ void write_coverage_signal(cover_t* cov, uint32* signal_count_pos, uint32* cover } cover_data_t sig = pc ^ prev; prev = hash(pc); + if (flag_coverage_filter && !coverage_filter((uint64)pc)) + continue; if (dedup(sig)) continue; write_output(sig); diff --git a/executor/test.h b/executor/test.h index 37d03b65a..c8492ed73 100644 --- a/executor/test.h +++ b/executor/test.h @@ -201,6 +201,39 @@ static int test_csum_inet_acc() return 0; } +static int test_coverage_filter() +{ + struct tmp_cov_filter_t { + uint32 pcstart; + uint32 pcsize; + uint8 bitmap[((0x1000 >> 4) + 7) / 8]; + }; + static struct tmp_cov_filter_t tmp_cov_filter; + tmp_cov_filter.pcstart = 0x81000000; + tmp_cov_filter.pcsize = 0x1000; + memset(tmp_cov_filter.bitmap, 0, ((0x1000 >> 4) + 7) / 8); + cov_filter = (cov_filter_t*)&tmp_cov_filter; + + uint64 full_enable_pc = 0xffffffff81000765; + uint64 full_disable_pc = 0xffffffff81000627; + uint64 full_out_pc = 0xffffffff82000000; + + uint32 enable_pc = (uint32)full_enable_pc & 0xffffffff; + uint32 idx = ((enable_pc - cov_filter->pcstart) >> 4) / 8; + uint32 shift = ((enable_pc - cov_filter->pcstart) >> 4) % 8; + cov_filter->bitmap[idx] |= (1 << shift); + + if (!coverage_filter(full_enable_pc)) + return 1; + if (coverage_filter(full_disable_pc)) + return 1; + if (coverage_filter(full_out_pc)) + return 1; + + cov_filter = NULL; + return 0; +} + static struct { const char* name; int (*f)(); @@ -211,6 +244,7 @@ static struct { #if GOOS_linux && (GOARCH_amd64 || GOARCH_ppc64 || GOARCH_ppc64le) {"test_kvm", test_kvm}, #endif + {"test_coverage_filter", test_coverage_filter}, }; static int run_tests() |
