aboutsummaryrefslogtreecommitdiffstats
path: root/executor/executor.cc
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-08-27 17:29:16 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-08-28 07:56:47 +0000
commit9881ea45723f0f7bbc5876d48c32a7cca1fecaa3 (patch)
treec6311149a7d225c12184c04c94d9fa659933429a /executor/executor.cc
parent6c853ff934ae691d82d2ddf8d401fdd07ed4ab74 (diff)
executor: fix corner case of misinterpreting comparison data
Reset coverage right before scheduling next syscall for execution. See the added comment for details.
Diffstat (limited to 'executor/executor.cc')
-rw-r--r--executor/executor.cc12
1 files changed, 12 insertions, 0 deletions
diff --git a/executor/executor.cc b/executor/executor.cc
index 3757f2698..305675bce 100644
--- a/executor/executor.cc
+++ b/executor/executor.cc
@@ -1095,6 +1095,18 @@ thread_t* schedule_call(int call_index, int call_num, uint64 copyout_index, uint
th->copyout_pos = pos;
th->copyout_index = copyout_index;
event_reset(&th->done);
+ // We do this both right before execute_syscall in the thread and here because:
+ // the former is useful to reset all unrelated coverage from our syscalls (e.g. futex in event_wait),
+ // while the reset here is useful to avoid the following scenario that the fuzzer was able to trigger.
+ // If the test program contains seccomp syscall that kills the worker thread on the next syscall,
+ // then it won't receive this next syscall and won't do cover_reset. If we are collecting comparions
+ // then we've already transformed comparison data from the previous syscall into rpc::ComparisonRaw
+ // in write_comparisons. That data is still in the buffer. The first word of rpc::ComparisonRaw is PC
+ // which overlaps with comparison type in kernel exposed records. As the result write_comparisons
+ // that will try to write out data from unfinished syscalls will see these rpc::ComparisonRaw records,
+ // mis-interpret PC as type, and fail as: SYZFAIL: invalid kcov comp type (type=ffffffff8100b4e0).
+ if (flag_coverage)
+ cover_reset(&th->cov);
th->executing = true;
th->call_index = call_index;
th->call_num = call_num;