aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
Diffstat (limited to 'executor')
-rw-r--r--executor/executor.cc25
-rw-r--r--executor/executor_linux.h9
2 files changed, 27 insertions, 7 deletions
diff --git a/executor/executor.cc b/executor/executor.cc
index 92d25e318..aa9f1d053 100644
--- a/executor/executor.cc
+++ b/executor/executor.cc
@@ -215,10 +215,13 @@ struct thread_t {
uint32 reserrno;
bool fault_injected;
cover_t cov;
+ bool soft_fail_state;
};
static thread_t threads[kMaxThreads];
static thread_t* last_scheduled;
+// Threads use this variable to access information about themselves.
+static __thread struct thread_t* current_thread;
static cover_t extra_cov;
@@ -375,6 +378,7 @@ int main(int argc, char** argv)
start_time_ms = current_time_ms();
os_init(argc, argv, (char*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE);
+ current_thread = &threads[0];
#if SYZ_EXECUTOR_USES_SHMEM
if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0])
@@ -1059,7 +1063,7 @@ void thread_create(thread_t* th, int id)
void* worker_thread(void* arg)
{
thread_t* th = (thread_t*)arg;
-
+ current_thread = th;
if (flag_coverage)
cover_enable(&th->cov, flag_comparisons, false);
for (;;) {
@@ -1084,10 +1088,12 @@ void execute_call(thread_t* th)
debug(")\n");
int fail_fd = -1;
+ th->soft_fail_state = false;
if (flag_fault && th->call_index == flag_fault_call) {
if (collide)
fail("both collide and fault injection are enabled");
fail_fd = inject_fault(flag_fault_nth);
+ th->soft_fail_state = true;
}
if (flag_coverage)
@@ -1104,6 +1110,9 @@ void execute_call(thread_t* th)
th->res = 0;
th->reserrno = 0;
}
+ // Reset the flag before the first possible fail().
+ th->soft_fail_state = false;
+
if (flag_coverage) {
cover_collect(&th->cov);
if (th->cov.size >= kCoverSize)
@@ -1477,6 +1486,20 @@ void fail(const char* msg, ...)
vfprintf(stderr, msg, args);
va_end(args);
fprintf(stderr, " (errno %d)\n", e);
+
+ // fail()'s are often used during the validation of kernel reactions to queries
+ // that were issued by pseudo syscalls implementations. As fault injection may
+ // cause the kernel not to succeed in handling these queries (e.g. socket writes
+ // or reads may fail), this could ultimately lead to unwanted "lost connection to
+ // test machine" crashes.
+ // In order to avoid this and, on the other hand, to still have the ability to
+ // signal a disastrous situation, the exit code of this function depends on the
+ // current context.
+ // All fail() invocations during system call execution with enabled fault injection
+ // lead to termination with zero exit code. In all other cases, the exit code is
+ // kFailStatus.
+ if (current_thread && current_thread->soft_fail_state)
+ doexit(0);
doexit(kFailStatus);
}
diff --git a/executor/executor_linux.h b/executor/executor_linux.h
index 26ce9ef52..f8aed1791 100644
--- a/executor/executor_linux.h
+++ b/executor/executor_linux.h
@@ -80,8 +80,6 @@ static void os_init(int argc, char** argv, char* data, size_t data_size)
fail("mmap of right data PROT_NONE page failed");
}
-static __thread cover_t* current_cover;
-
static intptr_t execute_syscall(const call_t* c, intptr_t a[kMaxArgs])
{
if (c->call)
@@ -186,7 +184,6 @@ static void cover_enable(cover_t* cov, bool collect_comps, bool extra)
if (!extra) {
if (ioctl(cov->fd, KCOV_ENABLE, kcov_mode))
exitf("cover enable write trace failed, mode=%d", kcov_mode);
- current_cover = cov;
return;
}
if (is_kernel_64_bit)
@@ -201,9 +198,9 @@ static void cover_reset(cover_t* cov)
if (!flag_coverage)
return;
if (cov == 0) {
- if (current_cover == 0)
- fail("cover_reset: current_cover == 0");
- cov = current_cover;
+ if (current_thread == 0)
+ fail("cover_reset: current_thread == 0");
+ cov = &current_thread->cov;
}
*(uint64*)cov->data = 0;
}