aboutsummaryrefslogtreecommitdiffstats
path: root/executor/executor.cc
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2020-09-21 18:37:45 +0300
committerDmitry Vyukov <dvyukov@google.com>2020-09-22 10:12:23 +0200
commit3e8f6c27551f163a2fd2661e4b3cac126a5e7ef2 (patch)
tree244bb7c316cb02764cb9074422ba32d3bb8f6d36 /executor/executor.cc
parent2450c42f1be626b601353c1e039f8fcbadfaffb1 (diff)
executor: make exit code during fail() depend on fault injection
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 now 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. This is achieved by introduction of a special thread-specific variable `current_thread` that allows to access information about the thread in which the current code is executing. Also, this commit eliminates current_cover as it is no longer needed.
Diffstat (limited to 'executor/executor.cc')
-rw-r--r--executor/executor.cc25
1 files changed, 24 insertions, 1 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);
}