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 #include <fcntl.h> 5 #include <stdlib.h> 6 #include <sys/ioctl.h> 7 #include <sys/mman.h> 8 #include <sys/resource.h> 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 #include <unistd.h> 12 13 #if !defined(__FreeBSD__) && !defined(__NetBSD__) 14 // This is just so that "make executor TARGETOS=freebsd/netbsd" works on linux. 15 #define __syscall syscall 16 #endif 17 18 static void os_init(int argc, char** argv, void* data, size_t data_size) 19 { 20 if (mmap(data, data_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != data) 21 fail("mmap of data segment failed"); 22 23 // Some minimal sandboxing. 24 // TODO: this should go into common_bsd.h because csource needs this too. 25 struct rlimit rlim; 26 #if GOOS_netbsd 27 // This causes frequent random aborts on netbsd. Reason unknown. 28 rlim.rlim_cur = rlim.rlim_max = 128 << 20; 29 setrlimit(RLIMIT_AS, &rlim); 30 #endif 31 rlim.rlim_cur = rlim.rlim_max = 8 << 20; 32 setrlimit(RLIMIT_MEMLOCK, &rlim); 33 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 34 setrlimit(RLIMIT_FSIZE, &rlim); 35 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 36 setrlimit(RLIMIT_STACK, &rlim); 37 rlim.rlim_cur = rlim.rlim_max = 0; 38 setrlimit(RLIMIT_CORE, &rlim); 39 rlim.rlim_cur = rlim.rlim_max = 256; // see kMaxFd 40 setrlimit(RLIMIT_NOFILE, &rlim); 41 } 42 43 static long execute_syscall(const call_t* c, long a[kMaxArgs]) 44 { 45 if (c->call) 46 return c->call(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); 47 return __syscall(c->sys_nr, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); 48 } 49 50 #if GOOS_freebsd 51 #define KIOENABLE _IOW('c', 2, int) // Enable coverage recording 52 #define KIODISABLE _IO('c', 3) // Disable coverage recording 53 #define KIOSETBUFSIZE _IOW('c', 4, unsigned int) // Set the buffer size 54 55 #define KCOV_MODE_NONE -1 56 #define KCOV_MODE_TRACE_PC 0 57 #define KCOV_MODE_TRACE_CMP 1 58 59 static void cover_open(cover_t* cov) 60 { 61 int fd = open("/dev/kcov", O_RDWR); 62 if (fd == -1) 63 fail("open of /dev/kcov failed"); 64 if (dup2(fd, cov->fd) < 0) 65 fail("filed to dup2(%d, %d) cover fd", fd, cov->fd); 66 close(fd); 67 if (ioctl(cov->fd, KIOSETBUFSIZE, &kCoverSize)) 68 fail("ioctl init trace write failed"); 69 size_t mmap_alloc_size = kCoverSize * (is_kernel_64_bit ? 8 : 4); 70 char* mmap_ptr = (char*)mmap(NULL, mmap_alloc_size, 71 PROT_READ | PROT_WRITE, 72 MAP_SHARED, cov->fd, 0); 73 if (mmap_ptr == NULL) 74 fail("cover mmap failed"); 75 cov->data = mmap_ptr; 76 cov->data_end = mmap_ptr + mmap_alloc_size; 77 } 78 79 static void cover_enable(cover_t* cov, bool collect_comps) 80 { 81 int kcov_mode = flag_collect_comps ? KCOV_MODE_TRACE_CMP : KCOV_MODE_TRACE_PC; 82 if (ioctl(cov->fd, KIOENABLE, &kcov_mode)) 83 exitf("cover enable write trace failed, mode=%d", kcov_mode); 84 } 85 86 static void cover_reset(cover_t* cov) 87 { 88 *(uint64*)cov->data = 0; 89 } 90 91 static void cover_collect(cover_t* cov) 92 { 93 cov->size = *(uint64*)cov->data; 94 } 95 96 static bool cover_check(uint32 pc) 97 { 98 return true; 99 } 100 101 static bool cover_check(uint64 pc) 102 { 103 return true; 104 } 105 #else 106 #include "nocover.h" 107 #endif 108