aboutsummaryrefslogtreecommitdiffstats
path: root/executor/executor_linux.cc
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-10-20 11:30:59 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-10-23 09:59:39 +0200
commitb71450d9fbb6e1d07d83b01d2f2fe4b41c5cdefb (patch)
tree1cfe7f7330e15879d6cfcb58e44a318c5b36e5d2 /executor/executor_linux.cc
parent3c6fe803958431367baa476f5e591cf6d749640a (diff)
executor: prevent executor from messing with output region
When comparisons are enabled fuzzer somehow manages to discover the output region and corrupt it. It seems to fetch the address from some memory operations (mmap/munmap). Don't leak the output region address.
Diffstat (limited to 'executor/executor_linux.cc')
-rw-r--r--executor/executor_linux.cc39
1 files changed, 36 insertions, 3 deletions
diff --git a/executor/executor_linux.cc b/executor/executor_linux.cc
index d49e7e22b..77316fa12 100644
--- a/executor/executor_linux.cc
+++ b/executor/executor_linux.cc
@@ -34,8 +34,8 @@ const unsigned long KCOV_TRACE_CMP = 1;
const int kInFd = 3;
const int kOutFd = 4;
-const int kCoverSize = 64 << 10;
-const int kPageSize = 4 << 10;
+
+void* const kOutputDataAddr = (void*)0x1bdbc20000ull;
uint32_t* output_data;
uint32_t* output_pos;
@@ -54,7 +54,6 @@ int main(int argc, char** argv)
// If it is corrupted ipc package will fail to parse its contents and panic.
// But fuzzer constantly invents new ways of how to currupt the region,
// so we map the region at a (hopefully) hard to guess address surrounded by unmapped pages.
- void* const kOutputDataAddr = (void*)0x1ddbc20000;
output_data = (uint32_t*)mmap(kOutputDataAddr, kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0);
if (output_data != kOutputDataAddr)
fail("mmap of output file failed");
@@ -292,3 +291,37 @@ void write_completed(uint32_t completed)
{
__atomic_store_n(output_data, completed, __ATOMIC_RELEASE);
}
+
+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_t out_start = (uint64_t)kOutputDataAddr;
+ uint64_t out_end = out_start + kMaxOutput;
+ if (arg1 >= out_start && arg1 <= out_end)
+ return true;
+ if (arg2 >= out_start && arg2 <= out_end)
+ return true;
+#if defined(__i386__) || defined(__x86_64__)
+ // Filter out kernel physical memory addresses.
+ // These are internal kernel comparisons and should not be interesting.
+ // The range covers first 1TB of physical mapping.
+ uint64_t kmem_start = (uint64_t)0xffff880000000000ull;
+ uint64_t kmem_end = (uint64_t)0xffff890000000000ull;
+ bool kptr1 = arg1 >= kmem_start && arg1 <= kmem_end;
+ bool kptr2 = arg2 >= kmem_start && arg2 <= kmem_end;
+ if (kptr1 && kptr2)
+ return true;
+ if (kptr1 && arg2 == 0)
+ return true;
+ if (kptr2 && arg1 == 0)
+ return true;
+#endif
+ }
+ return false;
+}