Home | History | Annotate | Download | only in executor
      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