diff options
Diffstat (limited to 'executor/executor_bsd.h')
| -rw-r--r-- | executor/executor_bsd.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/executor/executor_bsd.h b/executor/executor_bsd.h new file mode 100644 index 000000000..0bed21679 --- /dev/null +++ b/executor/executor_bsd.h @@ -0,0 +1,104 @@ +// 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. + +#include <fcntl.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) +// This is just so that "make executor TARGETOS=freebsd/netbsd" works on linux. +#define __syscall syscall +#endif + +static void os_init(int argc, char** argv, void* data, size_t data_size) +{ + if (mmap(data, data_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != data) + fail("mmap of data segment failed"); + + // Some minimal sandboxing. + // TODO: this should go into common_bsd.h because csource needs this too. + struct rlimit rlim; +#if GOOS_netbsd + // This causes frequent random aborts on netbsd. Reason unknown. + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); +#endif + 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); + rlim.rlim_cur = rlim.rlim_max = 256; // see kMaxFd + setrlimit(RLIMIT_NOFILE, &rlim); +} + +static long execute_syscall(const call_t* c, long a[kMaxArgs]) +{ + if (c->call) + return c->call(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); + return __syscall(c->sys_nr, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); +} + +#if GOOS_freebsd +#define KIOENABLE _IOW('c', 2, int) // Enable coverage recording +#define KIODISABLE _IO('c', 3) // Disable coverage recording +#define KIOSETBUFSIZE _IOW('c', 4, unsigned int) // Set the buffer size + +#define KCOV_MODE_NONE -1 +#define KCOV_MODE_TRACE_PC 0 +#define KCOV_MODE_TRACE_CMP 1 + +static void cover_open(cover_t* cov) +{ + cov->fd = open("/dev/kcov", O_RDWR); + if (cov->fd == -1) + fail("open of /dev/kcov failed"); + if (ioctl(cov->fd, KIOSETBUFSIZE, &kCoverSize)) + fail("ioctl init trace write failed"); + size_t mmap_alloc_size = kCoverSize * (is_kernel_64_bit ? 8 : 4); + char* mmap_ptr = (char*)mmap(NULL, mmap_alloc_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, cov->fd, 0); + if (mmap_ptr == NULL) + fail("cover mmap failed"); + cov->data = mmap_ptr; + cov->data_end = mmap_ptr + mmap_alloc_size; +} + +static void cover_enable(cover_t* cov, bool collect_comps) +{ + int kcov_mode = flag_collect_comps ? KCOV_MODE_TRACE_CMP : KCOV_MODE_TRACE_PC; + if (ioctl(cov->fd, KIOENABLE, &kcov_mode)) + exitf("cover enable write trace failed, mode=%d", kcov_mode); +} + +static void cover_reset(cover_t* cov) +{ + *(uint64*)cov->data = 0; +} + +static void cover_collect(cover_t* cov) +{ + cov->size = *(uint64*)cov->data; +} + +static bool cover_check(uint32 pc) +{ + return true; +} + +static bool cover_check(uint64 pc) +{ + return true; +} +#else +#include "nocover.h" +#endif |
