aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-10-02 14:47:21 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-10-12 10:16:15 +0200
commit4dc2659337ed0252583d99acb87ba38fa0083ce4 (patch)
tree2b8a2738b9a90b78d81d578097f5de3bd184a453 /executor
parent128c09f19df897ccc8e4aacebbc7d4ae5db16ae8 (diff)
executor: simple freebsd executor
Diffstat (limited to 'executor')
-rw-r--r--executor/common_freebsd.h100
-rw-r--r--executor/executor_freebsd.cc100
2 files changed, 200 insertions, 0 deletions
diff --git a/executor/common_freebsd.h b/executor/common_freebsd.h
new file mode 100644
index 000000000..87daa17ff
--- /dev/null
+++ b/executor/common_freebsd.h
@@ -0,0 +1,100 @@
+// 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 <unistd.h>
+#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE)
+#include <pthread.h>
+#include <stdlib.h>
+#endif
+#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT))
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <time.h>
+#endif
+
+#define doexit exit
+#define NORETURN __attribute__((noreturn))
+
+#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_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_freebsd.cc b/executor/executor_freebsd.cc
new file mode 100644
index 000000000..8435d4465
--- /dev/null
+++ b/executor/executor_freebsd.cc
@@ -0,0 +1,100 @@
+// 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.
+
+// +build
+
+#define SYZ_EXECUTOR
+#include "common_freebsd.h"
+
+#include "executor_posix.h"
+
+#include "executor.h"
+
+#include "syscalls_freebsd.h"
+
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+char input_data[kMaxInput];
+uint32_t output;
+
+int main(int argc, char** argv)
+{
+ if (argc == 2 && strcmp(argv[1], "version") == 0) {
+ puts("linux " GOARCH " " SYZ_REVISION " " GIT_REVISION);
+ return 0;
+ }
+
+ // Some minimal sandboxing.
+ struct rlimit rlim;
+ rlim.rlim_cur = rlim.rlim_max = 128 << 20;
+ setrlimit(RLIMIT_AS, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 8 << 20;
+ setrlimit(RLIMIT_MEMLOCK, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 1 << 20;
+ setrlimit(RLIMIT_FSIZE, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 1 << 20;
+ setrlimit(RLIMIT_STACK, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+
+ install_segv_handler();
+ int pos = 0;
+ for (;;) {
+ int rv = read(0, input_data + pos, sizeof(input_data) - pos);
+ if (rv < 0)
+ fail("read failed");
+ if (rv == 0)
+ break;
+ pos += rv;
+ }
+ if (pos < 24)
+ fail("truncated input");
+
+ uint64_t flags = *(uint64_t*)input_data;
+ flag_debug = flags & (1 << 0);
+ flag_threaded = flags & (1 << 2);
+ flag_collide = flags & (1 << 3);
+ if (!flag_threaded)
+ flag_collide = false;
+ uint64_t executor_pid = *((uint64_t*)input_data + 2);
+ debug("input %d, threaded=%d collide=%d pid=%llu\n",
+ pos, flag_threaded, flag_collide, executor_pid);
+
+ execute_one(((uint64_t*)input_data) + 3);
+ return 0;
+}
+
+long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8)
+{
+ if (c->call)
+ return c->call(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+ return syscall(c->sys_nr, a0, a1, a2, a3, a4, a5);
+}
+
+void cover_open()
+{
+}
+
+void cover_enable(thread_t* th)
+{
+}
+
+void cover_reset(thread_t* th)
+{
+}
+
+uint64_t read_cover_size(thread_t* th)
+{
+ return 0;
+}
+
+uint32_t* write_output(uint32_t v)
+{
+ return &output;
+}
+
+void write_completed(uint32_t completed)
+{
+}