github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/executor.cc (about) 1 // Copyright 2017 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 // +build 5 6 #include <algorithm> 7 #include <errno.h> 8 #include <limits.h> 9 #include <signal.h> 10 #include <stdarg.h> 11 #include <stddef.h> 12 #include <stdint.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <time.h> 17 18 #include <atomic> 19 #include <optional> 20 21 #if !GOOS_windows 22 #include <unistd.h> 23 #endif 24 25 #include "defs.h" 26 27 #include "pkg/flatrpc/flatrpc.h" 28 29 #if defined(__GNUC__) 30 #define SYSCALLAPI 31 #define NORETURN __attribute__((noreturn)) 32 #define PRINTF(fmt, args) __attribute__((format(printf, fmt, args))) 33 #else 34 // Assuming windows/cl. 35 #define SYSCALLAPI WINAPI 36 #define NORETURN __declspec(noreturn) 37 #define PRINTF(fmt, args) 38 #define __thread __declspec(thread) 39 #endif 40 41 #ifndef GIT_REVISION 42 #define GIT_REVISION "unknown" 43 #endif 44 45 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 46 47 #ifndef __has_feature 48 #define __has_feature(x) 0 49 #endif 50 51 #if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) 52 constexpr bool kAddressSanitizer = true; 53 #else 54 constexpr bool kAddressSanitizer = false; 55 #endif 56 57 // uint64 is impossible to printf without using the clumsy and verbose "%" PRId64. 58 // So we define and use uint64. Note: pkg/csource does s/uint64/uint64/. 59 // Also define uint32/16/8 for consistency. 60 typedef unsigned long long uint64; 61 typedef unsigned int uint32; 62 typedef unsigned short uint16; 63 typedef unsigned char uint8; 64 65 // Note: zircon max fd is 256. 66 // Some common_OS.h files know about this constant for RLIMIT_NOFILE. 67 const int kMaxFd = 250; 68 const int kFdLimit = 256; 69 const int kMaxThreads = 32; 70 const int kInPipeFd = kMaxFd - 1; // remapped from stdin 71 const int kOutPipeFd = kMaxFd - 2; // remapped from stdout 72 const int kCoverFd = kOutPipeFd - kMaxThreads; 73 const int kExtraCoverFd = kCoverFd - 1; 74 const int kMaxArgs = 9; 75 const int kCoverSize = 512 << 10; 76 const int kFailStatus = 67; 77 78 // Two approaches of dealing with kcov memory. 79 const int kCoverOptimizedCount = 8; // the max number of kcov instances 80 const int kCoverOptimizedPreMmap = 3; // this many will be mmapped inside main(), others - when needed. 81 const int kCoverDefaultCount = 6; // the max number of kcov instances when delayed kcov mmap is not available 82 83 // Logical error (e.g. invalid input program), use as an assert() alternative. 84 // If such error happens 10+ times in a row, it will be detected as a bug by the runner process. 85 // The runner will fail and syz-manager will create a bug for this. 86 // Note: err is used for bug deduplication, thus distinction between err (constant message) 87 // and msg (varying part). 88 static NORETURN void fail(const char* err); 89 static NORETURN PRINTF(2, 3) void failmsg(const char* err, const char* msg, ...); 90 // Just exit (e.g. due to temporal ENOMEM error). 91 static NORETURN PRINTF(1, 2) void exitf(const char* msg, ...); 92 static NORETURN void doexit(int status); 93 #if !GOOS_fuchsia 94 static NORETURN void doexit_thread(int status); 95 #endif 96 97 // Print debug output that is visible when running syz-manager/execprog with -debug flag. 98 // Debug output is supposed to be relatively high-level (syscalls executed, return values, timing, etc) 99 // and is intended mostly for end users. If you need to debug lower-level details, use debug_verbose 100 // function and temporary enable it in your build by changing #if 0 below. 101 // This function does not add \n at the end of msg as opposed to the previous functions. 102 static PRINTF(1, 2) void debug(const char* msg, ...); 103 void debug_dump_data(const char* data, int length); 104 105 #if 0 106 #define debug_verbose(...) debug(__VA_ARGS__) 107 #else 108 #define debug_verbose(...) (void)0 109 #endif 110 111 static void receive_execute(); 112 static void reply_execute(uint32 status); 113 static void receive_handshake(); 114 115 #if SYZ_EXECUTOR_USES_FORK_SERVER 116 static void SnapshotPrepareParent(); 117 118 // Allocating (and forking) virtual memory for each executed process is expensive, so we only mmap 119 // the amount we might possibly need for the specific received prog. 120 const int kMaxOutputComparisons = 14 << 20; // executions with comparsions enabled are usually < 1% of all executions 121 const int kMaxOutputCoverage = 6 << 20; // coverage is needed in ~ up to 1/3 of all executions (depending on corpus rotation) 122 const int kMaxOutputSignal = 4 << 20; 123 const int kMinOutput = 256 << 10; // if we don't need to send signal, the output is rather short. 124 const int kInitialOutput = kMinOutput; // the minimal size to be allocated in the parent process 125 const int kMaxOutput = kMaxOutputComparisons; 126 #else 127 // We don't fork and allocate the memory only once, so prepare for the worst case. 128 const int kInitialOutput = 14 << 20; 129 const int kMaxOutput = kInitialOutput; 130 #endif 131 132 // For use with flatrpc bit flags. 133 template <typename T> 134 bool IsSet(T flags, T f) 135 { 136 return (flags & f) != T::NONE; 137 } 138 139 // TODO: allocate a smaller amount of memory in the parent once we merge the patches that enable 140 // prog execution with neither signal nor coverage. Likely 64kb will be enough in that case. 141 142 const uint32 kMaxCalls = 64; 143 144 struct alignas(8) OutputData { 145 std::atomic<uint32> size; 146 std::atomic<uint32> consumed; 147 std::atomic<uint32> completed; 148 std::atomic<uint32> num_calls; 149 std::atomic<flatbuffers::Offset<flatbuffers::Vector<uint8_t>>> result_offset; 150 struct { 151 // Call index in the test program (they may be out-of-order is some syscalls block). 152 int index; 153 // Offset of the CallInfo object in the output region. 154 flatbuffers::Offset<rpc::CallInfoRaw> offset; 155 } calls[kMaxCalls]; 156 157 void Reset() 158 { 159 size.store(0, std::memory_order_relaxed); 160 consumed.store(0, std::memory_order_relaxed); 161 completed.store(0, std::memory_order_relaxed); 162 num_calls.store(0, std::memory_order_relaxed); 163 result_offset.store(0, std::memory_order_relaxed); 164 } 165 }; 166 167 // ShmemAllocator/ShmemBuilder help to construct flatbuffers ExecResult reply message in shared memory. 168 // 169 // To avoid copying the reply (in particular coverage/signal/comparisons which may be large), the child 170 // process starts forming CallInfo objects as it handles completion of syscalls, then the top-most runner 171 // process uses these CallInfo to form an array of them, and adds ProgInfo object with a reference to the array. 172 // In order to make this possible, OutputData object is placed at the beginning of the shared memory region, 173 // and it records metadata required to start serialization in one process and continue later in another process. 174 // 175 // OutputData::size is the size of the whole shmem region that the child uses (it different size when coverage/ 176 // comparisons are requested). Note that flatbuffers serialization happens from the end of the buffer backwards. 177 // OutputData::consumed records currently consumed amount memory in the shmem region so that the parent process 178 // can continue from that point. 179 // OutputData::completed records number of completed calls (entries in OutputData::calls arrays). 180 // Flatbuffers identifies everything using offsets in the buffer, OutputData::calls::offset records this offset 181 // for the call object so that we can use it in the parent process to construct the array of calls. 182 // 183 // FlatBufferBuilder generally grows the underlying buffer incrementally as necessary and copying data 184 // (std::vector style). We cannot do this in the shared memory since we have only a single region. 185 // To allow serialization into the shared memory region, ShmemBuilder passes initial buffer size which is equal 186 // to the overall shmem region size (minus OutputData header size) to FlatBufferBuilder, and the custom 187 // ShmemAllocator allocator. As the result, FlatBufferBuilder does exactly one allocation request 188 // to ShmemAllocator and never reallocates (if we overflow the buffer and FlatBufferBuilder does another request, 189 // ShmemAllocator will fail). 190 class ShmemAllocator : public flatbuffers::Allocator 191 { 192 public: 193 ShmemAllocator(void* buf, size_t size) 194 : buf_(buf), 195 size_(size) 196 { 197 } 198 199 private: 200 void* buf_; 201 size_t size_; 202 bool allocated_ = false; 203 204 uint8_t* allocate(size_t size) override 205 { 206 if (allocated_ || size != size_) 207 failmsg("bad allocate request", "allocated=%d size=%zu/%zu", allocated_, size_, size); 208 allocated_ = true; 209 return static_cast<uint8_t*>(buf_); 210 } 211 212 void deallocate(uint8_t* p, size_t size) override 213 { 214 if (!allocated_ || buf_ != p || size_ != size) 215 failmsg("bad deallocate request", "allocated=%d buf=%p/%p size=%zu/%zu", 216 allocated_, buf_, p, size_, size); 217 allocated_ = false; 218 } 219 220 uint8_t* reallocate_downward(uint8_t* old_p, size_t old_size, 221 size_t new_size, size_t in_use_back, 222 size_t in_use_front) override 223 { 224 fail("can't reallocate"); 225 } 226 }; 227 228 class ShmemBuilder : ShmemAllocator, public flatbuffers::FlatBufferBuilder 229 { 230 public: 231 ShmemBuilder(OutputData* data, size_t size, bool store_size) 232 : ShmemAllocator(data + 1, size - sizeof(*data)), 233 flatbuffers::FlatBufferBuilder(size - sizeof(*data), this) 234 { 235 if (store_size) 236 data->size.store(size, std::memory_order_relaxed); 237 size_t consumed = data->consumed.load(std::memory_order_relaxed); 238 if (consumed >= size - sizeof(*data)) 239 failmsg("ShmemBuilder: too large output offset", "size=%zd consumed=%zd", size, consumed); 240 if (consumed) 241 flatbuffers::FlatBufferBuilder::buf_.make_space(consumed); 242 } 243 }; 244 245 const int kInFd = 3; 246 const int kOutFd = 4; 247 const int kMaxSignalFd = 5; 248 const int kCoverFilterFd = 6; 249 static OutputData* output_data; 250 static std::optional<ShmemBuilder> output_builder; 251 static uint32 output_size; 252 static void mmap_output(uint32 size); 253 static uint32 hash(uint32 a); 254 static bool dedup(uint8 index, uint64 sig); 255 256 static uint64 start_time_ms = 0; 257 static bool flag_debug; 258 static bool flag_snapshot; 259 static bool flag_coverage; 260 static bool flag_read_only_coverage; 261 static bool flag_sandbox_none; 262 static bool flag_sandbox_setuid; 263 static bool flag_sandbox_namespace; 264 static bool flag_sandbox_android; 265 static bool flag_extra_coverage; 266 static bool flag_net_injection; 267 static bool flag_net_devices; 268 static bool flag_net_reset; 269 static bool flag_cgroups; 270 static bool flag_close_fds; 271 static bool flag_devlink_pci; 272 static bool flag_nic_vf; 273 static bool flag_vhci_injection; 274 static bool flag_wifi; 275 static bool flag_delay_kcov_mmap; 276 277 static bool flag_collect_cover; 278 static bool flag_collect_signal; 279 static bool flag_dedup_cover; 280 static bool flag_threaded; 281 282 // If true, then executor should write the comparisons data to fuzzer. 283 static bool flag_comparisons; 284 285 static uint64 request_id; 286 static rpc::RequestType request_type; 287 static uint64 all_call_signal; 288 static bool all_extra_signal; 289 290 // Tunable timeouts, received with execute_req. 291 static uint64 syscall_timeout_ms; 292 static uint64 program_timeout_ms; 293 static uint64 slowdown_scale; 294 295 // Can be used to disginguish whether we're at the initialization stage 296 // or we already execute programs. 297 static bool in_execute_one = false; 298 299 #define SYZ_EXECUTOR 1 300 #include "common.h" 301 302 const size_t kMaxInput = 4 << 20; // keep in sync with prog.ExecBufferSize 303 const size_t kMaxCommands = 1000; // prog package knows about this constant (prog.execMaxCommands) 304 305 const uint64 instr_eof = -1; 306 const uint64 instr_copyin = -2; 307 const uint64 instr_copyout = -3; 308 const uint64 instr_setprops = -4; 309 310 const uint64 arg_const = 0; 311 const uint64 arg_addr32 = 1; 312 const uint64 arg_addr64 = 2; 313 const uint64 arg_result = 3; 314 const uint64 arg_data = 4; 315 const uint64 arg_csum = 5; 316 317 const uint64 binary_format_native = 0; 318 const uint64 binary_format_bigendian = 1; 319 const uint64 binary_format_strdec = 2; 320 const uint64 binary_format_strhex = 3; 321 const uint64 binary_format_stroct = 4; 322 323 const uint64 no_copyout = -1; 324 325 static int running; 326 static uint32 completed; 327 static bool is_kernel_64_bit; 328 static bool use_cover_edges; 329 330 static uint8* input_data; 331 332 // Checksum kinds. 333 static const uint64 arg_csum_inet = 0; 334 335 // Checksum chunk kinds. 336 static const uint64 arg_csum_chunk_data = 0; 337 static const uint64 arg_csum_chunk_const = 1; 338 339 typedef intptr_t(SYSCALLAPI* syscall_t)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t); 340 341 struct call_t { 342 const char* name; 343 int sys_nr; 344 call_attrs_t attrs; 345 syscall_t call; 346 }; 347 348 struct cover_t { 349 int fd; 350 uint32 size; 351 // mmap_alloc_ptr is the internal pointer to KCOV mapping, possibly with guard pages. 352 // It is only used to allocate/deallocate the buffer of mmap_alloc_size. 353 char* mmap_alloc_ptr; 354 uint32 mmap_alloc_size; 355 // data is the pointer to the kcov buffer containing the recorded PCs. 356 // data may differ from mmap_alloc_ptr. 357 char* data; 358 // data_size is set by cover_open(). This is the requested kcov buffer size. 359 uint32 data_size; 360 // data_end is simply data + data_size. 361 char* data_end; 362 // Currently collecting comparisons. 363 bool collect_comps; 364 // Note: On everything but darwin the first value in data is the count of 365 // recorded PCs, followed by the PCs. We therefore set data_offset to the 366 // size of one PC. 367 // On darwin data points to an instance of the ksancov_trace struct. Here we 368 // set data_offset to the offset between data and the structs 'pcs' member, 369 // which contains the PCs. 370 intptr_t data_offset; 371 // Note: On everything but darwin this is 0, as the PCs contained in data 372 // are already correct. XNUs KSANCOV API, however, chose to always squeeze 373 // PCs into 32 bit. To make the recorded PC fit, KSANCOV substracts a fixed 374 // offset (VM_MIN_KERNEL_ADDRESS for AMD64) and then truncates the result to 375 // uint32_t. We get this from the 'offset' member in ksancov_trace. 376 intptr_t pc_offset; 377 // The coverage buffer has overflowed and we have truncated coverage. 378 bool overflow; 379 // True if cover_enable() was called for this object. 380 bool enabled; 381 }; 382 383 struct thread_t { 384 int id; 385 bool created; 386 event_t ready; 387 event_t done; 388 uint8* copyout_pos; 389 uint64 copyout_index; 390 bool executing; 391 int call_index; 392 int call_num; 393 int num_args; 394 intptr_t args[kMaxArgs]; 395 call_props_t call_props; 396 intptr_t res; 397 uint32 reserrno; 398 bool fault_injected; 399 cover_t cov; 400 bool soft_fail_state; 401 }; 402 403 static thread_t threads[kMaxThreads]; 404 static thread_t* last_scheduled; 405 // Threads use this variable to access information about themselves. 406 static __thread struct thread_t* current_thread; 407 408 static cover_t extra_cov; 409 410 struct res_t { 411 bool executed; 412 uint64 val; 413 }; 414 415 static res_t results[kMaxCommands]; 416 417 const uint64 kInMagic = 0xbadc0ffeebadface; 418 419 struct handshake_req { 420 uint64 magic; 421 bool use_cover_edges; 422 bool is_kernel_64_bit; 423 rpc::ExecEnv flags; 424 uint64 pid; 425 uint64 sandbox_arg; 426 uint64 syscall_timeout_ms; 427 uint64 program_timeout_ms; 428 uint64 slowdown_scale; 429 }; 430 431 struct execute_req { 432 uint64 magic; 433 uint64 id; 434 rpc::RequestType type; 435 uint64 exec_flags; 436 uint64 all_call_signal; 437 bool all_extra_signal; 438 }; 439 440 struct execute_reply { 441 uint32 magic; 442 uint32 done; 443 uint32 status; 444 }; 445 446 enum { 447 KCOV_CMP_CONST = 1, 448 KCOV_CMP_SIZE1 = 0, 449 KCOV_CMP_SIZE2 = 2, 450 KCOV_CMP_SIZE4 = 4, 451 KCOV_CMP_SIZE8 = 6, 452 KCOV_CMP_SIZE_MASK = 6, 453 }; 454 455 struct kcov_comparison_t { 456 // Note: comparisons are always 64-bits regardless of kernel bitness. 457 uint64 type; 458 uint64 arg1; 459 uint64 arg2; 460 uint64 pc; 461 }; 462 463 typedef char kcov_comparison_size[sizeof(kcov_comparison_t) == 4 * sizeof(uint64) ? 1 : -1]; 464 465 struct feature_t { 466 rpc::Feature id; 467 const char* (*setup)(); 468 }; 469 470 static thread_t* schedule_call(int call_index, int call_num, uint64 copyout_index, uint64 num_args, uint64* args, uint8* pos, call_props_t call_props); 471 static void handle_completion(thread_t* th); 472 static void copyout_call_results(thread_t* th); 473 static void write_call_output(thread_t* th, bool finished); 474 static void write_extra_output(); 475 static void execute_call(thread_t* th); 476 static void thread_create(thread_t* th, int id, bool need_coverage); 477 static void thread_mmap_cover(thread_t* th); 478 static void* worker_thread(void* arg); 479 static uint64 read_input(uint8** input_posp, bool peek = false); 480 static uint64 read_arg(uint8** input_posp); 481 static uint64 read_const_arg(uint8** input_posp, uint64* size_p, uint64* bf, uint64* bf_off_p, uint64* bf_len_p); 482 static uint64 read_result(uint8** input_posp); 483 static uint64 swap(uint64 v, uint64 size, uint64 bf); 484 static void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len); 485 static bool copyout(char* addr, uint64 size, uint64* res); 486 static void setup_control_pipes(); 487 static bool coverage_filter(uint64 pc); 488 static rpc::ComparisonRaw convert(const kcov_comparison_t& cmp); 489 static flatbuffers::span<uint8_t> finish_output(OutputData* output, int proc_id, uint64 req_id, uint32 num_calls, 490 uint64 elapsed, uint64 freshness, uint32 status, bool hanged, 491 const std::vector<uint8_t>* process_output); 492 static void parse_execute(const execute_req& req); 493 static void parse_handshake(const handshake_req& req); 494 495 static void mmap_input(); 496 497 #include "syscalls.h" 498 499 #if GOOS_linux 500 #ifndef MAP_FIXED_NOREPLACE 501 #define MAP_FIXED_NOREPLACE 0x100000 502 #endif 503 #define MAP_FIXED_EXCLUSIVE MAP_FIXED_NOREPLACE 504 #elif GOOS_freebsd 505 #define MAP_FIXED_EXCLUSIVE (MAP_FIXED | MAP_EXCL) 506 #else 507 #define MAP_FIXED_EXCLUSIVE MAP_FIXED // The check is not supported. 508 #endif 509 510 #if GOOS_linux 511 #include "executor_linux.h" 512 #elif GOOS_fuchsia 513 #include "executor_fuchsia.h" 514 #elif GOOS_freebsd || GOOS_netbsd || GOOS_openbsd 515 #include "executor_bsd.h" 516 #elif GOOS_darwin 517 #include "executor_darwin.h" 518 #elif GOOS_windows 519 #include "executor_windows.h" 520 #elif GOOS_test 521 #include "executor_test.h" 522 #else 523 #error "unknown OS" 524 #endif 525 526 class CoverAccessScope final 527 { 528 public: 529 CoverAccessScope(cover_t* cov) 530 : cov_(cov) 531 { 532 // CoverAccessScope must not be used recursively b/c on Linux pkeys protection is global, 533 // so cover_protect for one cov overrides previous cover_unprotect for another cov. 534 if (used_) 535 fail("recursion in CoverAccessScope"); 536 used_ = true; 537 if (flag_coverage) 538 cover_unprotect(cov_); 539 } 540 ~CoverAccessScope() 541 { 542 if (flag_coverage) 543 cover_protect(cov_); 544 used_ = false; 545 } 546 547 private: 548 cover_t* const cov_; 549 static bool used_; 550 551 CoverAccessScope(const CoverAccessScope&) = delete; 552 CoverAccessScope& operator=(const CoverAccessScope&) = delete; 553 }; 554 555 bool CoverAccessScope::used_; 556 557 #if !SYZ_HAVE_FEATURES 558 static feature_t features[] = {}; 559 #endif 560 561 #include "shmem.h" 562 563 #include "conn.h" 564 #include "cover_filter.h" 565 #include "files.h" 566 #include "subprocess.h" 567 568 #include "snapshot.h" 569 570 #include "executor_runner.h" 571 572 #include "test.h" 573 574 static std::optional<CoverFilter> max_signal; 575 static std::optional<CoverFilter> cover_filter; 576 577 #if SYZ_HAVE_SANDBOX_ANDROID 578 static uint64 sandbox_arg = 0; 579 #endif 580 581 int main(int argc, char** argv) 582 { 583 if (argc == 1) { 584 fprintf(stderr, "no command"); 585 return 1; 586 } 587 if (strcmp(argv[1], "runner") == 0) { 588 runner(argv, argc); 589 fail("runner returned"); 590 } 591 if (strcmp(argv[1], "leak") == 0) { 592 #if SYZ_HAVE_LEAK_CHECK 593 check_leaks(argv + 2, argc - 2); 594 #else 595 fail("leak checking is not implemented"); 596 #endif 597 return 0; 598 } 599 if (strcmp(argv[1], "test") == 0) 600 return run_tests(argc == 3 ? argv[2] : nullptr); 601 602 if (strcmp(argv[1], "exec") != 0) { 603 fprintf(stderr, "unknown command"); 604 return 1; 605 } 606 607 start_time_ms = current_time_ms(); 608 609 os_init(argc, argv, (char*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE); 610 use_temporary_dir(); 611 install_segv_handler(); 612 current_thread = &threads[0]; 613 614 if (argc > 2 && strcmp(argv[2], "snapshot") == 0) { 615 SnapshotSetup(argv, argc); 616 } else { 617 mmap_input(); 618 mmap_output(kInitialOutput); 619 620 // Prevent test programs to mess with these fds. 621 // Due to races in collider mode, a program can e.g. ftruncate one of these fds, 622 // which will cause fuzzer to crash. 623 close(kInFd); 624 #if !SYZ_EXECUTOR_USES_FORK_SERVER 625 // For SYZ_EXECUTOR_USES_FORK_SERVER, close(kOutFd) is invoked in the forked child, 626 // after the program has been received. 627 close(kOutFd); 628 #endif 629 630 if (fcntl(kMaxSignalFd, F_GETFD) != -1) { 631 // Use random addresses for coverage filters to not collide with output_data. 632 max_signal.emplace(kMaxSignalFd, reinterpret_cast<void*>(0x110c230000ull)); 633 close(kMaxSignalFd); 634 } 635 if (fcntl(kCoverFilterFd, F_GETFD) != -1) { 636 cover_filter.emplace(kCoverFilterFd, reinterpret_cast<void*>(0x110f230000ull)); 637 close(kCoverFilterFd); 638 } 639 640 setup_control_pipes(); 641 receive_handshake(); 642 #if !SYZ_EXECUTOR_USES_FORK_SERVER 643 // We receive/reply handshake when fork server is disabled just to simplify runner logic. 644 // It's a bit suboptimal, but no fork server is much slower anyway. 645 reply_execute(0); 646 receive_execute(); 647 #endif 648 } 649 650 if (flag_coverage) { 651 int create_count = kCoverDefaultCount, mmap_count = create_count; 652 if (flag_delay_kcov_mmap) { 653 create_count = kCoverOptimizedCount; 654 mmap_count = kCoverOptimizedPreMmap; 655 } 656 if (create_count > kMaxThreads) 657 create_count = kMaxThreads; 658 for (int i = 0; i < create_count; i++) { 659 threads[i].cov.fd = kCoverFd + i; 660 cover_open(&threads[i].cov, false); 661 if (i < mmap_count) { 662 // Pre-mmap coverage collection for some threads. This should be enough for almost 663 // all programs, for the remaning few ones coverage will be set up when it's needed. 664 thread_mmap_cover(&threads[i]); 665 } 666 } 667 extra_cov.fd = kExtraCoverFd; 668 cover_open(&extra_cov, true); 669 cover_mmap(&extra_cov); 670 cover_protect(&extra_cov); 671 if (flag_extra_coverage) { 672 // Don't enable comps because we don't use them in the fuzzer yet. 673 cover_enable(&extra_cov, false, true); 674 } 675 } 676 677 int status = 0; 678 if (flag_sandbox_none) 679 status = do_sandbox_none(); 680 #if SYZ_HAVE_SANDBOX_SETUID 681 else if (flag_sandbox_setuid) 682 status = do_sandbox_setuid(); 683 #endif 684 #if SYZ_HAVE_SANDBOX_NAMESPACE 685 else if (flag_sandbox_namespace) 686 status = do_sandbox_namespace(); 687 #endif 688 #if SYZ_HAVE_SANDBOX_ANDROID 689 else if (flag_sandbox_android) 690 status = do_sandbox_android(sandbox_arg); 691 #endif 692 else 693 fail("unknown sandbox type"); 694 695 #if SYZ_EXECUTOR_USES_FORK_SERVER 696 fprintf(stderr, "loop exited with status %d\n", status); 697 // If an external sandbox process wraps executor, the out pipe will be closed 698 // before the sandbox process exits this will make ipc package kill the sandbox. 699 // As the result sandbox process will exit with exit status 9 instead of the executor 700 // exit status (notably kFailStatus). So we duplicate the exit status on the pipe. 701 reply_execute(status); 702 doexit(status); 703 // Unreachable. 704 return 1; 705 #else 706 reply_execute(status); 707 return status; 708 #endif 709 } 710 711 static uint32* input_base_address() 712 { 713 if (kAddressSanitizer) { 714 // ASan conflicts with -static, so we end up having a dynamically linked syz-executor binary. 715 // It's often the case that the libraries are mapped shortly after 0x7f0000000000, so we cannot 716 // blindly set some HighMemory address and hope it's free. 717 // Since we only run relatively safe (or fake) syscalls under tests, it should be fine to 718 // just use whatever address mmap() returns us. 719 return 0; 720 } 721 // It's the first time we map output region - generate its location. 722 // The output region is the only thing in executor process for which consistency matters. 723 // If it is corrupted ipc package will fail to parse its contents and panic. 724 // But fuzzer constantly invents new ways of how to corrupt the region, 725 // so we map the region at a (hopefully) hard to guess address with random offset, 726 // surrounded by unmapped pages. 727 // The address chosen must also work on 32-bit kernels with 1GB user address space. 728 const uint64 kOutputBase = 0x1b2bc20000ull; 729 return (uint32*)(kOutputBase + (1 << 20) * (getpid() % 128)); 730 } 731 732 static void mmap_input() 733 { 734 uint32* mmap_at = input_base_address(); 735 int flags = MAP_SHARED; 736 if (mmap_at != 0) 737 // If we map at a specific address, ensure it's not overlapping with anything else. 738 flags = flags | MAP_FIXED_EXCLUSIVE; 739 void* result = mmap(mmap_at, kMaxInput, PROT_READ, flags, kInFd, 0); 740 if (result == MAP_FAILED) 741 fail("mmap of input file failed"); 742 input_data = static_cast<uint8*>(result); 743 } 744 745 static uint32* output_base_address() 746 { 747 if (kAddressSanitizer) { 748 // See the comment in input_base_address(); 749 return 0; 750 } 751 if (output_data != NULL) { 752 // If output_data was already mapped, use the old base address 753 // since we could be extending the area from a different pid: 754 // realloc_output_data() may be called from a fork, which would cause 755 // input_base_address() to return a different address. 756 return (uint32*)output_data; 757 } 758 // Leave some unmmapped area after the input data. 759 return input_base_address() + kMaxInput + SYZ_PAGE_SIZE; 760 } 761 762 // This method can be invoked as many times as one likes - MMAP_FIXED can overwrite the previous 763 // mapping without any problems. The only precondition - kOutFd must not be closed. 764 static void mmap_output(uint32 size) 765 { 766 if (size <= output_size) 767 return; 768 if (size % SYZ_PAGE_SIZE != 0) 769 failmsg("trying to mmap output area that is not divisible by page size", "page=%d,area=%d", SYZ_PAGE_SIZE, size); 770 uint32* mmap_at = output_base_address(); 771 int flags = MAP_SHARED; 772 if (mmap_at == NULL) { 773 // We map at an address chosen by the kernel, so if there was any previous mapping, just unmap it. 774 if (output_data != NULL) { 775 int ret = munmap(output_data, output_size); 776 if (ret != 0) 777 fail("munmap failed"); 778 output_size = 0; 779 } 780 } else { 781 // We are possibly expanding the mmapped region. Adjust the parameters to avoid mmapping already 782 // mmapped area as much as possible. 783 // There exists a mremap call that could have helped, but it's purely Linux-specific. 784 mmap_at = (uint32*)((char*)(mmap_at) + output_size); 785 // Ensure we don't overwrite anything. 786 flags = flags | MAP_FIXED_EXCLUSIVE; 787 } 788 void* result = mmap(mmap_at, size - output_size, PROT_READ | PROT_WRITE, flags, kOutFd, output_size); 789 if (result == MAP_FAILED || (mmap_at && result != mmap_at)) 790 failmsg("mmap of output file failed", "want %p, got %p", mmap_at, result); 791 if (output_size == 0) 792 output_data = static_cast<OutputData*>(result); 793 output_size = size; 794 } 795 796 void setup_control_pipes() 797 { 798 if (dup2(0, kInPipeFd) < 0) 799 fail("dup2(0, kInPipeFd) failed"); 800 if (dup2(1, kOutPipeFd) < 0) 801 fail("dup2(1, kOutPipeFd) failed"); 802 if (dup2(2, 1) < 0) 803 fail("dup2(2, 1) failed"); 804 // We used to close(0), but now we dup stderr to stdin to keep fd numbers 805 // stable across executor and C programs generated by pkg/csource. 806 if (dup2(2, 0) < 0) 807 fail("dup2(2, 0) failed"); 808 } 809 810 void receive_handshake() 811 { 812 handshake_req req = {}; 813 ssize_t n = read(kInPipeFd, &req, sizeof(req)); 814 if (n != sizeof(req)) 815 failmsg("handshake read failed", "read=%zu", n); 816 parse_handshake(req); 817 } 818 819 void parse_handshake(const handshake_req& req) 820 { 821 if (req.magic != kInMagic) 822 failmsg("bad handshake magic", "magic=0x%llx", req.magic); 823 #if SYZ_HAVE_SANDBOX_ANDROID 824 sandbox_arg = req.sandbox_arg; 825 #endif 826 is_kernel_64_bit = req.is_kernel_64_bit; 827 use_cover_edges = req.use_cover_edges; 828 procid = req.pid; 829 syscall_timeout_ms = req.syscall_timeout_ms; 830 program_timeout_ms = req.program_timeout_ms; 831 slowdown_scale = req.slowdown_scale; 832 flag_debug = (bool)(req.flags & rpc::ExecEnv::Debug); 833 flag_coverage = (bool)(req.flags & rpc::ExecEnv::Signal); 834 flag_read_only_coverage = (bool)(req.flags & rpc::ExecEnv::ReadOnlyCoverage); 835 flag_sandbox_none = (bool)(req.flags & rpc::ExecEnv::SandboxNone); 836 flag_sandbox_setuid = (bool)(req.flags & rpc::ExecEnv::SandboxSetuid); 837 flag_sandbox_namespace = (bool)(req.flags & rpc::ExecEnv::SandboxNamespace); 838 flag_sandbox_android = (bool)(req.flags & rpc::ExecEnv::SandboxAndroid); 839 flag_extra_coverage = (bool)(req.flags & rpc::ExecEnv::ExtraCover); 840 flag_net_injection = (bool)(req.flags & rpc::ExecEnv::EnableTun); 841 flag_net_devices = (bool)(req.flags & rpc::ExecEnv::EnableNetDev); 842 flag_net_reset = (bool)(req.flags & rpc::ExecEnv::EnableNetReset); 843 flag_cgroups = (bool)(req.flags & rpc::ExecEnv::EnableCgroups); 844 flag_close_fds = (bool)(req.flags & rpc::ExecEnv::EnableCloseFds); 845 flag_devlink_pci = (bool)(req.flags & rpc::ExecEnv::EnableDevlinkPCI); 846 flag_vhci_injection = (bool)(req.flags & rpc::ExecEnv::EnableVhciInjection); 847 flag_wifi = (bool)(req.flags & rpc::ExecEnv::EnableWifi); 848 flag_delay_kcov_mmap = (bool)(req.flags & rpc::ExecEnv::DelayKcovMmap); 849 flag_nic_vf = (bool)(req.flags & rpc::ExecEnv::EnableNicVF); 850 } 851 852 void receive_execute() 853 { 854 execute_req req = {}; 855 ssize_t n = 0; 856 while ((n = read(kInPipeFd, &req, sizeof(req))) == -1 && errno == EINTR) 857 ; 858 if (n != (ssize_t)sizeof(req)) 859 failmsg("control pipe read failed", "read=%zd want=%zd", n, sizeof(req)); 860 parse_execute(req); 861 } 862 863 void parse_execute(const execute_req& req) 864 { 865 request_id = req.id; 866 request_type = req.type; 867 flag_collect_signal = req.exec_flags & (uint64)rpc::ExecFlag::CollectSignal; 868 flag_collect_cover = req.exec_flags & (uint64)rpc::ExecFlag::CollectCover; 869 flag_dedup_cover = req.exec_flags & (uint64)rpc::ExecFlag::DedupCover; 870 flag_comparisons = req.exec_flags & (uint64)rpc::ExecFlag::CollectComps; 871 flag_threaded = req.exec_flags & (uint64)rpc::ExecFlag::Threaded; 872 all_call_signal = req.all_call_signal; 873 all_extra_signal = req.all_extra_signal; 874 875 debug("[%llums] exec opts: reqid=%llu type=%llu procid=%llu threaded=%d cover=%d comps=%d dedup=%d signal=%d " 876 " sandbox=%d/%d/%d/%d timeouts=%llu/%llu/%llu kernel_64_bit=%d\n", 877 current_time_ms() - start_time_ms, request_id, (uint64)request_type, procid, flag_threaded, flag_collect_cover, 878 flag_comparisons, flag_dedup_cover, flag_collect_signal, flag_sandbox_none, flag_sandbox_setuid, 879 flag_sandbox_namespace, flag_sandbox_android, syscall_timeout_ms, program_timeout_ms, slowdown_scale, 880 is_kernel_64_bit); 881 if (syscall_timeout_ms == 0 || program_timeout_ms <= syscall_timeout_ms || slowdown_scale == 0) 882 failmsg("bad timeouts", "syscall=%llu, program=%llu, scale=%llu", 883 syscall_timeout_ms, program_timeout_ms, slowdown_scale); 884 } 885 886 bool cover_collection_required() 887 { 888 return flag_coverage && (flag_collect_signal || flag_collect_cover || flag_comparisons); 889 } 890 891 void reply_execute(uint32 status) 892 { 893 if (flag_snapshot) 894 SnapshotDone(status == kFailStatus); 895 if (write(kOutPipeFd, &status, sizeof(status)) != sizeof(status)) 896 fail("control pipe write failed"); 897 } 898 899 void realloc_output_data() 900 { 901 #if SYZ_EXECUTOR_USES_FORK_SERVER 902 if (flag_comparisons) 903 mmap_output(kMaxOutputComparisons); 904 else if (flag_collect_cover) 905 mmap_output(kMaxOutputCoverage); 906 else if (flag_collect_signal) 907 mmap_output(kMaxOutputSignal); 908 if (close(kOutFd) < 0) 909 fail("failed to close kOutFd"); 910 #endif 911 } 912 913 void execute_glob() 914 { 915 const char* pattern = (const char*)input_data; 916 const auto& files = Glob(pattern); 917 size_t size = 0; 918 for (const auto& file : files) 919 size += file.size() + 1; 920 mmap_output(kMaxOutput); 921 ShmemBuilder fbb(output_data, kMaxOutput, true); 922 uint8_t* pos = nullptr; 923 auto off = fbb.CreateUninitializedVector(size, &pos); 924 for (const auto& file : files) { 925 memcpy(pos, file.c_str(), file.size() + 1); 926 pos += file.size() + 1; 927 } 928 output_data->consumed.store(fbb.GetSize(), std::memory_order_release); 929 output_data->result_offset.store(off, std::memory_order_release); 930 } 931 932 // execute_one executes program stored in input_data. 933 void execute_one() 934 { 935 if (request_type == rpc::RequestType::Glob) { 936 execute_glob(); 937 return; 938 } 939 if (request_type != rpc::RequestType::Program) 940 failmsg("bad request type", "type=%llu", (uint64)request_type); 941 942 in_execute_one = true; 943 #if GOOS_linux 944 char buf[64]; 945 // Linux TASK_COMM_LEN is only 16, so the name needs to be compact. 946 snprintf(buf, sizeof(buf), "syz.%llu.%llu", procid, request_id); 947 prctl(PR_SET_NAME, buf); 948 #endif 949 if (flag_snapshot) 950 SnapshotStart(); 951 else 952 realloc_output_data(); 953 // Output buffer may be pkey-protected in snapshot mode, so don't write the output size 954 // (it's fixed and known anyway). 955 output_builder.emplace(output_data, output_size, !flag_snapshot); 956 uint64 start = current_time_ms(); 957 uint8* input_pos = input_data; 958 959 if (cover_collection_required()) { 960 if (!flag_threaded) 961 cover_enable(&threads[0].cov, flag_comparisons, false); 962 if (flag_extra_coverage) 963 cover_reset(&extra_cov); 964 } 965 966 int call_index = 0; 967 uint64 prog_extra_timeout = 0; 968 uint64 prog_extra_cover_timeout = 0; 969 call_props_t call_props; 970 memset(&call_props, 0, sizeof(call_props)); 971 972 read_input(&input_pos); // total number of calls 973 for (;;) { 974 uint64 call_num = read_input(&input_pos); 975 if (call_num == instr_eof) 976 break; 977 if (call_num == instr_copyin) { 978 char* addr = (char*)(read_input(&input_pos) + SYZ_DATA_OFFSET); 979 uint64 typ = read_input(&input_pos); 980 switch (typ) { 981 case arg_const: { 982 uint64 size, bf, bf_off, bf_len; 983 uint64 arg = read_const_arg(&input_pos, &size, &bf, &bf_off, &bf_len); 984 copyin(addr, arg, size, bf, bf_off, bf_len); 985 break; 986 } 987 case arg_addr32: 988 case arg_addr64: { 989 uint64 val = read_input(&input_pos) + SYZ_DATA_OFFSET; 990 if (typ == arg_addr32) 991 NONFAILING(*(uint32*)addr = val); 992 else 993 NONFAILING(*(uint64*)addr = val); 994 break; 995 } 996 case arg_result: { 997 uint64 meta = read_input(&input_pos); 998 uint64 size = meta & 0xff; 999 uint64 bf = meta >> 8; 1000 uint64 val = read_result(&input_pos); 1001 copyin(addr, val, size, bf, 0, 0); 1002 break; 1003 } 1004 case arg_data: { 1005 uint64 size = read_input(&input_pos); 1006 size &= ~(1ull << 63); // readable flag 1007 if (input_pos + size > input_data + kMaxInput) 1008 fail("data arg overflow"); 1009 NONFAILING(memcpy(addr, input_pos, size)); 1010 input_pos += size; 1011 break; 1012 } 1013 case arg_csum: { 1014 debug_verbose("checksum found at %p\n", addr); 1015 uint64 size = read_input(&input_pos); 1016 char* csum_addr = addr; 1017 uint64 csum_kind = read_input(&input_pos); 1018 switch (csum_kind) { 1019 case arg_csum_inet: { 1020 if (size != 2) 1021 failmsg("bag inet checksum size", "size=%llu", size); 1022 debug_verbose("calculating checksum for %p\n", csum_addr); 1023 struct csum_inet csum; 1024 csum_inet_init(&csum); 1025 uint64 chunks_num = read_input(&input_pos); 1026 uint64 chunk; 1027 for (chunk = 0; chunk < chunks_num; chunk++) { 1028 uint64 chunk_kind = read_input(&input_pos); 1029 uint64 chunk_value = read_input(&input_pos); 1030 uint64 chunk_size = read_input(&input_pos); 1031 switch (chunk_kind) { 1032 case arg_csum_chunk_data: 1033 chunk_value += SYZ_DATA_OFFSET; 1034 debug_verbose("#%lld: data chunk, addr: %llx, size: %llu\n", 1035 chunk, chunk_value, chunk_size); 1036 NONFAILING(csum_inet_update(&csum, (const uint8*)chunk_value, chunk_size)); 1037 break; 1038 case arg_csum_chunk_const: 1039 if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) 1040 failmsg("bad checksum const chunk size", "size=%lld", chunk_size); 1041 // Here we assume that const values come to us big endian. 1042 debug_verbose("#%lld: const chunk, value: %llx, size: %llu\n", 1043 chunk, chunk_value, chunk_size); 1044 csum_inet_update(&csum, (const uint8*)&chunk_value, chunk_size); 1045 break; 1046 default: 1047 failmsg("bad checksum chunk kind", "kind=%llu", chunk_kind); 1048 } 1049 } 1050 uint16 csum_value = csum_inet_digest(&csum); 1051 debug_verbose("writing inet checksum %hx to %p\n", csum_value, csum_addr); 1052 copyin(csum_addr, csum_value, 2, binary_format_native, 0, 0); 1053 break; 1054 } 1055 default: 1056 failmsg("bad checksum kind", "kind=%llu", csum_kind); 1057 } 1058 break; 1059 } 1060 default: 1061 failmsg("bad argument type", "type=%llu", typ); 1062 } 1063 continue; 1064 } 1065 if (call_num == instr_copyout) { 1066 read_input(&input_pos); // index 1067 read_input(&input_pos); // addr 1068 read_input(&input_pos); // size 1069 // The copyout will happen when/if the call completes. 1070 continue; 1071 } 1072 if (call_num == instr_setprops) { 1073 read_call_props_t(call_props, read_input(&input_pos, false)); 1074 continue; 1075 } 1076 1077 // Normal syscall. 1078 if (call_num >= ARRAY_SIZE(syscalls)) 1079 failmsg("invalid syscall number", "call_num=%llu", call_num); 1080 const call_t* call = &syscalls[call_num]; 1081 if (prog_extra_timeout < call->attrs.prog_timeout) 1082 prog_extra_timeout = call->attrs.prog_timeout * slowdown_scale; 1083 if (call->attrs.remote_cover) 1084 prog_extra_cover_timeout = 500 * slowdown_scale; // 500 ms 1085 uint64 copyout_index = read_input(&input_pos); 1086 uint64 num_args = read_input(&input_pos); 1087 if (num_args > kMaxArgs) 1088 failmsg("command has bad number of arguments", "args=%llu", num_args); 1089 uint64 args[kMaxArgs] = {}; 1090 for (uint64 i = 0; i < num_args; i++) 1091 args[i] = read_arg(&input_pos); 1092 for (uint64 i = num_args; i < kMaxArgs; i++) 1093 args[i] = 0; 1094 thread_t* th = schedule_call(call_index++, call_num, copyout_index, 1095 num_args, args, input_pos, call_props); 1096 1097 if (call_props.async && flag_threaded) { 1098 // Don't wait for an async call to finish. We'll wait at the end. 1099 // If we're not in the threaded mode, just ignore the async flag - during repro simplification syzkaller 1100 // will anyway try to make it non-threaded. 1101 } else if (flag_threaded) { 1102 // Wait for call completion. 1103 uint64 timeout_ms = syscall_timeout_ms + call->attrs.timeout * slowdown_scale; 1104 // This is because of printing pre/post call. Ideally we print everything in the main thread 1105 // and then remove this (would also avoid intermixed output). 1106 if (flag_debug && timeout_ms < 1000) 1107 timeout_ms = 1000; 1108 if (event_timedwait(&th->done, timeout_ms)) 1109 handle_completion(th); 1110 1111 // Check if any of previous calls have completed. 1112 for (int i = 0; i < kMaxThreads; i++) { 1113 th = &threads[i]; 1114 if (th->executing && event_isset(&th->done)) 1115 handle_completion(th); 1116 } 1117 } else { 1118 // Execute directly. 1119 if (th != &threads[0]) 1120 fail("using non-main thread in non-thread mode"); 1121 event_reset(&th->ready); 1122 execute_call(th); 1123 event_set(&th->done); 1124 handle_completion(th); 1125 } 1126 memset(&call_props, 0, sizeof(call_props)); 1127 } 1128 1129 if (running > 0) { 1130 // Give unfinished syscalls some additional time. 1131 last_scheduled = 0; 1132 uint64 wait_start = current_time_ms(); 1133 uint64 wait_end = wait_start + 2 * syscall_timeout_ms; 1134 wait_end = std::max(wait_end, start + program_timeout_ms / 6); 1135 wait_end = std::max(wait_end, wait_start + prog_extra_timeout); 1136 while (running > 0 && current_time_ms() <= wait_end) { 1137 sleep_ms(1 * slowdown_scale); 1138 for (int i = 0; i < kMaxThreads; i++) { 1139 thread_t* th = &threads[i]; 1140 if (th->executing && event_isset(&th->done)) 1141 handle_completion(th); 1142 } 1143 } 1144 // Write output coverage for unfinished calls. 1145 if (running > 0) { 1146 for (int i = 0; i < kMaxThreads; i++) { 1147 thread_t* th = &threads[i]; 1148 if (th->executing) { 1149 if (cover_collection_required()) 1150 cover_collect(&th->cov); 1151 write_call_output(th, false); 1152 } 1153 } 1154 } 1155 } 1156 1157 #if SYZ_HAVE_CLOSE_FDS 1158 close_fds(); 1159 #endif 1160 1161 write_extra_output(); 1162 if (flag_extra_coverage) { 1163 // Check for new extra coverage in small intervals to avoid situation 1164 // that we were killed on timeout before we write any. 1165 // Check for extra coverage is very cheap, effectively a memory load. 1166 const uint64 kSleepMs = 100; 1167 for (uint64 i = 0; i < prog_extra_cover_timeout / kSleepMs && 1168 output_data->completed.load(std::memory_order_relaxed) < kMaxCalls; 1169 i++) { 1170 sleep_ms(kSleepMs); 1171 write_extra_output(); 1172 } 1173 } 1174 } 1175 1176 thread_t* schedule_call(int call_index, int call_num, uint64 copyout_index, uint64 num_args, uint64* args, uint8* pos, call_props_t call_props) 1177 { 1178 // Find a spare thread to execute the call. 1179 int i = 0; 1180 for (; i < kMaxThreads; i++) { 1181 thread_t* th = &threads[i]; 1182 if (!th->created) 1183 thread_create(th, i, cover_collection_required()); 1184 if (event_isset(&th->done)) { 1185 if (th->executing) 1186 handle_completion(th); 1187 break; 1188 } 1189 } 1190 if (i == kMaxThreads) 1191 exitf("out of threads"); 1192 thread_t* th = &threads[i]; 1193 if (event_isset(&th->ready) || !event_isset(&th->done) || th->executing) 1194 exitf("bad thread state in schedule: ready=%d done=%d executing=%d", 1195 event_isset(&th->ready), event_isset(&th->done), th->executing); 1196 last_scheduled = th; 1197 th->copyout_pos = pos; 1198 th->copyout_index = copyout_index; 1199 event_reset(&th->done); 1200 // We do this both right before execute_syscall in the thread and here because: 1201 // the former is useful to reset all unrelated coverage from our syscalls (e.g. futex in event_wait), 1202 // while the reset here is useful to avoid the following scenario that the fuzzer was able to trigger. 1203 // If the test program contains seccomp syscall that kills the worker thread on the next syscall, 1204 // then it won't receive this next syscall and won't do cover_reset. If we are collecting comparions 1205 // then we've already transformed comparison data from the previous syscall into rpc::ComparisonRaw 1206 // in write_comparisons. That data is still in the buffer. The first word of rpc::ComparisonRaw is PC 1207 // which overlaps with comparison type in kernel exposed records. As the result write_comparisons 1208 // that will try to write out data from unfinished syscalls will see these rpc::ComparisonRaw records, 1209 // mis-interpret PC as type, and fail as: SYZFAIL: invalid kcov comp type (type=ffffffff8100b4e0). 1210 if (flag_coverage) 1211 cover_reset(&th->cov); 1212 th->executing = true; 1213 th->call_index = call_index; 1214 th->call_num = call_num; 1215 th->num_args = num_args; 1216 th->call_props = call_props; 1217 for (int i = 0; i < kMaxArgs; i++) 1218 th->args[i] = args[i]; 1219 event_set(&th->ready); 1220 running++; 1221 return th; 1222 } 1223 1224 template <typename cover_data_t> 1225 uint32 write_signal(flatbuffers::FlatBufferBuilder& fbb, int index, cover_t* cov, bool all) 1226 { 1227 // Write out feedback signals. 1228 // Currently it is code edges computed as xor of two subsequent basic block PCs. 1229 fbb.StartVector<uint64_t>(0); 1230 cover_data_t* cover_data = (cover_data_t*)(cov->data + cov->data_offset); 1231 if ((char*)(cover_data + cov->size) > cov->data_end) 1232 failmsg("too much cover", "cov=%u", cov->size); 1233 uint32 nsig = 0; 1234 cover_data_t prev_pc = 0; 1235 bool prev_filter = true; 1236 for (uint32 i = 0; i < cov->size; i++) { 1237 cover_data_t pc = cover_data[i] + cov->pc_offset; 1238 uint64 sig = pc; 1239 if (use_cover_edges) { 1240 // Only hash the lower 12 bits so the hash is independent of any module offsets. 1241 const uint64 mask = (1 << 12) - 1; 1242 sig ^= hash(prev_pc & mask) & mask; 1243 } 1244 bool filter = coverage_filter(pc); 1245 // Ignore the edge only if both current and previous PCs are filtered out 1246 // to capture all incoming and outcoming edges into the interesting code. 1247 bool ignore = !filter && !prev_filter; 1248 prev_pc = pc; 1249 prev_filter = filter; 1250 if (ignore || dedup(index, sig)) 1251 continue; 1252 if (!all && max_signal && max_signal->Contains(sig)) 1253 continue; 1254 fbb.PushElement(uint64(sig)); 1255 nsig++; 1256 } 1257 return fbb.EndVector(nsig); 1258 } 1259 1260 template <typename cover_data_t> 1261 uint32 write_cover(flatbuffers::FlatBufferBuilder& fbb, cover_t* cov) 1262 { 1263 uint32 cover_size = cov->size; 1264 cover_data_t* cover_data = (cover_data_t*)(cov->data + cov->data_offset); 1265 if (flag_dedup_cover) { 1266 cover_data_t* end = cover_data + cover_size; 1267 std::sort(cover_data, end); 1268 cover_size = std::unique(cover_data, end) - cover_data; 1269 } 1270 fbb.StartVector<uint64_t>(cover_size); 1271 // Flatbuffer arrays are written backwards, so reverse the order on our side as well. 1272 for (uint32 i = 0; i < cover_size; i++) 1273 fbb.PushElement(uint64(cover_data[cover_size - i - 1] + cov->pc_offset)); 1274 return fbb.EndVector(cover_size); 1275 } 1276 1277 uint32 write_comparisons(flatbuffers::FlatBufferBuilder& fbb, cover_t* cov) 1278 { 1279 // Collect only the comparisons 1280 uint64 ncomps = *(uint64_t*)cov->data; 1281 kcov_comparison_t* cov_start = (kcov_comparison_t*)(cov->data + sizeof(uint64)); 1282 if ((char*)(cov_start + ncomps) > cov->data_end) 1283 failmsg("too many comparisons", "ncomps=%llu", ncomps); 1284 cov->overflow = ((char*)(cov_start + ncomps + 1) > cov->data_end); 1285 rpc::ComparisonRaw* start = (rpc::ComparisonRaw*)cov_start; 1286 rpc::ComparisonRaw* end = start; 1287 // We will convert kcov_comparison_t to ComparisonRaw inplace. 1288 static_assert(sizeof(kcov_comparison_t) >= sizeof(rpc::ComparisonRaw)); 1289 for (uint32 i = 0; i < ncomps; i++) { 1290 auto raw = convert(cov_start[i]); 1291 if (!raw.pc()) 1292 continue; 1293 *end++ = raw; 1294 } 1295 std::sort(start, end, [](rpc::ComparisonRaw a, rpc::ComparisonRaw b) -> bool { 1296 if (a.pc() != b.pc()) 1297 return a.pc() < b.pc(); 1298 if (a.op1() != b.op1()) 1299 return a.op1() < b.op1(); 1300 return a.op2() < b.op2(); 1301 }); 1302 ncomps = std::unique(start, end, [](rpc::ComparisonRaw a, rpc::ComparisonRaw b) -> bool { 1303 return a.pc() == b.pc() && a.op1() == b.op1() && a.op2() == b.op2(); 1304 }) - 1305 start; 1306 return fbb.CreateVectorOfStructs(start, ncomps).o; 1307 } 1308 1309 bool coverage_filter(uint64 pc) 1310 { 1311 if (!cover_filter) 1312 return true; 1313 return cover_filter->Contains(pc); 1314 } 1315 1316 void handle_completion(thread_t* th) 1317 { 1318 if (event_isset(&th->ready) || !event_isset(&th->done) || !th->executing) 1319 exitf("bad thread state in completion: ready=%d done=%d executing=%d", 1320 event_isset(&th->ready), event_isset(&th->done), th->executing); 1321 if (th->res != (intptr_t)-1) 1322 copyout_call_results(th); 1323 1324 write_call_output(th, true); 1325 write_extra_output(); 1326 th->executing = false; 1327 running--; 1328 if (running < 0) { 1329 // This fires periodically for the past 2 years (see issue #502). 1330 fprintf(stderr, "running=%d completed=%d flag_threaded=%d current=%d\n", 1331 running, completed, flag_threaded, th->id); 1332 for (int i = 0; i < kMaxThreads; i++) { 1333 thread_t* th1 = &threads[i]; 1334 fprintf(stderr, "th #%2d: created=%d executing=%d" 1335 " ready=%d done=%d call_index=%d res=%lld reserrno=%d\n", 1336 i, th1->created, th1->executing, 1337 event_isset(&th1->ready), event_isset(&th1->done), 1338 th1->call_index, (uint64)th1->res, th1->reserrno); 1339 } 1340 exitf("negative running"); 1341 } 1342 } 1343 1344 void copyout_call_results(thread_t* th) 1345 { 1346 if (th->copyout_index != no_copyout) { 1347 if (th->copyout_index >= kMaxCommands) 1348 failmsg("result overflows kMaxCommands", "index=%lld", th->copyout_index); 1349 results[th->copyout_index].executed = true; 1350 results[th->copyout_index].val = th->res; 1351 } 1352 for (bool done = false; !done;) { 1353 uint64 instr = read_input(&th->copyout_pos); 1354 switch (instr) { 1355 case instr_copyout: { 1356 uint64 index = read_input(&th->copyout_pos); 1357 if (index >= kMaxCommands) 1358 failmsg("result overflows kMaxCommands", "index=%lld", index); 1359 char* addr = (char*)(read_input(&th->copyout_pos) + SYZ_DATA_OFFSET); 1360 uint64 size = read_input(&th->copyout_pos); 1361 uint64 val = 0; 1362 if (copyout(addr, size, &val)) { 1363 results[index].executed = true; 1364 results[index].val = val; 1365 } 1366 debug_verbose("copyout 0x%llx from %p\n", val, addr); 1367 break; 1368 } 1369 default: 1370 done = true; 1371 break; 1372 } 1373 } 1374 } 1375 1376 void write_output(int index, cover_t* cov, rpc::CallFlag flags, uint32 error, bool all_signal) 1377 { 1378 CoverAccessScope scope(cov); 1379 auto& fbb = *output_builder; 1380 const uint32 start_size = output_builder->GetSize(); 1381 (void)start_size; 1382 uint32 signal_off = 0; 1383 uint32 cover_off = 0; 1384 uint32 comps_off = 0; 1385 if (flag_comparisons) { 1386 comps_off = write_comparisons(fbb, cov); 1387 } else { 1388 if (flag_collect_signal) { 1389 if (is_kernel_64_bit) 1390 signal_off = write_signal<uint64>(fbb, index, cov, all_signal); 1391 else 1392 signal_off = write_signal<uint32>(fbb, index, cov, all_signal); 1393 } 1394 if (flag_collect_cover) { 1395 if (is_kernel_64_bit) 1396 cover_off = write_cover<uint64>(fbb, cov); 1397 else 1398 cover_off = write_cover<uint32>(fbb, cov); 1399 } 1400 } 1401 1402 rpc::CallInfoRawBuilder builder(*output_builder); 1403 if (cov->overflow) 1404 flags |= rpc::CallFlag::CoverageOverflow; 1405 builder.add_flags(flags); 1406 builder.add_error(error); 1407 if (signal_off) 1408 builder.add_signal(signal_off); 1409 if (cover_off) 1410 builder.add_cover(cover_off); 1411 if (comps_off) 1412 builder.add_comps(comps_off); 1413 auto off = builder.Finish(); 1414 uint32 slot = output_data->completed.load(std::memory_order_relaxed); 1415 if (slot >= kMaxCalls) 1416 failmsg("too many calls in output", "slot=%d", slot); 1417 auto& call = output_data->calls[slot]; 1418 call.index = index; 1419 call.offset = off; 1420 output_data->consumed.store(output_builder->GetSize(), std::memory_order_release); 1421 output_data->completed.store(slot + 1, std::memory_order_release); 1422 debug_verbose("out #%u: index=%u errno=%d flags=0x%x total_size=%u\n", 1423 slot + 1, index, error, static_cast<unsigned>(flags), call.data_size - start_size); 1424 } 1425 1426 void write_call_output(thread_t* th, bool finished) 1427 { 1428 uint32 reserrno = ENOSYS; 1429 rpc::CallFlag flags = rpc::CallFlag::Executed; 1430 if (finished && th != last_scheduled) 1431 flags |= rpc::CallFlag::Blocked; 1432 if (finished) { 1433 reserrno = th->res != -1 ? 0 : th->reserrno; 1434 flags |= rpc::CallFlag::Finished; 1435 if (th->fault_injected) 1436 flags |= rpc::CallFlag::FaultInjected; 1437 } 1438 bool all_signal = th->call_index < 64 ? (all_call_signal & (1ull << th->call_index)) : false; 1439 write_output(th->call_index, &th->cov, flags, reserrno, all_signal); 1440 } 1441 1442 void write_extra_output() 1443 { 1444 if (!cover_collection_required() || !flag_extra_coverage || flag_comparisons) 1445 return; 1446 cover_collect(&extra_cov); 1447 if (!extra_cov.size) 1448 return; 1449 write_output(-1, &extra_cov, rpc::CallFlag::NONE, 997, all_extra_signal); 1450 cover_reset(&extra_cov); 1451 } 1452 1453 flatbuffers::span<uint8_t> finish_output(OutputData* output, int proc_id, uint64 req_id, uint32 num_calls, uint64 elapsed, 1454 uint64 freshness, uint32 status, bool hanged, const std::vector<uint8_t>* process_output) 1455 { 1456 // In snapshot mode the output size is fixed and output_size is always initialized, so use it. 1457 int out_size = flag_snapshot ? output_size : output->size.load(std::memory_order_relaxed) ? 1458 : kMaxOutput; 1459 uint32 completed = output->completed.load(std::memory_order_relaxed); 1460 completed = std::min(completed, kMaxCalls); 1461 debug("handle completion: completed=%u output_size=%u\n", completed, out_size); 1462 ShmemBuilder fbb(output, out_size, false); 1463 auto empty_call = rpc::CreateCallInfoRawDirect(fbb, rpc::CallFlag::NONE, 998); 1464 std::vector<flatbuffers::Offset<rpc::CallInfoRaw>> calls(num_calls, empty_call); 1465 std::vector<flatbuffers::Offset<rpc::CallInfoRaw>> extra; 1466 for (uint32_t i = 0; i < completed; i++) { 1467 const auto& call = output->calls[i]; 1468 if (call.index == -1) { 1469 extra.push_back(call.offset); 1470 continue; 1471 } 1472 if (call.index < 0 || call.index >= static_cast<int>(num_calls) || call.offset.o > kMaxOutput) { 1473 debug("bad call index/offset: proc=%d req=%llu call=%d/%d completed=%d offset=%u", 1474 proc_id, req_id, call.index, num_calls, 1475 completed, call.offset.o); 1476 continue; 1477 } 1478 calls[call.index] = call.offset; 1479 } 1480 auto prog_info_off = rpc::CreateProgInfoRawDirect(fbb, &calls, &extra, 0, elapsed, freshness); 1481 flatbuffers::Offset<flatbuffers::String> error_off = 0; 1482 if (status == kFailStatus) 1483 error_off = fbb.CreateString("process failed"); 1484 // If the request wrote binary result (currently glob requests do this), use it instead of the output. 1485 auto output_off = output->result_offset.load(std::memory_order_relaxed); 1486 if (output_off.IsNull() && process_output) 1487 output_off = fbb.CreateVector(*process_output); 1488 auto exec_off = rpc::CreateExecResultRaw(fbb, req_id, proc_id, output_off, hanged, error_off, prog_info_off); 1489 auto msg_off = rpc::CreateExecutorMessageRaw(fbb, rpc::ExecutorMessagesRaw::ExecResult, 1490 flatbuffers::Offset<void>(exec_off.o)); 1491 fbb.FinishSizePrefixed(msg_off); 1492 return fbb.GetBufferSpan(); 1493 } 1494 1495 void thread_create(thread_t* th, int id, bool need_coverage) 1496 { 1497 th->created = true; 1498 th->id = id; 1499 th->executing = false; 1500 // Lazily set up coverage collection. 1501 // It is assumed that actually it's already initialized - with a few rare exceptions. 1502 if (need_coverage) { 1503 if (!th->cov.fd) 1504 exitf("out of opened kcov threads"); 1505 thread_mmap_cover(th); 1506 } 1507 event_init(&th->ready); 1508 event_init(&th->done); 1509 event_set(&th->done); 1510 if (flag_threaded) 1511 thread_start(worker_thread, th); 1512 } 1513 1514 void thread_mmap_cover(thread_t* th) 1515 { 1516 if (th->cov.data != NULL) 1517 return; 1518 cover_mmap(&th->cov); 1519 cover_protect(&th->cov); 1520 } 1521 1522 void* worker_thread(void* arg) 1523 { 1524 thread_t* th = (thread_t*)arg; 1525 current_thread = th; 1526 for (bool first = true;; first = false) { 1527 event_wait(&th->ready); 1528 event_reset(&th->ready); 1529 // Setup coverage only after receiving the first ready event 1530 // because in snapshot mode we don't know coverage mode for precreated threads. 1531 if (first && cover_collection_required()) 1532 cover_enable(&th->cov, flag_comparisons, false); 1533 execute_call(th); 1534 event_set(&th->done); 1535 } 1536 return 0; 1537 } 1538 1539 void execute_call(thread_t* th) 1540 { 1541 const call_t* call = &syscalls[th->call_num]; 1542 debug("#%d [%llums] -> %s(", 1543 th->id, current_time_ms() - start_time_ms, call->name); 1544 for (int i = 0; i < th->num_args; i++) { 1545 if (i != 0) 1546 debug(", "); 1547 debug("0x%llx", (uint64)th->args[i]); 1548 } 1549 debug(")\n"); 1550 1551 int fail_fd = -1; 1552 th->soft_fail_state = false; 1553 if (th->call_props.fail_nth > 0) { 1554 if (th->call_props.rerun > 0) 1555 fail("both fault injection and rerun are enabled for the same call"); 1556 fail_fd = inject_fault(th->call_props.fail_nth); 1557 th->soft_fail_state = true; 1558 } 1559 1560 if (flag_coverage) 1561 cover_reset(&th->cov); 1562 // For pseudo-syscalls and user-space functions NONFAILING can abort before assigning to th->res. 1563 // Arrange for res = -1 and errno = EFAULT result for such case. 1564 th->res = -1; 1565 errno = EFAULT; 1566 NONFAILING(th->res = execute_syscall(call, th->args)); 1567 th->reserrno = errno; 1568 // Our pseudo-syscalls may misbehave. 1569 if ((th->res == -1 && th->reserrno == 0) || call->attrs.ignore_return) 1570 th->reserrno = EINVAL; 1571 // Reset the flag before the first possible fail(). 1572 th->soft_fail_state = false; 1573 1574 if (flag_coverage) 1575 cover_collect(&th->cov); 1576 th->fault_injected = false; 1577 1578 if (th->call_props.fail_nth > 0) 1579 th->fault_injected = fault_injected(fail_fd); 1580 1581 // If required, run the syscall some more times. 1582 // But let's still return res, errno and coverage from the first execution. 1583 for (int i = 0; i < th->call_props.rerun; i++) 1584 NONFAILING(execute_syscall(call, th->args)); 1585 1586 debug("#%d [%llums] <- %s=0x%llx", 1587 th->id, current_time_ms() - start_time_ms, call->name, (uint64)th->res); 1588 if (th->res == (intptr_t)-1) 1589 debug(" errno=%d", th->reserrno); 1590 if (flag_coverage) 1591 debug(" cover=%u", th->cov.size); 1592 if (th->call_props.fail_nth > 0) 1593 debug(" fault=%d", th->fault_injected); 1594 if (th->call_props.rerun > 0) 1595 debug(" rerun=%d", th->call_props.rerun); 1596 debug("\n"); 1597 } 1598 1599 static uint32 hash(uint32 a) 1600 { 1601 // For test OS we disable hashing for determinism and testability. 1602 #if !GOOS_test 1603 a = (a ^ 61) ^ (a >> 16); 1604 a = a + (a << 3); 1605 a = a ^ (a >> 4); 1606 a = a * 0x27d4eb2d; 1607 a = a ^ (a >> 15); 1608 #endif 1609 return a; 1610 } 1611 1612 const uint32 dedup_table_size = 8 << 10; 1613 uint64 dedup_table_sig[dedup_table_size]; 1614 uint8 dedup_table_index[dedup_table_size]; 1615 1616 // Poorman's best-effort hashmap-based deduplication. 1617 static bool dedup(uint8 index, uint64 sig) 1618 { 1619 for (uint32 i = 0; i < 4; i++) { 1620 uint32 pos = (sig + i) % dedup_table_size; 1621 if (dedup_table_sig[pos] == sig && dedup_table_index[pos] == index) 1622 return true; 1623 if (dedup_table_sig[pos] == 0 || dedup_table_index[pos] != index) { 1624 dedup_table_index[pos] = index; 1625 dedup_table_sig[pos] = sig; 1626 return false; 1627 } 1628 } 1629 uint32 pos = sig % dedup_table_size; 1630 dedup_table_sig[pos] = sig; 1631 dedup_table_index[pos] = index; 1632 return false; 1633 } 1634 1635 template <typename T> 1636 void copyin_int(char* addr, uint64 val, uint64 bf, uint64 bf_off, uint64 bf_len) 1637 { 1638 if (bf_off == 0 && bf_len == 0) { 1639 *(T*)addr = swap(val, sizeof(T), bf); 1640 return; 1641 } 1642 T x = swap(*(T*)addr, sizeof(T), bf); 1643 debug_verbose("copyin_int<%zu>: old x=0x%llx\n", sizeof(T), (uint64)x); 1644 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 1645 const uint64 shift = sizeof(T) * CHAR_BIT - bf_off - bf_len; 1646 #else 1647 const uint64 shift = bf_off; 1648 #endif 1649 x = (x & ~BITMASK(shift, bf_len)) | ((val << shift) & BITMASK(shift, bf_len)); 1650 debug_verbose("copyin_int<%zu>: x=0x%llx\n", sizeof(T), (uint64)x); 1651 *(T*)addr = swap(x, sizeof(T), bf); 1652 } 1653 1654 void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len) 1655 { 1656 debug_verbose("copyin: addr=%p val=0x%llx size=%llu bf=%llu bf_off=%llu bf_len=%llu\n", 1657 addr, val, size, bf, bf_off, bf_len); 1658 if (bf != binary_format_native && bf != binary_format_bigendian && (bf_off != 0 || bf_len != 0)) 1659 failmsg("bitmask for string format", "off=%llu, len=%llu", bf_off, bf_len); 1660 switch (bf) { 1661 case binary_format_native: 1662 case binary_format_bigendian: 1663 NONFAILING(switch (size) { 1664 case 1: 1665 copyin_int<uint8>(addr, val, bf, bf_off, bf_len); 1666 break; 1667 case 2: 1668 copyin_int<uint16>(addr, val, bf, bf_off, bf_len); 1669 break; 1670 case 4: 1671 copyin_int<uint32>(addr, val, bf, bf_off, bf_len); 1672 break; 1673 case 8: 1674 copyin_int<uint64>(addr, val, bf, bf_off, bf_len); 1675 break; 1676 default: 1677 failmsg("copyin: bad argument size", "size=%llu", size); 1678 }); 1679 break; 1680 case binary_format_strdec: 1681 if (size != 20) 1682 failmsg("bad strdec size", "size=%llu", size); 1683 NONFAILING(sprintf((char*)addr, "%020llu", val)); 1684 break; 1685 case binary_format_strhex: 1686 if (size != 18) 1687 failmsg("bad strhex size", "size=%llu", size); 1688 NONFAILING(sprintf((char*)addr, "0x%016llx", val)); 1689 break; 1690 case binary_format_stroct: 1691 if (size != 23) 1692 failmsg("bad stroct size", "size=%llu", size); 1693 NONFAILING(sprintf((char*)addr, "%023llo", val)); 1694 break; 1695 default: 1696 failmsg("unknown binary format", "format=%llu", bf); 1697 } 1698 } 1699 1700 bool copyout(char* addr, uint64 size, uint64* res) 1701 { 1702 return NONFAILING( 1703 switch (size) { 1704 case 1: 1705 *res = *(uint8*)addr; 1706 break; 1707 case 2: 1708 *res = *(uint16*)addr; 1709 break; 1710 case 4: 1711 *res = *(uint32*)addr; 1712 break; 1713 case 8: 1714 *res = *(uint64*)addr; 1715 break; 1716 default: 1717 failmsg("copyout: bad argument size", "size=%llu", size); 1718 }); 1719 } 1720 1721 uint64 read_arg(uint8** input_posp) 1722 { 1723 uint64 typ = read_input(input_posp); 1724 switch (typ) { 1725 case arg_const: { 1726 uint64 size, bf, bf_off, bf_len; 1727 uint64 val = read_const_arg(input_posp, &size, &bf, &bf_off, &bf_len); 1728 if (bf != binary_format_native && bf != binary_format_bigendian) 1729 failmsg("bad argument binary format", "format=%llu", bf); 1730 if (bf_off != 0 || bf_len != 0) 1731 failmsg("bad argument bitfield", "off=%llu, len=%llu", bf_off, bf_len); 1732 return swap(val, size, bf); 1733 } 1734 case arg_addr32: 1735 case arg_addr64: { 1736 return read_input(input_posp) + SYZ_DATA_OFFSET; 1737 } 1738 case arg_result: { 1739 uint64 meta = read_input(input_posp); 1740 uint64 bf = meta >> 8; 1741 if (bf != binary_format_native) 1742 failmsg("bad result argument format", "format=%llu", bf); 1743 return read_result(input_posp); 1744 } 1745 default: 1746 failmsg("bad argument type", "type=%llu", typ); 1747 } 1748 } 1749 1750 uint64 swap(uint64 v, uint64 size, uint64 bf) 1751 { 1752 if (bf == binary_format_native) 1753 return v; 1754 if (bf != binary_format_bigendian) 1755 failmsg("bad binary format in swap", "format=%llu", bf); 1756 switch (size) { 1757 case 2: 1758 return htobe16(v); 1759 case 4: 1760 return htobe32(v); 1761 case 8: 1762 return htobe64(v); 1763 default: 1764 failmsg("bad big-endian int size", "size=%llu", size); 1765 } 1766 } 1767 1768 uint64 read_const_arg(uint8** input_posp, uint64* size_p, uint64* bf_p, uint64* bf_off_p, uint64* bf_len_p) 1769 { 1770 uint64 meta = read_input(input_posp); 1771 uint64 val = read_input(input_posp); 1772 *size_p = meta & 0xff; 1773 uint64 bf = (meta >> 8) & 0xff; 1774 *bf_off_p = (meta >> 16) & 0xff; 1775 *bf_len_p = (meta >> 24) & 0xff; 1776 uint64 pid_stride = meta >> 32; 1777 val += pid_stride * procid; 1778 *bf_p = bf; 1779 return val; 1780 } 1781 1782 uint64 read_result(uint8** input_posp) 1783 { 1784 uint64 idx = read_input(input_posp); 1785 uint64 op_div = read_input(input_posp); 1786 uint64 op_add = read_input(input_posp); 1787 uint64 arg = read_input(input_posp); 1788 if (idx >= kMaxCommands) 1789 failmsg("command refers to bad result", "result=%lld", idx); 1790 if (results[idx].executed) { 1791 arg = results[idx].val; 1792 if (op_div != 0) 1793 arg = arg / op_div; 1794 arg += op_add; 1795 } 1796 return arg; 1797 } 1798 1799 uint64 read_input(uint8** input_posp, bool peek) 1800 { 1801 uint64 v = 0; 1802 unsigned shift = 0; 1803 uint8* input_pos = *input_posp; 1804 for (int i = 0;; i++, shift += 7) { 1805 const int maxLen = 10; 1806 if (i == maxLen) 1807 failmsg("varint overflow", "pos=%zu", (size_t)(*input_posp - input_data)); 1808 if (input_pos >= input_data + kMaxInput) 1809 failmsg("input command overflows input", "pos=%p: [%p:%p)", 1810 input_pos, input_data, input_data + kMaxInput); 1811 uint8 b = *input_pos++; 1812 v |= uint64(b & 0x7f) << shift; 1813 if (b < 0x80) { 1814 if (i == maxLen - 1 && b > 1) 1815 failmsg("varint overflow", "pos=%zu", (size_t)(*input_posp - input_data)); 1816 break; 1817 } 1818 } 1819 if (v & 1) 1820 v = ~(v >> 1); 1821 else 1822 v = v >> 1; 1823 if (!peek) 1824 *input_posp = input_pos; 1825 return v; 1826 } 1827 1828 rpc::ComparisonRaw convert(const kcov_comparison_t& cmp) 1829 { 1830 if (cmp.type > (KCOV_CMP_CONST | KCOV_CMP_SIZE_MASK)) 1831 failmsg("invalid kcov comp type", "type=%llx", cmp.type); 1832 uint64 arg1 = cmp.arg1; 1833 uint64 arg2 = cmp.arg2; 1834 // Comparisons with 0 are not interesting, fuzzer should be able to guess 0's without help. 1835 if (arg1 == 0 && (arg2 == 0 || (cmp.type & KCOV_CMP_CONST))) 1836 return {}; 1837 // Successful comparison is not interesting. 1838 if (arg1 == arg2) 1839 return {}; 1840 1841 // This can be a pointer (assuming 64-bit kernel). 1842 // First of all, we want avert fuzzer from our output region. 1843 // Without this fuzzer manages to discover and corrupt it. 1844 uint64 out_start = (uint64)output_data; 1845 uint64 out_end = out_start + output_size; 1846 if (arg1 >= out_start && arg1 <= out_end) 1847 return {}; 1848 if (arg2 >= out_start && arg2 <= out_end) 1849 return {}; 1850 if (!coverage_filter(cmp.pc)) 1851 return {}; 1852 1853 // KCOV converts all arguments of size x first to uintx_t and then to uint64. 1854 // We want to properly extend signed values, e.g we want int8 c = 0xfe to be represented 1855 // as 0xfffffffffffffffe. Note that uint8 c = 0xfe will be represented the same way. 1856 // This is ok because during hints processing we will anyways try the value 0x00000000000000fe. 1857 switch (cmp.type & KCOV_CMP_SIZE_MASK) { 1858 case KCOV_CMP_SIZE1: 1859 arg1 = (uint64)(long long)(signed char)arg1; 1860 arg2 = (uint64)(long long)(signed char)arg2; 1861 break; 1862 case KCOV_CMP_SIZE2: 1863 arg1 = (uint64)(long long)(short)arg1; 1864 arg2 = (uint64)(long long)(short)arg2; 1865 break; 1866 case KCOV_CMP_SIZE4: 1867 arg1 = (uint64)(long long)(int)arg1; 1868 arg2 = (uint64)(long long)(int)arg2; 1869 break; 1870 } 1871 1872 // Prog package expects operands in the opposite order (first operand may come from the input, 1873 // the second operand was computed in the kernel), so swap operands. 1874 return {cmp.pc, arg2, arg1, !!(cmp.type & KCOV_CMP_CONST)}; 1875 } 1876 1877 void failmsg(const char* err, const char* msg, ...) 1878 { 1879 int e = errno; 1880 fprintf(stderr, "SYZFAIL: %s\n", err); 1881 if (msg) { 1882 va_list args; 1883 va_start(args, msg); 1884 vfprintf(stderr, msg, args); 1885 va_end(args); 1886 } 1887 fprintf(stderr, " (errno %d: %s)\n", e, strerror(e)); 1888 1889 // fail()'s are often used during the validation of kernel reactions to queries 1890 // that were issued by pseudo syscalls implementations. As fault injection may 1891 // cause the kernel not to succeed in handling these queries (e.g. socket writes 1892 // or reads may fail), this could ultimately lead to unwanted "lost connection to 1893 // test machine" crashes. 1894 // In order to avoid this and, on the other hand, to still have the ability to 1895 // signal a disastrous situation, the exit code of this function depends on the 1896 // current context. 1897 // All fail() invocations during system call execution with enabled fault injection 1898 // lead to termination with zero exit code. In all other cases, the exit code is 1899 // kFailStatus. 1900 if (current_thread && current_thread->soft_fail_state) 1901 doexit(0); 1902 doexit(kFailStatus); 1903 } 1904 1905 void fail(const char* err) 1906 { 1907 failmsg(err, 0); 1908 } 1909 1910 void exitf(const char* msg, ...) 1911 { 1912 int e = errno; 1913 va_list args; 1914 va_start(args, msg); 1915 vfprintf(stderr, msg, args); 1916 va_end(args); 1917 fprintf(stderr, " (errno %d)\n", e); 1918 doexit(1); 1919 } 1920 1921 void debug(const char* msg, ...) 1922 { 1923 if (!flag_debug) 1924 return; 1925 int err = errno; 1926 va_list args; 1927 va_start(args, msg); 1928 vfprintf(stderr, msg, args); 1929 va_end(args); 1930 fflush(stderr); 1931 errno = err; 1932 } 1933 1934 void debug_dump_data(const char* data, int length) 1935 { 1936 if (!flag_debug) 1937 return; 1938 int i = 0; 1939 for (; i < length; i++) { 1940 debug("%02x ", data[i] & 0xff); 1941 if (i % 16 == 15) 1942 debug("\n"); 1943 } 1944 if (i % 16 != 0) 1945 debug("\n"); 1946 }