From 031174c3103a625f16e192ffa82572c92e05bbf4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 25 Oct 2017 09:45:05 +0200 Subject: executor: fix netbsd syscalls executor_netbsd.cc was including syscalls_freebsd.h, which completely messed up syscall numbers and names. Include the right syscalls header. --- executor/common_bsd.h | 164 ++++++++++++++++++++++++++++++++++++++++++++++ executor/common_freebsd.h | 164 ---------------------------------------------- executor/executor_bsd.cc | 10 ++- 3 files changed, 173 insertions(+), 165 deletions(-) create mode 100644 executor/common_bsd.h delete mode 100644 executor/common_freebsd.h diff --git a/executor/common_bsd.h b/executor/common_bsd.h new file mode 100644 index 000000000..a9c4933db --- /dev/null +++ b/executor/common_bsd.h @@ -0,0 +1,164 @@ +// Copyright 2017 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// This file is shared between executor and csource package. + +#include +#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +#include +#include +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) +#include +#endif + +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || \ + defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ + defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) +__attribute__((noreturn)) static void doexit(int status) +{ + _exit(status); + for (;;) { + } +} +#endif + +#include "common.h" + +#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) +static __thread int skip_segv; +static __thread jmp_buf segv_env; + +static void segv_handler(int sig, siginfo_t* info, void* uctx) +{ + // Generated programs can contain bad (unmapped/protected) addresses, + // which cause SIGSEGVs during copyin/copyout. + // This handler ignores such crashes to allow the program to proceed. + // We additionally opportunistically check that the faulty address + // is not within executable data region, because such accesses can corrupt + // output region and then fuzzer will fail on corrupted data. + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1 << 20; + const uintptr_t prog_end = 100 << 20; + if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { + debug("SIGSEGV on %p, skipping\n", addr); + _longjmp(segv_env, 1); + } + debug("SIGSEGV on %p, exiting\n", addr); + doexit(sig); + for (;;) { + } +} + +static void install_segv_handler() +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = segv_handler; + sa.sa_flags = SA_NODEFER | SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); +} + +#define NONFAILING(...) \ + { \ + __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + if (_setjmp(segv_env) == 0) { \ + __VA_ARGS__; \ + } \ + __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + } +#endif + +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +static uint64_t current_time_ms() +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + fail("clock_gettime failed"); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} +#endif + +#if defined(SYZ_EXECUTOR) +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} +#endif + +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) +static void remove_dir(const char* dir) +{ + DIR* dp; + struct dirent* ep; + int iter = 0; +retry: + dp = opendir(dir); + if (dp == NULL) + return; + while ((ep = readdir(dp))) { + if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) + continue; + char filename[FILENAME_MAX]; + snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); + struct stat st; + if (lstat(filename, &st)) + return; + if (S_ISDIR(st.st_mode)) { + remove_dir(filename); + continue; + } + int i; + for (i = 0;; i++) { + if (unlink(filename) == 0) + break; + if (errno == EROFS) + break; + if (errno != EBUSY || i > 100) + return; + } + } + closedir(dp); + int i; + for (i = 0;; i++) { + if (rmdir(dir) == 0) + break; + if (i < 100) { + if (errno == EROFS) + break; + if (errno == ENOTEMPTY) { + if (iter < 100) { + iter++; + goto retry; + } + } + } + return; + } +} +#endif + +#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) +static int inject_fault(int nth) +{ + return 0; +} + +static int fault_injected(int fail_fd) +{ + return 0; +} +#endif diff --git a/executor/common_freebsd.h b/executor/common_freebsd.h deleted file mode 100644 index a9c4933db..000000000 --- a/executor/common_freebsd.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2017 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -// This file is shared between executor and csource package. - -#include -#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) -#include -#include -#endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) -#include -#include -#include -#include -#include -#include -#include -#endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) -#include -#endif - -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ - defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || \ - defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ - defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) -__attribute__((noreturn)) static void doexit(int status) -{ - _exit(status); - for (;;) { - } -} -#endif - -#include "common.h" - -#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) -static __thread int skip_segv; -static __thread jmp_buf segv_env; - -static void segv_handler(int sig, siginfo_t* info, void* uctx) -{ - // Generated programs can contain bad (unmapped/protected) addresses, - // which cause SIGSEGVs during copyin/copyout. - // This handler ignores such crashes to allow the program to proceed. - // We additionally opportunistically check that the faulty address - // is not within executable data region, because such accesses can corrupt - // output region and then fuzzer will fail on corrupted data. - uintptr_t addr = (uintptr_t)info->si_addr; - const uintptr_t prog_start = 1 << 20; - const uintptr_t prog_end = 100 << 20; - if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { - debug("SIGSEGV on %p, skipping\n", addr); - _longjmp(segv_env, 1); - } - debug("SIGSEGV on %p, exiting\n", addr); - doexit(sig); - for (;;) { - } -} - -static void install_segv_handler() -{ - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = segv_handler; - sa.sa_flags = SA_NODEFER | SA_SIGINFO; - sigaction(SIGSEGV, &sa, NULL); - sigaction(SIGBUS, &sa, NULL); -} - -#define NONFAILING(...) \ - { \ - __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ - if (_setjmp(segv_env) == 0) { \ - __VA_ARGS__; \ - } \ - __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ - } -#endif - -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) -static uint64_t current_time_ms() -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - fail("clock_gettime failed"); - return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; -} -#endif - -#if defined(SYZ_EXECUTOR) -static void sleep_ms(uint64_t ms) -{ - usleep(ms * 1000); -} -#endif - -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) -static void remove_dir(const char* dir) -{ - DIR* dp; - struct dirent* ep; - int iter = 0; -retry: - dp = opendir(dir); - if (dp == NULL) - return; - while ((ep = readdir(dp))) { - if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) - continue; - char filename[FILENAME_MAX]; - snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); - struct stat st; - if (lstat(filename, &st)) - return; - if (S_ISDIR(st.st_mode)) { - remove_dir(filename); - continue; - } - int i; - for (i = 0;; i++) { - if (unlink(filename) == 0) - break; - if (errno == EROFS) - break; - if (errno != EBUSY || i > 100) - return; - } - } - closedir(dp); - int i; - for (i = 0;; i++) { - if (rmdir(dir) == 0) - break; - if (i < 100) { - if (errno == EROFS) - break; - if (errno == ENOTEMPTY) { - if (iter < 100) { - iter++; - goto retry; - } - } - } - return; - } -} -#endif - -#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) -static int inject_fault(int nth) -{ - return 0; -} - -static int fault_injected(int fail_fd) -{ - return 0; -} -#endif diff --git a/executor/executor_bsd.cc b/executor/executor_bsd.cc index 07bdb0b26..d920c82f5 100644 --- a/executor/executor_bsd.cc +++ b/executor/executor_bsd.cc @@ -4,13 +4,21 @@ // +build #define SYZ_EXECUTOR -#include "common_freebsd.h" +#include "common_bsd.h" #include "executor_posix.h" #include "executor.h" +// This file is used by both freebsd and netbsd (as a link to executor_bsd.cc). +#if defined(__FreeBSD__) #include "syscalls_freebsd.h" +#elif defined(__NetBSD__) +#include "syscalls_netbsd.h" +#else +// This is just so that "make executor TARGETOS=freebsd" works on linux. +#include "syscalls_freebsd.h" +#endif #include #include -- cgit mrf-deployment