aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-06-10 11:06:31 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-06-11 05:18:24 +0000
commit2a003ea76245ebf8417137c75d95874a91d1a09f (patch)
tree6b49c8e559f60b50cf48e7849124a5d2694606f7 /executor
parent5f02070655b3c1f2ab50a82fd5f466aaeb7af44a (diff)
executor: factor out is_kernel_pc helper
Factor out is_kernel_pc helper and add kernel pc range for test OS for testing.
Diffstat (limited to 'executor')
-rw-r--r--executor/executor.cc34
-rw-r--r--executor/executor_bsd.h5
-rw-r--r--executor/executor_darwin.h5
-rw-r--r--executor/executor_linux.h18
-rw-r--r--executor/executor_test.h27
-rw-r--r--executor/nocover.h5
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;