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
os_init(int argc,char ** argv,void * data,size_t data_size)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
execute_syscall(const call_t * c,long a[kMaxArgs])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
cover_open(cover_t * cov)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
cover_enable(cover_t * cov,bool collect_comps)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
cover_reset(cover_t * cov)86 static void cover_reset(cover_t* cov)
87 {
88 *(uint64*)cov->data = 0;
89 }
90
cover_collect(cover_t * cov)91 static void cover_collect(cover_t* cov)
92 {
93 cov->size = *(uint64*)cov->data;
94 }
95
cover_check(uint32 pc)96 static bool cover_check(uint32 pc)
97 {
98 return true;
99 }
100
cover_check(uint64 pc)101 static bool cover_check(uint64 pc)
102 {
103 return true;
104 }
105 #else
106 #include "nocover.h"
107 #endif
108