aboutsummaryrefslogtreecommitdiffstats
path: root/csource
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-17 12:46:42 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-17 14:41:15 +0200
commitbaad3b4b027658f49ba318c41dfc745788ba87d1 (patch)
treec48887b0267454a139d8225e3512f47848d7c9f9 /csource
parentec95d17c3271cc8c108d386c269737781b58ae08 (diff)
pkg/csource: move from csource
Diffstat (limited to 'csource')
-rw-r--r--csource/common.go1975
-rw-r--r--csource/csource.go533
-rw-r--r--csource/csource_test.go138
3 files changed, 0 insertions, 2646 deletions
diff --git a/csource/common.go b/csource/common.go
deleted file mode 100644
index 5e241092a..000000000
--- a/csource/common.go
+++ /dev/null
@@ -1,1975 +0,0 @@
-// AUTOGENERATED FROM executor/common.h
-package csource
-
-var commonHeader = `
-
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <stdint.h>
-#include <string.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE)
-#include <pthread.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_COLLIDE)
-#include <stdlib.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
-#include <setjmp.h>
-#include <signal.h>
-#include <string.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.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/prctl.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <time.h>
-#endif
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR))
-#include <dirent.h>
-#include <sys/mount.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE)
-#include <errno.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID)
-#include <grp.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE)
-#include <fcntl.h>
-#include <linux/capability.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/if.h>
-#include <linux/if_ether.h>
-#include <linux/if_tun.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <net/if_arp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION)
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG)
-#include <stdarg.h>
-#include <stdio.h>
-#endif
-#ifdef __NR_syz_open_dev
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#endif
-#if defined(__NR_syz_fuse_mount) || defined(__NR_syz_fuseblk_mount)
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#endif
-#ifdef __NR_syz_open_pts
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#endif
-#ifdef __NR_syz_kvm_setup_cpu
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/kvm.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \
- defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \
- defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu)
-const int kFailStatus = 67;
-const int kRetryStatus = 69;
-#endif
-
-#if defined(SYZ_EXECUTOR)
-const int kErrorStatus = 68;
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \
- defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \
- defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || \
- defined(__NR_syz_kvm_setup_cpu)
-__attribute__((noreturn)) static void doexit(int status)
-{
- volatile unsigned i;
- syscall(__NR_exit_group, status);
- for (i = 0;; i++) {
- }
-}
-#endif
-
-#if defined(SYZ_EXECUTOR)
-#define exit use_doexit_instead
-#define _exit use_doexit_instead
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \
- defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \
- defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu)
-__attribute__((noreturn)) static void fail(const char* msg, ...)
-{
- int e = errno;
- fflush(stdout);
- va_list args;
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, " (errno %d)\n", e);
- doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR)
-__attribute__((noreturn)) static void error(const char* msg, ...)
-{
- fflush(stdout);
- va_list args;
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, "\n");
- doexit(kErrorStatus);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT))
-__attribute__((noreturn)) static void exitf(const char* msg, ...)
-{
- int e = errno;
- fflush(stdout);
- va_list args;
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, " (errno %d)\n", e);
- doexit(kRetryStatus);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG)
-static int flag_debug;
-
-static void debug(const char* msg, ...)
-{
- if (!flag_debug)
- return;
- va_list args;
- va_start(args, msg);
- vfprintf(stdout, msg, args);
- va_end(args);
- fflush(stdout);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_BITMASKS)
-#define BITMASK_LEN(type, bf_len) (type)((1ull << (bf_len)) - 1)
-
-#define BITMASK_LEN_OFF(type, bf_off, bf_len) (type)(BITMASK_LEN(type, (bf_len)) << (bf_off))
-
-#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \
- if ((bf_off) == 0 && (bf_len) == 0) { \
- *(type*)(addr) = (type)(val); \
- } else { \
- type new_val = *(type*)(addr); \
- new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \
- new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \
- *(type*)(addr) = new_val; \
- }
-#endif
-
-#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)
-{
- 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_handler = SIG_IGN;
- syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
- syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
-
- 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_USE_TMP_DIR)
-static void use_temporary_dir()
-{
- char tmpdir_template[] = "./syzkaller.XXXXXX";
- char* tmpdir = mkdtemp(tmpdir_template);
- if (!tmpdir)
- fail("failed to mkdtemp");
- if (chmod(tmpdir, 0777))
- fail("failed to chmod");
- if (chdir(tmpdir))
- fail("failed to chdir");
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
-static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
-{
- int rv;
-
- rv = vsnprintf(str, size, format, args);
- if (rv < 0)
- fail("tun: snprintf failed");
- if ((size_t)rv >= size)
- fail("tun: string '%s...' doesn't fit into buffer", str);
-}
-
-static void snprintf_check(char* str, size_t size, const char* format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vsnprintf_check(str, size, format, args);
- va_end(args);
-}
-
-#define COMMAND_MAX_LEN 128
-
-static void execute_command(const char* format, ...)
-{
- va_list args;
- char command[COMMAND_MAX_LEN];
- int rv;
-
- va_start(args, format);
-
- vsnprintf_check(command, sizeof(command), format, args);
- rv = system(command);
- if (rv != 0)
- fail("tun: command \"%s\" failed with code %d", &command[0], rv);
-
- va_end(args);
-}
-
-static int tunfd = -1;
-
-#define SYZ_TUN_MAX_PACKET_SIZE 1000
-
-#define MAX_PIDS 32
-#define ADDR_MAX_LEN 32
-
-#define LOCAL_MAC "aa:aa:aa:aa:aa:%02hx"
-#define REMOTE_MAC "bb:bb:bb:bb:bb:%02hx"
-
-#define LOCAL_IPV4 "172.20.%d.170"
-#define REMOTE_IPV4 "172.20.%d.187"
-
-#define LOCAL_IPV6 "fe80::%02hxaa"
-#define REMOTE_IPV6 "fe80::%02hxbb"
-
-static void initialize_tun(uint64_t pid)
-{
- if (pid >= MAX_PIDS)
- fail("tun: no more than %d executors", MAX_PIDS);
- int id = pid;
-
- tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
- if (tunfd == -1)
- fail("tun: can't open /dev/net/tun");
-
- char iface[IFNAMSIZ];
- snprintf_check(iface, sizeof(iface), "syz%d", id);
-
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, iface, IFNAMSIZ);
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0)
- fail("tun: ioctl(TUNSETIFF) failed");
-
- char local_mac[ADDR_MAX_LEN];
- snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC, id);
- char remote_mac[ADDR_MAX_LEN];
- snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC, id);
-
- char local_ipv4[ADDR_MAX_LEN];
- snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, id);
- char remote_ipv4[ADDR_MAX_LEN];
- snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, id);
-
- char local_ipv6[ADDR_MAX_LEN];
- snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, id);
- char remote_ipv6[ADDR_MAX_LEN];
- snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, id);
-
- execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
-
- execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
-
- execute_command("ip link set dev %s address %s", iface, local_mac);
- execute_command("ip addr add %s/24 dev %s", local_ipv4, iface);
- execute_command("ip -6 addr add %s/120 dev %s", local_ipv6, iface);
- execute_command("ip neigh add %s lladdr %s dev %s nud permanent", remote_ipv4, remote_mac, iface);
- execute_command("ip -6 neigh add %s lladdr %s dev %s nud permanent", remote_ipv6, remote_mac, iface);
- execute_command("ip link set dev %s up", iface);
-}
-
-static void setup_tun(uint64_t pid, bool enable_tun)
-{
- if (enable_tun)
- initialize_tun(pid);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_TUN_ENABLE) && (defined(__NR_syz_extract_tcp_res) || defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)))
-static int read_tun(char* data, int size)
-{
- int rv = read(tunfd, data, size);
- if (rv < 0) {
- if (errno == EAGAIN)
- return -1;
- fail("tun: read failed with %d, errno: %d", rv, errno);
- }
- return rv;
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_DEBUG) && defined(SYZ_TUN_ENABLE) && (defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res)))
-static void debug_dump_data(const char* data, int length)
-{
- int i;
- for (i = 0; i < length; i++) {
- debug("%02hx ", (uint8_t)data[i] & (uint8_t)0xff);
- if (i % 16 == 15)
- debug("\n");
- }
- if (i % 16 != 0)
- debug("\n");
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_CHECKSUMS)
-struct csum_inet {
- uint32_t acc;
-};
-
-static void csum_inet_init(struct csum_inet* csum)
-{
- csum->acc = 0;
-}
-
-static void csum_inet_update(struct csum_inet* csum, const uint8_t* data, size_t length)
-{
- if (length == 0)
- return;
-
- size_t i;
- for (i = 0; i < length - 1; i += 2)
- csum->acc += *(uint16_t*)&data[i];
-
- if (length & 1)
- csum->acc += (uint16_t)data[length - 1];
-
- while (csum->acc > 0xffff)
- csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16);
-}
-
-static uint16_t csum_inet_digest(struct csum_inet* csum)
-{
- return ~csum->acc;
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE))
-static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
-{
-
- if (tunfd < 0)
- return (uintptr_t)-1;
-
- int64_t length = a0;
- char* data = (char*)a1;
- debug_dump_data(data, length);
- return write(tunfd, data, length);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_TUN_ENABLE))
-static void flush_tun()
-{
- char data[SYZ_TUN_MAX_PACKET_SIZE];
- while (read_tun(&data[0], sizeof(data)) != -1)
- ;
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE))
-struct ipv6hdr {
- __u8 priority : 4,
- version : 4;
- __u8 flow_lbl[3];
-
- __be16 payload_len;
- __u8 nexthdr;
- __u8 hop_limit;
-
- struct in6_addr saddr;
- struct in6_addr daddr;
-};
-
-struct tcp_resources {
- int32_t seq;
- int32_t ack;
-};
-
-static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2)
-{
-
- if (tunfd < 0)
- return (uintptr_t)-1;
-
- char data[SYZ_TUN_MAX_PACKET_SIZE];
- int rv = read_tun(&data[0], sizeof(data));
- if (rv == -1)
- return (uintptr_t)-1;
- size_t length = rv;
- debug_dump_data(data, length);
-
- struct tcphdr* tcphdr;
-
- if (length < sizeof(struct ethhdr))
- return (uintptr_t)-1;
- struct ethhdr* ethhdr = (struct ethhdr*)&data[0];
-
- if (ethhdr->h_proto == htons(ETH_P_IP)) {
- if (length < sizeof(struct ethhdr) + sizeof(struct iphdr))
- return (uintptr_t)-1;
- struct iphdr* iphdr = (struct iphdr*)&data[sizeof(struct ethhdr)];
- if (iphdr->protocol != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ethhdr) + iphdr->ihl * 4 + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + iphdr->ihl * 4];
- } else {
- if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr))
- return (uintptr_t)-1;
- struct ipv6hdr* ipv6hdr = (struct ipv6hdr*)&data[sizeof(struct ethhdr)];
- if (ipv6hdr->nexthdr != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + sizeof(struct ipv6hdr)];
- }
-
- struct tcp_resources* res = (struct tcp_resources*)a0;
- NONFAILING(res->seq = htonl((ntohl(tcphdr->seq) + (uint32_t)a1)));
- NONFAILING(res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2)));
-
- debug("extracted seq: %08x\n", res->seq);
- debug("extracted ack: %08x\n", res->ack);
-
- return 0;
-}
-#endif
-
-#ifdef __NR_syz_open_dev
-static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
-{
- if (a0 == 0xc || a0 == 0xb) {
- char buf[128];
- sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2);
- return open(buf, O_RDWR, 0);
- } else {
- char buf[1024];
- char* hash;
- NONFAILING(strncpy(buf, (char*)a0, sizeof(buf)));
- buf[sizeof(buf) - 1] = 0;
- while ((hash = strchr(buf, '#'))) {
- *hash = '0' + (char)(a1 % 10);
- a1 /= 10;
- }
- return open(buf, a2, 0);
- }
-}
-#endif
-
-#ifdef __NR_syz_open_pts
-static uintptr_t syz_open_pts(uintptr_t a0, uintptr_t a1)
-{
- int ptyno = 0;
- if (ioctl(a0, TIOCGPTN, &ptyno))
- return -1;
- char buf[128];
- sprintf(buf, "/dev/pts/%d", ptyno);
- return open(buf, a1, 0);
-}
-#endif
-
-#ifdef __NR_syz_fuse_mount
-static uintptr_t syz_fuse_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
-{
- uint64_t target = a0;
- uint64_t mode = a1;
- uint64_t uid = a2;
- uint64_t gid = a3;
- uint64_t maxread = a4;
- uint64_t flags = a5;
-
- int fd = open("/dev/fuse", O_RDWR);
- if (fd == -1)
- return fd;
- char buf[1024];
- sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
- if (maxread != 0)
- sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
- if (mode & 1)
- strcat(buf, ",default_permissions");
- if (mode & 2)
- strcat(buf, ",allow_other");
- syscall(SYS_mount, "", target, "fuse", flags, buf);
- return fd;
-}
-#endif
-
-#ifdef __NR_syz_fuseblk_mount
-static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
-{
- uint64_t target = a0;
- uint64_t blkdev = a1;
- uint64_t mode = a2;
- uint64_t uid = a3;
- uint64_t gid = a4;
- uint64_t maxread = a5;
- uint64_t blksize = a6;
- uint64_t flags = a7;
-
- int fd = open("/dev/fuse", O_RDWR);
- if (fd == -1)
- return fd;
- if (syscall(SYS_mknodat, AT_FDCWD, blkdev, S_IFBLK, makedev(7, 199)))
- return fd;
- char buf[256];
- sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
- if (maxread != 0)
- sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
- if (blksize != 0)
- sprintf(buf + strlen(buf), ",blksize=%ld", (long)blksize);
- if (mode & 1)
- strcat(buf, ",default_permissions");
- if (mode & 2)
- strcat(buf, ",allow_other");
- syscall(SYS_mount, blkdev, target, "fuseblk", flags, buf);
- return fd;
-}
-#endif
-
-#ifdef __NR_syz_kvm_setup_cpu
-#if defined(__x86_64__)
-
-
-
-const char kvm_asm16_cpl3[] = "\x0f\x20\xc0\x66\x83\xc8\x01\x0f\x22\xc0\xb8\xa0\x00\x0f\x00\xd8\xb8\x2b\x00\x8e\xd8\x8e\xc0\x8e\xe0\x8e\xe8\xbc\x00\x01\xc7\x06\x00\x01\x1d\xba\xc7\x06\x02\x01\x23\x00\xc7\x06\x04\x01\x00\x01\xc7\x06\x06\x01\x2b\x00\xcb";
-const char kvm_asm32_paged[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0";
-const char kvm_asm32_vm86[] = "\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00";
-const char kvm_asm32_paged_vm86[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00";
-const char kvm_asm64_vm86[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00";
-const char kvm_asm64_enable_long[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8";
-const char kvm_asm64_init_vm[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8\x48\xc7\xc1\x3a\x00\x00\x00\x0f\x32\x48\x83\xc8\x05\x0f\x30\x0f\x20\xe0\x48\x0d\x00\x20\x00\x00\x0f\x22\xe0\x48\xc7\xc1\x80\x04\x00\x00\x0f\x32\x48\xc7\xc2\x00\x60\x00\x00\x89\x02\x48\xc7\xc2\x00\x70\x00\x00\x89\x02\x48\xc7\xc0\x00\x5f\x00\x00\xf3\x0f\xc7\x30\x48\xc7\xc0\x08\x5f\x00\x00\x66\x0f\xc7\x30\x0f\xc7\x30\x48\xc7\xc1\x81\x04\x00\x00\x0f\x32\x48\x83\xc8\x3f\x48\x21\xd0\x48\xc7\xc2\x00\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x40\x00\x00\x48\xb8\x84\x9e\x99\xf3\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x40\x00\x00\x48\xc7\xc0\x81\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x83\x04\x00\x00\x0f\x32\x48\x0d\xff\x6f\x03\x00\x48\x21\xd0\x48\xc7\xc2\x0c\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x84\x04\x00\x00\x0f\x32\x48\x0d\xff\x17\x00\x00\x48\x21\xd0\x48\xc7\xc2\x12\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x2c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x28\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x02\x0c\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc0\x58\x00\x00\x00\x48\xc7\xc2\x00\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc0\xd8\x00\x00\x00\x48\xc7\xc2\x0c\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x2c\x00\x00\x48\xc7\xc0\x00\x05\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x4c\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x0f\x20\xc0\x48\xc7\xc2\x00\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xd8\x48\xc7\xc2\x02\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xe0\x48\xc7\xc2\x04\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x48\xc7\xc2\x06\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x6c\x00\x00\x48\xc7\xc0\x00\x3a\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x6c\x00\x00\x48\xc7\xc0\x00\x10\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x6c\x00\x00\x48\xc7\xc0\x00\x38\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x6c\x00\x00\x48\x8b\x04\x25\x10\x5f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x77\x02\x00\x00\x0f\x32\x48\xc1\xe2\x20\x48\x09\xd0\x48\xc7\xc2\x00\x2c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x48\xc7\xc2\x04\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x60\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x02\x60\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x1c\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x22\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x08\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x08\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x08\x00\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x68\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x68\x00\x00\x48\xc7\xc0\x00\x3a\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x68\x00\x00\x48\xc7\xc0\x00\x10\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x18\x68\x00\x00\x48\xc7\xc0\x00\x38\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x48\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x48\x00\x00\x48\xc7\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x48\x00\x00\x48\xc7\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x48\x00\x00\x48\xc7\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x48\x00\x00\x48\xc7\xc0\x9b\x20\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x18\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1a\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1c\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x48\x00\x00\x48\xc7\xc0\x82\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x22\x48\x00\x00\x48\xc7\xc0\x8b\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1c\x68\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x68\x00\x00\x48\xc7\xc0\x00\x91\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x68\x00\x00\x48\xc7\xc0\x02\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x28\x00\x00\x48\xc7\xc0\x00\x05\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x0f\x20\xc0\x48\xc7\xc2\x00\x68\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xd8\x48\xc7\xc2\x02\x68\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xe0\x48\xc7\xc2\x04\x68\x00\x00\x48\x89\xc0\x0f\x79\xd0\x48\xc7\xc0\x18\x5f\x00\x00\x48\x8b\x10\x48\xc7\xc0\x20\x5f\x00\x00\x48\x8b\x08\x48\x31\xc0\x0f\x78\xd0\x48\x31\xc8\x0f\x79\xd0\x0f\x01\xc2\x48\xc7\xc2\x00\x44\x00\x00\x0f\x78\xd0\xf4";
-const char kvm_asm64_vm_exit[] = "\x48\xc7\xc3\x00\x44\x00\x00\x0f\x78\xda\x48\xc7\xc3\x02\x44\x00\x00\x0f\x78\xd9\x48\xc7\xc0\x00\x64\x00\x00\x0f\x78\xc0\x48\xc7\xc3\x1e\x68\x00\x00\x0f\x78\xdb\xf4";
-const char kvm_asm64_cpl3[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8\x48\xc7\xc0\x6b\x00\x00\x00\x8e\xd8\x8e\xc0\x8e\xe0\x8e\xe8\x48\xc7\xc4\x80\x0f\x00\x00\x48\xc7\x04\x24\x1d\xba\x00\x00\x48\xc7\x44\x24\x04\x63\x00\x00\x00\x48\xc7\x44\x24\x08\x80\x0f\x00\x00\x48\xc7\x44\x24\x0c\x6b\x00\x00\x00\xcb";
-
-#define ADDR_TEXT 0x0000
-#define ADDR_GDT 0x1000
-#define ADDR_LDT 0x1800
-#define ADDR_PML4 0x2000
-#define ADDR_PDP 0x3000
-#define ADDR_PD 0x4000
-#define ADDR_STACK0 0x0f80
-#define ADDR_VAR_HLT 0x2800
-#define ADDR_VAR_SYSRET 0x2808
-#define ADDR_VAR_SYSEXIT 0x2810
-#define ADDR_VAR_IDT 0x3800
-#define ADDR_VAR_TSS64 0x3a00
-#define ADDR_VAR_TSS64_CPL3 0x3c00
-#define ADDR_VAR_TSS16 0x3d00
-#define ADDR_VAR_TSS16_2 0x3e00
-#define ADDR_VAR_TSS16_CPL3 0x3f00
-#define ADDR_VAR_TSS32 0x4800
-#define ADDR_VAR_TSS32_2 0x4a00
-#define ADDR_VAR_TSS32_CPL3 0x4c00
-#define ADDR_VAR_TSS32_VM86 0x4e00
-#define ADDR_VAR_VMXON_PTR 0x5f00
-#define ADDR_VAR_VMCS_PTR 0x5f08
-#define ADDR_VAR_VMEXIT_PTR 0x5f10
-#define ADDR_VAR_VMWRITE_FLD 0x5f18
-#define ADDR_VAR_VMWRITE_VAL 0x5f20
-#define ADDR_VAR_VMXON 0x6000
-#define ADDR_VAR_VMCS 0x7000
-#define ADDR_VAR_VMEXIT_CODE 0x9000
-#define ADDR_VAR_USER_CODE 0x9100
-#define ADDR_VAR_USER_CODE2 0x9120
-
-#define SEL_LDT (1 << 3)
-#define SEL_CS16 (2 << 3)
-#define SEL_DS16 (3 << 3)
-#define SEL_CS16_CPL3 ((4 << 3) + 3)
-#define SEL_DS16_CPL3 ((5 << 3) + 3)
-#define SEL_CS32 (6 << 3)
-#define SEL_DS32 (7 << 3)
-#define SEL_CS32_CPL3 ((8 << 3) + 3)
-#define SEL_DS32_CPL3 ((9 << 3) + 3)
-#define SEL_CS64 (10 << 3)
-#define SEL_DS64 (11 << 3)
-#define SEL_CS64_CPL3 ((12 << 3) + 3)
-#define SEL_DS64_CPL3 ((13 << 3) + 3)
-#define SEL_CGATE16 (14 << 3)
-#define SEL_TGATE16 (15 << 3)
-#define SEL_CGATE32 (16 << 3)
-#define SEL_TGATE32 (17 << 3)
-#define SEL_CGATE64 (18 << 3)
-#define SEL_CGATE64_HI (19 << 3)
-#define SEL_TSS16 (20 << 3)
-#define SEL_TSS16_2 (21 << 3)
-#define SEL_TSS16_CPL3 ((22 << 3) + 3)
-#define SEL_TSS32 (23 << 3)
-#define SEL_TSS32_2 (24 << 3)
-#define SEL_TSS32_CPL3 ((25 << 3) + 3)
-#define SEL_TSS32_VM86 (26 << 3)
-#define SEL_TSS64 (27 << 3)
-#define SEL_TSS64_HI (28 << 3)
-#define SEL_TSS64_CPL3 ((29 << 3) + 3)
-#define SEL_TSS64_CPL3_HI (30 << 3)
-
-#define MSR_IA32_FEATURE_CONTROL 0x3a
-#define MSR_IA32_VMX_BASIC 0x480
-#define MSR_IA32_SMBASE 0x9e
-#define MSR_IA32_SYSENTER_CS 0x174
-#define MSR_IA32_SYSENTER_ESP 0x175
-#define MSR_IA32_SYSENTER_EIP 0x176
-#define MSR_IA32_STAR 0xC0000081
-#define MSR_IA32_LSTAR 0xC0000082
-#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B
-
-#define NEXT_INSN $0xbadc0de
-#define PREFIX_SIZE 0xba1d
-
-#ifndef KVM_SMI
-#define KVM_SMI _IO(KVMIO, 0xb7)
-#endif
-
-#define CR0_PE 1
-#define CR0_MP (1 << 1)
-#define CR0_EM (1 << 2)
-#define CR0_TS (1 << 3)
-#define CR0_ET (1 << 4)
-#define CR0_NE (1 << 5)
-#define CR0_WP (1 << 16)
-#define CR0_AM (1 << 18)
-#define CR0_NW (1 << 29)
-#define CR0_CD (1 << 30)
-#define CR0_PG (1 << 31)
-
-#define CR4_VME 1
-#define CR4_PVI (1 << 1)
-#define CR4_TSD (1 << 2)
-#define CR4_DE (1 << 3)
-#define CR4_PSE (1 << 4)
-#define CR4_PAE (1 << 5)
-#define CR4_MCE (1 << 6)
-#define CR4_PGE (1 << 7)
-#define CR4_PCE (1 << 8)
-#define CR4_OSFXSR (1 << 8)
-#define CR4_OSXMMEXCPT (1 << 10)
-#define CR4_UMIP (1 << 11)
-#define CR4_VMXE (1 << 13)
-#define CR4_SMXE (1 << 14)
-#define CR4_FSGSBASE (1 << 16)
-#define CR4_PCIDE (1 << 17)
-#define CR4_OSXSAVE (1 << 18)
-#define CR4_SMEP (1 << 20)
-#define CR4_SMAP (1 << 21)
-#define CR4_PKE (1 << 22)
-
-#define EFER_SCE 1
-#define EFER_LME (1 << 8)
-#define EFER_LMA (1 << 10)
-#define EFER_NXE (1 << 11)
-#define EFER_SVME (1 << 12)
-#define EFER_LMSLE (1 << 13)
-#define EFER_FFXSR (1 << 14)
-#define EFER_TCE (1 << 15)
-
-#define PDE32_PRESENT 1
-#define PDE32_RW (1 << 1)
-#define PDE32_USER (1 << 2)
-#define PDE32_PS (1 << 7)
-
-#define PDE64_PRESENT 1
-#define PDE64_RW (1 << 1)
-#define PDE64_USER (1 << 2)
-#define PDE64_ACCESSED (1 << 5)
-#define PDE64_DIRTY (1 << 6)
-#define PDE64_PS (1 << 7)
-#define PDE64_G (1 << 8)
-
-struct tss16 {
- uint16_t prev;
- uint16_t sp0;
- uint16_t ss0;
- uint16_t sp1;
- uint16_t ss1;
- uint16_t sp2;
- uint16_t ss2;
- uint16_t ip;
- uint16_t flags;
- uint16_t ax;
- uint16_t cx;
- uint16_t dx;
- uint16_t bx;
- uint16_t sp;
- uint16_t bp;
- uint16_t si;
- uint16_t di;
- uint16_t es;
- uint16_t cs;
- uint16_t ss;
- uint16_t ds;
- uint16_t ldt;
-} __attribute__((packed));
-
-struct tss32 {
- uint16_t prev, prevh;
- uint32_t sp0;
- uint16_t ss0, ss0h;
- uint32_t sp1;
- uint16_t ss1, ss1h;
- uint32_t sp2;
- uint16_t ss2, ss2h;
- uint32_t cr3;
- uint32_t ip;
- uint32_t flags;
- uint32_t ax;
- uint32_t cx;
- uint32_t dx;
- uint32_t bx;
- uint32_t sp;
- uint32_t bp;
- uint32_t si;
- uint32_t di;
- uint16_t es, esh;
- uint16_t cs, csh;
- uint16_t ss, ssh;
- uint16_t ds, dsh;
- uint16_t fs, fsh;
- uint16_t gs, gsh;
- uint16_t ldt, ldth;
- uint16_t trace;
- uint16_t io_bitmap;
-} __attribute__((packed));
-
-struct tss64 {
- uint32_t reserved0;
- uint64_t rsp[3];
- uint64_t reserved1;
- uint64_t ist[7];
- uint64_t reserved2;
- uint32_t reserved3;
- uint32_t io_bitmap;
-} __attribute__((packed));
-
-static void fill_segment_descriptor(uint64_t* dt, uint64_t* lt, struct kvm_segment* seg)
-{
- uint16_t index = seg->selector >> 3;
- uint64_t limit = seg->g ? seg->limit >> 12 : seg->limit;
- uint64_t sd = (limit & 0xffff) | (seg->base & 0xffffff) << 16 | (uint64_t)seg->type << 40 | (uint64_t)seg->s << 44 | (uint64_t)seg->dpl << 45 | (uint64_t)seg->present << 47 | (limit & 0xf0000ULL) << 48 | (uint64_t)seg->avl << 52 | (uint64_t)seg->l << 53 | (uint64_t)seg->db << 54 | (uint64_t)seg->g << 55 | (seg->base & 0xff000000ULL) << 56;
- NONFAILING(dt[index] = sd);
- NONFAILING(lt[index] = sd);
-}
-
-static void fill_segment_descriptor_dword(uint64_t* dt, uint64_t* lt, struct kvm_segment* seg)
-{
- fill_segment_descriptor(dt, lt, seg);
- uint16_t index = seg->selector >> 3;
- NONFAILING(dt[index + 1] = 0);
- NONFAILING(lt[index + 1] = 0);
-}
-
-static void setup_syscall_msrs(int cpufd, uint16_t sel_cs, uint16_t sel_cs_cpl3)
-{
- char buf[sizeof(struct kvm_msrs) + 5 * sizeof(struct kvm_msr_entry)];
- memset(buf, 0, sizeof(buf));
- struct kvm_msrs* msrs = (struct kvm_msrs*)buf;
- msrs->nmsrs = 5;
- msrs->entries[0].index = MSR_IA32_SYSENTER_CS;
- msrs->entries[0].data = sel_cs;
- msrs->entries[1].index = MSR_IA32_SYSENTER_ESP;
- msrs->entries[1].data = ADDR_STACK0;
- msrs->entries[2].index = MSR_IA32_SYSENTER_EIP;
- msrs->entries[2].data = ADDR_VAR_SYSEXIT;
- msrs->entries[3].index = MSR_IA32_STAR;
- msrs->entries[3].data = ((uint64_t)sel_cs << 32) | ((uint64_t)sel_cs_cpl3 << 48);
- msrs->entries[4].index = MSR_IA32_LSTAR;
- msrs->entries[4].data = ADDR_VAR_SYSRET;
- ioctl(cpufd, KVM_SET_MSRS, msrs);
-}
-
-static void setup_32bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t guest_mem)
-{
- sregs->idt.base = guest_mem + ADDR_VAR_IDT;
- sregs->idt.limit = 0x1ff;
- uint64_t* idt = (uint64_t*)(host_mem + sregs->idt.base);
- int i;
- for (i = 0; i < 32; i++) {
- struct kvm_segment gate;
- gate.selector = i << 3;
- switch (i % 6) {
- case 0:
- gate.type = 6;
- gate.base = SEL_CS16;
- break;
- case 1:
- gate.type = 7;
- gate.base = SEL_CS16;
- break;
- case 2:
- gate.type = 3;
- gate.base = SEL_TGATE16;
- break;
- case 3:
- gate.type = 14;
- gate.base = SEL_CS32;
- break;
- case 4:
- gate.type = 15;
- gate.base = SEL_CS32;
- break;
- case 6:
- gate.type = 11;
- gate.base = SEL_TGATE32;
- break;
- }
- gate.limit = guest_mem + ADDR_VAR_USER_CODE2;
- gate.present = 1;
- gate.dpl = 0;
- gate.s = 0;
- gate.g = 0;
- gate.db = 0;
- gate.l = 0;
- gate.avl = 0;
- fill_segment_descriptor(idt, idt, &gate);
- }
-}
-
-static void setup_64bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t guest_mem)
-{
- sregs->idt.base = guest_mem + ADDR_VAR_IDT;
- sregs->idt.limit = 0x1ff;
- uint64_t* idt = (uint64_t*)(host_mem + sregs->idt.base);
- int i;
- for (i = 0; i < 32; i++) {
- struct kvm_segment gate;
- gate.selector = (i * 2) << 3;
- gate.type = (i & 1) ? 14 : 15;
- gate.base = SEL_CS64;
- gate.limit = guest_mem + ADDR_VAR_USER_CODE2;
- gate.present = 1;
- gate.dpl = 0;
- gate.s = 0;
- gate.g = 0;
- gate.db = 0;
- gate.l = 0;
- gate.avl = 0;
- fill_segment_descriptor_dword(idt, idt, &gate);
- }
-}
-
-struct kvm_text {
- uintptr_t typ;
- const void* text;
- uintptr_t size;
-};
-
-struct kvm_opt {
- uint64_t typ;
- uint64_t val;
-};
-
-#define KVM_SETUP_PAGING (1 << 0)
-#define KVM_SETUP_PAE (1 << 1)
-#define KVM_SETUP_PROTECTED (1 << 2)
-#define KVM_SETUP_CPL3 (1 << 3)
-#define KVM_SETUP_VIRT86 (1 << 4)
-#define KVM_SETUP_SMM (1 << 5)
-#define KVM_SETUP_VM (1 << 6)
-
-static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
-{
- const int vmfd = a0;
- const int cpufd = a1;
- char* const host_mem = (char*)a2;
- const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3;
- const uintptr_t text_count = a4;
- const uintptr_t flags = a5;
- const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6;
- uintptr_t opt_count = a7;
-
- const uintptr_t page_size = 4 << 10;
- const uintptr_t ioapic_page = 10;
- const uintptr_t guest_mem_size = 24 * page_size;
- const uintptr_t guest_mem = 0;
-
- (void)text_count;
- int text_type = 0;
- const void* text = 0;
- uintptr_t text_size = 0;
- NONFAILING(text_type = text_array_ptr[0].typ);
- NONFAILING(text = text_array_ptr[0].text);
- NONFAILING(text_size = text_array_ptr[0].size);
-
- uintptr_t i;
- for (i = 0; i < guest_mem_size / page_size; i++) {
- struct kvm_userspace_memory_region memreg;
- memreg.slot = i;
- memreg.flags = 0;
- memreg.guest_phys_addr = guest_mem + i * page_size;
- if (i == ioapic_page)
- memreg.guest_phys_addr = 0xfec00000;
- memreg.memory_size = page_size;
- memreg.userspace_addr = (uintptr_t)host_mem + i * page_size;
- ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
- }
- struct kvm_userspace_memory_region memreg;
- memreg.slot = 1 + (1 << 16);
- memreg.flags = 0;
- memreg.guest_phys_addr = 0x30000;
- memreg.memory_size = 64 << 10;
- memreg.userspace_addr = (uintptr_t)host_mem;
- ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
-
- struct kvm_sregs sregs;
- if (ioctl(cpufd, KVM_GET_SREGS, &sregs))
- return -1;
-
- struct kvm_regs regs;
- memset(&regs, 0, sizeof(regs));
- regs.rip = guest_mem + ADDR_TEXT;
- regs.rsp = ADDR_STACK0;
-
- sregs.gdt.base = guest_mem + ADDR_GDT;
- sregs.gdt.limit = 256 * sizeof(uint64_t) - 1;
- uint64_t* gdt = (uint64_t*)(host_mem + sregs.gdt.base);
-
- struct kvm_segment seg_ldt;
- seg_ldt.selector = SEL_LDT;
- seg_ldt.type = 2;
- seg_ldt.base = guest_mem + ADDR_LDT;
- seg_ldt.limit = 256 * sizeof(uint64_t) - 1;
- seg_ldt.present = 1;
- seg_ldt.dpl = 0;
- seg_ldt.s = 0;
- seg_ldt.g = 0;
- seg_ldt.db = 1;
- seg_ldt.l = 0;
- sregs.ldt = seg_ldt;
- uint64_t* ldt = (uint64_t*)(host_mem + sregs.ldt.base);
-
- struct kvm_segment seg_cs16;
- seg_cs16.selector = SEL_CS16;
- seg_cs16.type = 11;
- seg_cs16.base = 0;
- seg_cs16.limit = 0xfffff;
- seg_cs16.present = 1;
- seg_cs16.dpl = 0;
- seg_cs16.s = 1;
- seg_cs16.g = 0;
- seg_cs16.db = 0;
- seg_cs16.l = 0;
-
- struct kvm_segment seg_ds16 = seg_cs16;
- seg_ds16.selector = SEL_DS16;
- seg_ds16.type = 3;
-
- struct kvm_segment seg_cs16_cpl3 = seg_cs16;
- seg_cs16_cpl3.selector = SEL_CS16_CPL3;
- seg_cs16_cpl3.dpl = 3;
-
- struct kvm_segment seg_ds16_cpl3 = seg_ds16;
- seg_ds16_cpl3.selector = SEL_DS16_CPL3;
- seg_ds16_cpl3.dpl = 3;
-
- struct kvm_segment seg_cs32 = seg_cs16;
- seg_cs32.selector = SEL_CS32;
- seg_cs32.db = 1;
-
- struct kvm_segment seg_ds32 = seg_ds16;
- seg_ds32.selector = SEL_DS32;
- seg_ds32.db = 1;
-
- struct kvm_segment seg_cs32_cpl3 = seg_cs32;
- seg_cs32_cpl3.selector = SEL_CS32_CPL3;
- seg_cs32_cpl3.dpl = 3;
-
- struct kvm_segment seg_ds32_cpl3 = seg_ds32;
- seg_ds32_cpl3.selector = SEL_DS32_CPL3;
- seg_ds32_cpl3.dpl = 3;
-
- struct kvm_segment seg_cs64 = seg_cs16;
- seg_cs64.selector = SEL_CS64;
- seg_cs64.l = 1;
-
- struct kvm_segment seg_ds64 = seg_ds32;
- seg_ds64.selector = SEL_DS64;
-
- struct kvm_segment seg_cs64_cpl3 = seg_cs64;
- seg_cs64_cpl3.selector = SEL_CS64_CPL3;
- seg_cs64_cpl3.dpl = 3;
-
- struct kvm_segment seg_ds64_cpl3 = seg_ds64;
- seg_ds64_cpl3.selector = SEL_DS64_CPL3;
- seg_ds64_cpl3.dpl = 3;
-
- struct kvm_segment seg_tss32;
- seg_tss32.selector = SEL_TSS32;
- seg_tss32.type = 9;
- seg_tss32.base = ADDR_VAR_TSS32;
- seg_tss32.limit = 0x1ff;
- seg_tss32.present = 1;
- seg_tss32.dpl = 0;
- seg_tss32.s = 0;
- seg_tss32.g = 0;
- seg_tss32.db = 0;
- seg_tss32.l = 0;
-
- struct kvm_segment seg_tss32_2 = seg_tss32;
- seg_tss32_2.selector = SEL_TSS32_2;
- seg_tss32_2.base = ADDR_VAR_TSS32_2;
-
- struct kvm_segment seg_tss32_cpl3 = seg_tss32;
- seg_tss32_cpl3.selector = SEL_TSS32_CPL3;
- seg_tss32_cpl3.base = ADDR_VAR_TSS32_CPL3;
-
- struct kvm_segment seg_tss32_vm86 = seg_tss32;
- seg_tss32_vm86.selector = SEL_TSS32_VM86;
- seg_tss32_vm86.base = ADDR_VAR_TSS32_VM86;
-
- struct kvm_segment seg_tss16 = seg_tss32;
- seg_tss16.selector = SEL_TSS16;
- seg_tss16.base = ADDR_VAR_TSS16;
- seg_tss16.limit = 0xff;
- seg_tss16.type = 1;
-
- struct kvm_segment seg_tss16_2 = seg_tss16;
- seg_tss16_2.selector = SEL_TSS16_2;
- seg_tss16_2.base = ADDR_VAR_TSS16_2;
- seg_tss16_2.dpl = 0;
-
- struct kvm_segment seg_tss16_cpl3 = seg_tss16;
- seg_tss16_cpl3.selector = SEL_TSS16_CPL3;
- seg_tss16_cpl3.base = ADDR_VAR_TSS16_CPL3;
- seg_tss16_cpl3.dpl = 3;
-
- struct kvm_segment seg_tss64 = seg_tss32;
- seg_tss64.selector = SEL_TSS64;
- seg_tss64.base = ADDR_VAR_TSS64;
- seg_tss64.limit = 0x1ff;
-
- struct kvm_segment seg_tss64_cpl3 = seg_tss64;
- seg_tss64_cpl3.selector = SEL_TSS64_CPL3;
- seg_tss64_cpl3.base = ADDR_VAR_TSS64_CPL3;
- seg_tss64_cpl3.dpl = 3;
-
- struct kvm_segment seg_cgate16;
- seg_cgate16.selector = SEL_CGATE16;
- seg_cgate16.type = 4;
- seg_cgate16.base = SEL_CS16 | (2 << 16);
- seg_cgate16.limit = ADDR_VAR_USER_CODE2;
- seg_cgate16.present = 1;
- seg_cgate16.dpl = 0;
- seg_cgate16.s = 0;
- seg_cgate16.g = 0;
- seg_cgate16.db = 0;
- seg_cgate16.l = 0;
- seg_cgate16.avl = 0;
-
- struct kvm_segment seg_tgate16 = seg_cgate16;
- seg_tgate16.selector = SEL_TGATE16;
- seg_tgate16.type = 3;
- seg_cgate16.base = SEL_TSS16_2;
- seg_tgate16.limit = 0;
-
- struct kvm_segment seg_cgate32 = seg_cgate16;
- seg_cgate32.selector = SEL_CGATE32;
- seg_cgate32.type = 12;
- seg_cgate32.base = SEL_CS32 | (2 << 16);
-
- struct kvm_segment seg_tgate32 = seg_cgate32;
- seg_tgate32.selector = SEL_TGATE32;
- seg_tgate32.type = 11;
- seg_tgate32.base = SEL_TSS32_2;
- seg_tgate32.limit = 0;
-
- struct kvm_segment seg_cgate64 = seg_cgate16;
- seg_cgate64.selector = SEL_CGATE64;
- seg_cgate64.type = 12;
- seg_cgate64.base = SEL_CS64;
-
- int kvmfd = open("/dev/kvm", O_RDWR);
- char buf[sizeof(struct kvm_cpuid2) + 128 * sizeof(struct kvm_cpuid_entry2)];
- memset(buf, 0, sizeof(buf));
- struct kvm_cpuid2* cpuid = (struct kvm_cpuid2*)buf;
- cpuid->nent = 128;
- ioctl(kvmfd, KVM_GET_SUPPORTED_CPUID, cpuid);
- ioctl(cpufd, KVM_SET_CPUID2, cpuid);
- close(kvmfd);
-
- const char* text_prefix = 0;
- int text_prefix_size = 0;
- char* host_text = host_mem + ADDR_TEXT;
-
- if (text_type == 8) {
- if (flags & KVM_SETUP_SMM) {
- if (flags & KVM_SETUP_PROTECTED) {
- sregs.cs = seg_cs16;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16;
- sregs.cr0 |= CR0_PE;
- } else {
- sregs.cs.selector = 0;
- sregs.cs.base = 0;
- }
-
- NONFAILING(*(host_mem + ADDR_TEXT) = 0xf4);
- host_text = host_mem + 0x8000;
-
- ioctl(cpufd, KVM_SMI, 0);
- } else if (flags & KVM_SETUP_VIRT86) {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
- sregs.cr0 |= CR0_PE;
- sregs.efer |= EFER_SCE;
-
- setup_syscall_msrs(cpufd, SEL_CS32, SEL_CS32_CPL3);
- setup_32bit_idt(&sregs, host_mem, guest_mem);
-
- if (flags & KVM_SETUP_PAGING) {
- uint64_t pd_addr = guest_mem + ADDR_PD;
- uint64_t* pd = (uint64_t*)(host_mem + ADDR_PD);
- NONFAILING(pd[0] = PDE32_PRESENT | PDE32_RW | PDE32_USER | PDE32_PS);
- sregs.cr3 = pd_addr;
- sregs.cr4 |= CR4_PSE;
-
- text_prefix = kvm_asm32_paged_vm86;
- text_prefix_size = sizeof(kvm_asm32_paged_vm86) - 1;
- } else {
- text_prefix = kvm_asm32_vm86;
- text_prefix_size = sizeof(kvm_asm32_vm86) - 1;
- }
- } else {
- sregs.cs.selector = 0;
- sregs.cs.base = 0;
- }
- } else if (text_type == 16) {
- if (flags & KVM_SETUP_CPL3) {
- sregs.cs = seg_cs16;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16;
-
- text_prefix = kvm_asm16_cpl3;
- text_prefix_size = sizeof(kvm_asm16_cpl3) - 1;
- } else {
- sregs.cr0 |= CR0_PE;
- sregs.cs = seg_cs16;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16;
- }
- } else if (text_type == 32) {
- sregs.cr0 |= CR0_PE;
- sregs.efer |= EFER_SCE;
-
- setup_syscall_msrs(cpufd, SEL_CS32, SEL_CS32_CPL3);
- setup_32bit_idt(&sregs, host_mem, guest_mem);
-
- if (flags & KVM_SETUP_SMM) {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
-
- NONFAILING(*(host_mem + ADDR_TEXT) = 0xf4);
- host_text = host_mem + 0x8000;
-
- ioctl(cpufd, KVM_SMI, 0);
- } else if (flags & KVM_SETUP_PAGING) {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
-
- uint64_t pd_addr = guest_mem + ADDR_PD;
- uint64_t* pd = (uint64_t*)(host_mem + ADDR_PD);
- NONFAILING(pd[0] = PDE32_PRESENT | PDE32_RW | PDE32_USER | PDE32_PS);
- sregs.cr3 = pd_addr;
- sregs.cr4 |= CR4_PSE;
-
- text_prefix = kvm_asm32_paged;
- text_prefix_size = sizeof(kvm_asm32_paged) - 1;
- } else if (flags & KVM_SETUP_CPL3) {
- sregs.cs = seg_cs32_cpl3;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32_cpl3;
- } else {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
- }
- } else {
- sregs.efer |= EFER_LME | EFER_SCE;
- sregs.cr0 |= CR0_PE;
-
- setup_syscall_msrs(cpufd, SEL_CS64, SEL_CS64_CPL3);
- setup_64bit_idt(&sregs, host_mem, guest_mem);
-
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
-
- uint64_t pml4_addr = guest_mem + ADDR_PML4;
- uint64_t* pml4 = (uint64_t*)(host_mem + ADDR_PML4);
- uint64_t pdpt_addr = guest_mem + ADDR_PDP;
- uint64_t* pdpt = (uint64_t*)(host_mem + ADDR_PDP);
- uint64_t pd_addr = guest_mem + ADDR_PD;
- uint64_t* pd = (uint64_t*)(host_mem + ADDR_PD);
- NONFAILING(pml4[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | pdpt_addr);
- NONFAILING(pdpt[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | pd_addr);
- NONFAILING(pd[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | PDE64_PS);
- sregs.cr3 = pml4_addr;
- sregs.cr4 |= CR4_PAE;
-
- if (flags & KVM_SETUP_VM) {
- sregs.cr0 |= CR0_NE;
-
- NONFAILING(*((uint64_t*)(host_mem + ADDR_VAR_VMXON_PTR)) = ADDR_VAR_VMXON);
- NONFAILING(*((uint64_t*)(host_mem + ADDR_VAR_VMCS_PTR)) = ADDR_VAR_VMCS);
- NONFAILING(memcpy(host_mem + ADDR_VAR_VMEXIT_CODE, kvm_asm64_vm_exit, sizeof(kvm_asm64_vm_exit) - 1));
- NONFAILING(*((uint64_t*)(host_mem + ADDR_VAR_VMEXIT_PTR)) = ADDR_VAR_VMEXIT_CODE);
-
- text_prefix = kvm_asm64_init_vm;
- text_prefix_size = sizeof(kvm_asm64_init_vm) - 1;
- } else if (flags & KVM_SETUP_CPL3) {
- text_prefix = kvm_asm64_cpl3;
- text_prefix_size = sizeof(kvm_asm64_cpl3) - 1;
- } else {
- text_prefix = kvm_asm64_enable_long;
- text_prefix_size = sizeof(kvm_asm64_enable_long) - 1;
- }
- }
-
- struct tss16 tss16;
- memset(&tss16, 0, sizeof(tss16));
- tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16;
- tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0;
- tss16.ip = ADDR_VAR_USER_CODE2;
- tss16.flags = (1 << 1);
- tss16.cs = SEL_CS16;
- tss16.es = tss16.ds = tss16.ss = SEL_DS16;
- tss16.ldt = SEL_LDT;
- struct tss16* tss16_addr = (struct tss16*)(host_mem + seg_tss16_2.base);
- NONFAILING(memcpy(tss16_addr, &tss16, sizeof(tss16)));
-
- memset(&tss16, 0, sizeof(tss16));
- tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16;
- tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0;
- tss16.ip = ADDR_VAR_USER_CODE2;
- tss16.flags = (1 << 1);
- tss16.cs = SEL_CS16_CPL3;
- tss16.es = tss16.ds = tss16.ss = SEL_DS16_CPL3;
- tss16.ldt = SEL_LDT;
- struct tss16* tss16_cpl3_addr = (struct tss16*)(host_mem + seg_tss16_cpl3.base);
- NONFAILING(memcpy(tss16_cpl3_addr, &tss16, sizeof(tss16)));
-
- struct tss32 tss32;
- memset(&tss32, 0, sizeof(tss32));
- tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32;
- tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0;
- tss32.ip = ADDR_VAR_USER_CODE;
- tss32.flags = (1 << 1) | (1 << 17);
- tss32.ldt = SEL_LDT;
- tss32.cr3 = sregs.cr3;
- tss32.io_bitmap = offsetof(struct tss32, io_bitmap);
- struct tss32* tss32_addr = (struct tss32*)(host_mem + seg_tss32_vm86.base);
- NONFAILING(memcpy(tss32_addr, &tss32, sizeof(tss32)));
-
- memset(&tss32, 0, sizeof(tss32));
- tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32;
- tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0;
- tss32.ip = ADDR_VAR_USER_CODE;
- tss32.flags = (1 << 1);
- tss32.cr3 = sregs.cr3;
- tss32.es = tss32.ds = tss32.ss = tss32.gs = tss32.fs = SEL_DS32;
- tss32.cs = SEL_CS32;
- tss32.ldt = SEL_LDT;
- tss32.cr3 = sregs.cr3;
- tss32.io_bitmap = offsetof(struct tss32, io_bitmap);
- struct tss32* tss32_cpl3_addr = (struct tss32*)(host_mem + seg_tss32_2.base);
- NONFAILING(memcpy(tss32_cpl3_addr, &tss32, sizeof(tss32)));
-
- struct tss64 tss64;
- memset(&tss64, 0, sizeof(tss64));
- tss64.rsp[0] = ADDR_STACK0;
- tss64.rsp[1] = ADDR_STACK0;
- tss64.rsp[2] = ADDR_STACK0;
- tss64.io_bitmap = offsetof(struct tss64, io_bitmap);
- struct tss64* tss64_addr = (struct tss64*)(host_mem + seg_tss64.base);
- NONFAILING(memcpy(tss64_addr, &tss64, sizeof(tss64)));
-
- memset(&tss64, 0, sizeof(tss64));
- tss64.rsp[0] = ADDR_STACK0;
- tss64.rsp[1] = ADDR_STACK0;
- tss64.rsp[2] = ADDR_STACK0;
- tss64.io_bitmap = offsetof(struct tss64, io_bitmap);
- struct tss64* tss64_cpl3_addr = (struct tss64*)(host_mem + seg_tss64_cpl3.base);
- NONFAILING(memcpy(tss64_cpl3_addr, &tss64, sizeof(tss64)));
-
- if (text_size > 1000)
- text_size = 1000;
- if (text_prefix) {
- NONFAILING(memcpy(host_text, text_prefix, text_prefix_size));
- void* patch = 0;
- NONFAILING(patch = memmem(host_text, text_prefix_size, "\xde\xc0\xad\x0b", 4));
- if (patch)
- NONFAILING(*((uint32_t*)patch) = guest_mem + ADDR_TEXT + ((char*)patch - host_text) + 6);
- uint16_t magic = PREFIX_SIZE;
- patch = 0;
- NONFAILING(patch = memmem(host_text, text_prefix_size, &magic, sizeof(magic)));
- if (patch)
- NONFAILING(*((uint16_t*)patch) = guest_mem + ADDR_TEXT + text_prefix_size);
- }
- NONFAILING(memcpy((void*)(host_text + text_prefix_size), text, text_size));
- NONFAILING(*(host_text + text_prefix_size + text_size) = 0xf4);
-
- NONFAILING(memcpy(host_mem + ADDR_VAR_USER_CODE, text, text_size));
- NONFAILING(*(host_mem + ADDR_VAR_USER_CODE + text_size) = 0xf4);
-
- NONFAILING(*(host_mem + ADDR_VAR_HLT) = 0xf4);
- NONFAILING(memcpy(host_mem + ADDR_VAR_SYSRET, "\x0f\x07\xf4", 3));
- NONFAILING(memcpy(host_mem + ADDR_VAR_SYSEXIT, "\x0f\x35\xf4", 3));
-
- NONFAILING(*(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_FLD) = 0);
- NONFAILING(*(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_VAL) = 0);
-
- if (opt_count > 2)
- opt_count = 2;
- for (i = 0; i < opt_count; i++) {
- uint64_t typ = 0;
- uint64_t val = 0;
- NONFAILING(typ = opt_array_ptr[i].typ);
- NONFAILING(val = opt_array_ptr[i].val);
- switch (typ % 9) {
- case 0:
- sregs.cr0 ^= val & (CR0_MP | CR0_EM | CR0_ET | CR0_NE | CR0_WP | CR0_AM | CR0_NW | CR0_CD);
- break;
- case 1:
- sregs.cr4 ^= val & (CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PGE | CR4_PCE |
- CR4_OSFXSR | CR4_OSXMMEXCPT | CR4_UMIP | CR4_VMXE | CR4_SMXE | CR4_FSGSBASE | CR4_PCIDE |
- CR4_OSXSAVE | CR4_SMEP | CR4_SMAP | CR4_PKE);
- break;
- case 2:
- sregs.efer ^= val & (EFER_SCE | EFER_NXE | EFER_SVME | EFER_LMSLE | EFER_FFXSR | EFER_TCE);
- break;
- case 3:
- val &= ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13) | (1 << 14) |
- (1 << 15) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21));
- regs.rflags ^= val;
- NONFAILING(tss16_addr->flags ^= val);
- NONFAILING(tss16_cpl3_addr->flags ^= val);
- NONFAILING(tss32_addr->flags ^= val);
- NONFAILING(tss32_cpl3_addr->flags ^= val);
- break;
- case 4:
- seg_cs16.type = val & 0xf;
- seg_cs32.type = val & 0xf;
- seg_cs64.type = val & 0xf;
- break;
- case 5:
- seg_cs16_cpl3.type = val & 0xf;
- seg_cs32_cpl3.type = val & 0xf;
- seg_cs64_cpl3.type = val & 0xf;
- break;
- case 6:
- seg_ds16.type = val & 0xf;
- seg_ds32.type = val & 0xf;
- seg_ds64.type = val & 0xf;
- break;
- case 7:
- seg_ds16_cpl3.type = val & 0xf;
- seg_ds32_cpl3.type = val & 0xf;
- seg_ds64_cpl3.type = val & 0xf;
- break;
- case 8:
- NONFAILING(*(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_FLD) = (val & 0xffff));
- NONFAILING(*(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_VAL) = (val >> 16));
- break;
- default:
- fail("bad kvm setup opt");
- }
- }
- regs.rflags |= 2;
-
- fill_segment_descriptor(gdt, ldt, &seg_ldt);
- fill_segment_descriptor(gdt, ldt, &seg_cs16);
- fill_segment_descriptor(gdt, ldt, &seg_ds16);
- fill_segment_descriptor(gdt, ldt, &seg_cs16_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_ds16_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_cs32);
- fill_segment_descriptor(gdt, ldt, &seg_ds32);
- fill_segment_descriptor(gdt, ldt, &seg_cs32_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_ds32_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_cs64);
- fill_segment_descriptor(gdt, ldt, &seg_ds64);
- fill_segment_descriptor(gdt, ldt, &seg_cs64_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_ds64_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_tss32);
- fill_segment_descriptor(gdt, ldt, &seg_tss32_2);
- fill_segment_descriptor(gdt, ldt, &seg_tss32_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_tss32_vm86);
- fill_segment_descriptor(gdt, ldt, &seg_tss16);
- fill_segment_descriptor(gdt, ldt, &seg_tss16_2);
- fill_segment_descriptor(gdt, ldt, &seg_tss16_cpl3);
- fill_segment_descriptor_dword(gdt, ldt, &seg_tss64);
- fill_segment_descriptor_dword(gdt, ldt, &seg_tss64_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_cgate16);
- fill_segment_descriptor(gdt, ldt, &seg_tgate16);
- fill_segment_descriptor(gdt, ldt, &seg_cgate32);
- fill_segment_descriptor(gdt, ldt, &seg_tgate32);
- fill_segment_descriptor_dword(gdt, ldt, &seg_cgate64);
-
- if (ioctl(cpufd, KVM_SET_SREGS, &sregs))
- return -1;
- if (ioctl(cpufd, KVM_SET_REGS, &regs))
- return -1;
- return 0;
-}
-#elif defined(__aarch64__)
-
-
-
-struct kvm_text {
- uintptr_t typ;
- const void* text;
- uintptr_t size;
-};
-
-struct kvm_opt {
- uint64_t typ;
- uint64_t val;
-};
-
-static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
-{
- const int vmfd = a0;
- const int cpufd = a1;
- char* const host_mem = (char*)a2;
- const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3;
- const uintptr_t text_count = a4;
- const uintptr_t flags = a5;
- const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6;
- uintptr_t opt_count = a7;
-
- (void)flags;
- (void)opt_count;
-
- const uintptr_t page_size = 4 << 10;
- const uintptr_t guest_mem = 0;
- const uintptr_t guest_mem_size = 24 * page_size;
-
- (void)text_count;
- int text_type = 0;
- const void* text = 0;
- int text_size = 0;
- NONFAILING(text_type = text_array_ptr[0].typ);
- NONFAILING(text = text_array_ptr[0].text);
- NONFAILING(text_size = text_array_ptr[0].size);
- (void)text_type;
- (void)opt_array_ptr;
-
- uint32_t features = 0;
- if (opt_count > 1)
- opt_count = 1;
- uintptr_t i;
- for (i = 0; i < opt_count; i++) {
- uint64_t typ = 0;
- uint64_t val = 0;
- NONFAILING(typ = opt_array_ptr[i].typ);
- NONFAILING(val = opt_array_ptr[i].val);
- switch (typ) {
- case 1:
- features = val;
- break;
- }
- }
-
- for (i = 0; i < guest_mem_size / page_size; i++) {
- struct kvm_userspace_memory_region memreg;
- memreg.slot = i;
- memreg.flags = 0;
- memreg.guest_phys_addr = guest_mem + i * page_size;
- memreg.memory_size = page_size;
- memreg.userspace_addr = (uintptr_t)host_mem + i * page_size;
- ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
- }
-
- struct kvm_vcpu_init init;
- ioctl(cpufd, KVM_ARM_PREFERRED_TARGET, &init);
- init.features[0] = features;
- ioctl(cpufd, KVM_ARM_VCPU_INIT, &init);
-
- if (text_size > 1000)
- text_size = 1000;
- NONFAILING(memcpy(host_mem, text, text_size));
-
- return 0;
-}
-#else
-static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
-{
- return 0;
-}
-#endif
-#endif
-
-#ifdef SYZ_EXECUTOR
-static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8)
-{
- switch (nr) {
- default:
- return syscall(nr, a0, a1, a2, a3, a4, a5);
-#ifdef __NR_syz_test
- case __NR_syz_test:
- return 0;
-#endif
-#ifdef __NR_syz_open_dev
- case __NR_syz_open_dev:
- return syz_open_dev(a0, a1, a2);
-#endif
-#ifdef __NR_syz_open_pts
- case __NR_syz_open_pts:
- return syz_open_pts(a0, a1);
-#endif
-#ifdef __NR_syz_fuse_mount
- case __NR_syz_fuse_mount:
- return syz_fuse_mount(a0, a1, a2, a3, a4, a5);
-#endif
-#ifdef __NR_syz_fuseblk_mount
- case __NR_syz_fuseblk_mount:
- return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7);
-#endif
-#ifdef __NR_syz_emit_ethernet
- case __NR_syz_emit_ethernet:
- return syz_emit_ethernet(a0, a1);
-#endif
-#ifdef __NR_syz_extract_tcp_res
- case __NR_syz_extract_tcp_res:
- return syz_extract_tcp_res(a0, a1, a2);
-#endif
-#ifdef __NR_syz_kvm_setup_cpu
- case __NR_syz_kvm_setup_cpu:
- return syz_kvm_setup_cpu(a0, a1, a2, a3, a4, a5, a6, a7);
-#endif
- }
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE)
-static void loop();
-
-static void sandbox_common()
-{
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setpgrp();
- setsid();
-
- struct rlimit rlim;
- rlim.rlim_cur = rlim.rlim_max = 128 << 20;
- setrlimit(RLIMIT_AS, &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);
-
- unshare(CLONE_NEWNS);
- unshare(CLONE_NEWIPC);
- unshare(CLONE_IO);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE)
-static int do_sandbox_none(int executor_pid, bool enable_tun)
-{
- int pid = fork();
- if (pid)
- return pid;
-
- sandbox_common();
-#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
- setup_tun(executor_pid, enable_tun);
-#endif
-
- loop();
- doexit(1);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID)
-static int do_sandbox_setuid(int executor_pid, bool enable_tun)
-{
- int pid = fork();
- if (pid)
- return pid;
-
- sandbox_common();
-#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
- setup_tun(executor_pid, enable_tun);
-#endif
-
- const int nobody = 65534;
- if (setgroups(0, NULL))
- fail("failed to setgroups");
- if (syscall(SYS_setresgid, nobody, nobody, nobody))
- fail("failed to setresgid");
- if (syscall(SYS_setresuid, nobody, nobody, nobody))
- fail("failed to setresuid");
-
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-
- loop();
- doexit(1);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_FAULT_INJECTION)
-static bool write_file(const char* file, const char* what, ...)
-{
- char buf[1024];
- va_list args;
- va_start(args, what);
- vsnprintf(buf, sizeof(buf), what, args);
- va_end(args);
- buf[sizeof(buf) - 1] = 0;
- int len = strlen(buf);
-
- int fd = open(file, O_WRONLY | O_CLOEXEC);
- if (fd == -1)
- return false;
- if (write(fd, buf, len) != len) {
- close(fd);
- return false;
- }
- close(fd);
- return true;
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE)
-static int real_uid;
-static int real_gid;
-static int epid;
-static bool etun;
-__attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20];
-
-static int namespace_sandbox_proc(void* arg)
-{
- sandbox_common();
-
- write_file("/proc/self/setgroups", "deny");
- if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid))
- fail("write of /proc/self/uid_map failed");
- if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid))
- fail("write of /proc/self/gid_map failed");
-
-#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
- setup_tun(epid, etun);
-#endif
-
- if (mkdir("./syz-tmp", 0777))
- fail("mkdir(syz-tmp) failed");
- if (mount("", "./syz-tmp", "tmpfs", 0, NULL))
- fail("mount(tmpfs) failed");
- if (mkdir("./syz-tmp/newroot", 0777))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/dev", 0700))
- fail("mkdir failed");
- if (mount("/dev", "./syz-tmp/newroot/dev", NULL, MS_BIND | MS_REC | MS_PRIVATE, NULL))
- fail("mount(dev) failed");
- if (mkdir("./syz-tmp/newroot/proc", 0700))
- fail("mkdir failed");
- if (mount(NULL, "./syz-tmp/newroot/proc", "proc", 0, NULL))
- fail("mount(proc) failed");
- if (mkdir("./syz-tmp/pivot", 0777))
- fail("mkdir failed");
- if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) {
- debug("pivot_root failed");
- if (chdir("./syz-tmp"))
- fail("chdir failed");
- } else {
- if (chdir("/"))
- fail("chdir failed");
- if (umount2("./pivot", MNT_DETACH))
- fail("umount failed");
- }
- if (chroot("./newroot"))
- fail("chroot failed");
- if (chdir("/"))
- fail("chdir failed");
-
- struct __user_cap_header_struct cap_hdr = {};
- struct __user_cap_data_struct cap_data[2] = {};
- cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
- cap_hdr.pid = getpid();
- if (syscall(SYS_capget, &cap_hdr, &cap_data))
- fail("capget failed");
- cap_data[0].effective &= ~(1 << CAP_SYS_PTRACE);
- cap_data[0].permitted &= ~(1 << CAP_SYS_PTRACE);
- cap_data[0].inheritable &= ~(1 << CAP_SYS_PTRACE);
- if (syscall(SYS_capset, &cap_hdr, &cap_data))
- fail("capset failed");
-
- loop();
- doexit(1);
-}
-
-static int do_sandbox_namespace(int executor_pid, bool enable_tun)
-{
- real_uid = getuid();
- real_gid = getgid();
- epid = executor_pid;
- etun = enable_tun;
- mprotect(sandbox_stack, 4096, PROT_NONE);
- return clone(namespace_sandbox_proc, &sandbox_stack[sizeof(sandbox_stack) - 64],
- CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET, NULL);
-}
-#endif
-
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR))
-static void remove_dir(const char* dir)
-{
- DIR* dp;
- struct dirent* ep;
- int iter = 0;
-retry:
- dp = opendir(dir);
- if (dp == NULL) {
- if (errno == EMFILE) {
- exitf("opendir(%s) failed due to NOFILE, exiting");
- }
- exitf("opendir(%s) failed", dir);
- }
- while ((ep = readdir(dp))) {
- if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
- continue;
- char filename[FILENAME_MAX];
- snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
- struct stat st;
- if (lstat(filename, &st))
- exitf("lstat(%s) failed", filename);
- if (S_ISDIR(st.st_mode)) {
- remove_dir(filename);
- continue;
- }
- int i;
- for (i = 0;; i++) {
- debug("unlink(%s)\n", filename);
- if (unlink(filename) == 0)
- break;
- if (errno == EROFS) {
- debug("ignoring EROFS\n");
- break;
- }
- if (errno != EBUSY || i > 100)
- exitf("unlink(%s) failed", filename);
- debug("umount(%s)\n", filename);
- if (umount2(filename, MNT_DETACH))
- exitf("umount(%s) failed", filename);
- }
- }
- closedir(dp);
- int i;
- for (i = 0;; i++) {
- debug("rmdir(%s)\n", dir);
- if (rmdir(dir) == 0)
- break;
- if (i < 100) {
- if (errno == EROFS) {
- debug("ignoring EROFS\n");
- break;
- }
- if (errno == EBUSY) {
- debug("umount(%s)\n", dir);
- if (umount2(dir, MNT_DETACH))
- exitf("umount(%s) failed", dir);
- continue;
- }
- if (errno == ENOTEMPTY) {
- if (iter < 100) {
- iter++;
- goto retry;
- }
- }
- }
- exitf("rmdir(%s) failed", dir);
- }
-}
-#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) || defined(SYZ_FAULT_INJECTION)
-static int inject_fault(int nth)
-{
- int fd;
- char buf[128];
-
- sprintf(buf, "/proc/self/task/%d/fail-nth", (int)syscall(SYS_gettid));
- fd = open(buf, O_RDWR);
- if (fd == -1)
- fail("failed to open /proc/self/task/tid/fail-nth");
- sprintf(buf, "%d", nth + 1);
- if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf))
- fail("failed to write /proc/self/task/tid/fail-nth");
- return fd;
-}
-#endif
-
-#if defined(SYZ_REPEAT)
-static void test();
-
-#if defined(SYZ_WAIT_REPEAT)
-void loop()
-{
- int iter;
- for (iter = 0;; iter++) {
-#ifdef SYZ_USE_TMP_DIR
- char cwdbuf[256];
- sprintf(cwdbuf, "./%d", iter);
- if (mkdir(cwdbuf, 0777))
- fail("failed to mkdir");
-#endif
- int pid = fork();
- if (pid < 0)
- fail("clone failed");
- if (pid == 0) {
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setpgrp();
-#ifdef SYZ_USE_TMP_DIR
- if (chdir(cwdbuf))
- fail("failed to chdir");
-#endif
-#ifdef SYZ_TUN_ENABLE
- flush_tun();
-#endif
- test();
- doexit(0);
- }
- int status = 0;
- uint64_t start = current_time_ms();
- for (;;) {
- int res = waitpid(-1, &status, __WALL | WNOHANG);
- if (res == pid)
- break;
- usleep(1000);
- if (current_time_ms() - start > 5 * 1000) {
- kill(-pid, SIGKILL);
- kill(pid, SIGKILL);
- while (waitpid(-1, &status, __WALL) != pid) {
- }
- break;
- }
- }
-#ifdef SYZ_USE_TMP_DIR
- remove_dir(cwdbuf);
-#endif
- }
-}
-#else
-void loop()
-{
- while (1) {
- test();
- }
-}
-#endif
-#endif
-`
diff --git a/csource/csource.go b/csource/csource.go
deleted file mode 100644
index db610ce2e..000000000
--- a/csource/csource.go
+++ /dev/null
@@ -1,533 +0,0 @@
-// Copyright 2015 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.
-
-// I heard you like shell...
-//go:generate bash -c "echo -e '// AUTOGENERATED FROM executor/common.h\npackage csource\nvar commonHeader = `' > common.go; cat ../executor/common.h | sed -e '/#include \"common_kvm_amd64.h\"/ {' -e 'r ../executor/common_kvm_amd64.h' -e 'd' -e '}' - | sed -e '/#include \"common_kvm_arm64.h\"/ {' -e 'r ../executor/common_kvm_arm64.h' -e 'd' -e '}' - | sed -e '/#include \"kvm.h\"/ {' -e 'r ../executor/kvm.h' -e 'd' -e '}' - | sed -e '/#include \"kvm.S.h\"/ {' -e 'r ../executor/kvm.S.h' -e 'd' -e '}' - | egrep -v '^[ ]*//' | sed '/^[ ]*\\/\\/.*/d' | sed 's#[ ]*//.*##g' >> common.go; echo '`' >> common.go"
-//go:generate go fmt common.go
-
-package csource
-
-import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "regexp"
- "strings"
- "unsafe"
-
- "github.com/google/syzkaller/prog"
- "github.com/google/syzkaller/sys"
-)
-
-type Options struct {
- Threaded bool
- Collide bool
- Repeat bool
- Procs int
- Sandbox string
-
- Fault bool // inject fault into FaultCall/FaultNth
- FaultCall int
- FaultNth int
-
- // These options allow for a more fine-tuned control over the generated C code.
- EnableTun bool
- UseTmpDir bool
- HandleSegv bool
- WaitRepeat bool
- Debug bool
-
- // Generate code for use with repro package to prints log messages,
- // which allows to distinguish between a hang and an absent crash.
- Repro bool
-}
-
-func Write(p *prog.Prog, opts Options) ([]byte, error) {
- exec := make([]byte, prog.ExecBufferSize)
- if err := p.SerializeForExec(exec, 0); err != nil {
- return nil, fmt.Errorf("failed to serialize program: %v", err)
- }
- w := new(bytes.Buffer)
-
- fmt.Fprint(w, "// autogenerated by syzkaller (http://github.com/google/syzkaller)\n\n")
-
- handled := make(map[string]int)
- for _, c := range p.Calls {
- handled[c.Meta.CallName] = c.Meta.NR
- }
- for name, nr := range handled {
- fmt.Fprintf(w, "#ifndef __NR_%v\n", name)
- fmt.Fprintf(w, "#define __NR_%v %v\n", name, nr)
- fmt.Fprintf(w, "#endif\n")
- }
- fmt.Fprintf(w, "\n")
-
- hdr, err := preprocessCommonHeader(opts, handled, prog.RequiresBitmasks(p), prog.RequiresChecksums(p))
- if err != nil {
- return nil, err
- }
- fmt.Fprint(w, hdr)
- fmt.Fprint(w, "\n")
-
- calls, nvar := generateCalls(exec, opts)
- fmt.Fprintf(w, "long r[%v];\n", nvar)
-
- if !opts.Repeat {
- generateTestFunc(w, opts, calls, "loop")
-
- fmt.Fprint(w, "int main()\n{\n")
- if opts.HandleSegv {
- fmt.Fprintf(w, "\tinstall_segv_handler();\n")
- }
- if opts.UseTmpDir {
- fmt.Fprintf(w, "\tuse_temporary_dir();\n")
- }
- if opts.Sandbox != "" {
- fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun)
- fmt.Fprint(w, "\tint status = 0;\n")
- fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n")
- } else {
- if opts.EnableTun {
- fmt.Fprintf(w, "\tsetup_tun(0, %v);\n", opts.EnableTun)
- }
- fmt.Fprint(w, "\tloop();\n")
- }
- fmt.Fprint(w, "\treturn 0;\n}\n")
- } else {
- generateTestFunc(w, opts, calls, "test")
- if opts.Procs <= 1 {
- fmt.Fprint(w, "int main()\n{\n")
- if opts.HandleSegv {
- fmt.Fprintf(w, "\tinstall_segv_handler();\n")
- }
- if opts.UseTmpDir {
- fmt.Fprintf(w, "\tuse_temporary_dir();\n")
- }
- if opts.Sandbox != "" {
- fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun)
- fmt.Fprint(w, "\tint status = 0;\n")
- fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n")
- } else {
- if opts.EnableTun {
- fmt.Fprintf(w, "\tsetup_tun(0, %v);\n", opts.EnableTun)
- }
- fmt.Fprint(w, "\tloop();\n")
- }
- fmt.Fprint(w, "\treturn 0;\n}\n")
- } else {
- fmt.Fprint(w, "int main()\n{\n")
- fmt.Fprint(w, "\tint i;")
- fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", opts.Procs)
- fmt.Fprint(w, "\t\tif (fork() == 0) {\n")
- if opts.HandleSegv {
- fmt.Fprintf(w, "\t\t\tinstall_segv_handler();\n")
- }
- if opts.UseTmpDir {
- fmt.Fprintf(w, "\t\t\tuse_temporary_dir();\n")
- }
- if opts.Sandbox != "" {
- fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun)
- fmt.Fprint(w, "\t\t\tint status = 0;\n")
- fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n")
- } else {
- if opts.EnableTun {
- fmt.Fprintf(w, "\t\t\tsetup_tun(i, %v);\n", opts.EnableTun)
- }
- fmt.Fprint(w, "\t\t\tloop();\n")
- }
- fmt.Fprint(w, "\t\t\treturn 0;\n")
- fmt.Fprint(w, "\t\t}\n")
- fmt.Fprint(w, "\t}\n")
- fmt.Fprint(w, "\tsleep(1000000);\n")
- fmt.Fprint(w, "\treturn 0;\n}\n")
- }
- }
-
- // Remove NONFAILING and debug calls.
- out0 := w.String()
- if !opts.HandleSegv {
- re := regexp.MustCompile(`\t*NONFAILING\((.*)\);\n`)
- out0 = re.ReplaceAllString(out0, "$1;\n")
- }
- if !opts.Debug {
- re := regexp.MustCompile(`\t*debug\(.*\);\n`)
- out0 = re.ReplaceAllString(out0, "")
- re = regexp.MustCompile(`\t*debug_dump_data\(.*\);\n`)
- out0 = re.ReplaceAllString(out0, "")
- }
-
- // Remove duplicate new lines.
- out1 := []byte(out0)
- for {
- out2 := bytes.Replace(out1, []byte{'\n', '\n', '\n'}, []byte{'\n', '\n'}, -1)
- if len(out1) == len(out2) {
- break
- }
- out1 = out2
- }
-
- return out1, nil
-}
-
-func generateTestFunc(w io.Writer, opts Options, calls []string, name string) {
- if !opts.Threaded && !opts.Collide {
- fmt.Fprintf(w, "void %v()\n{\n", name)
- if opts.Debug {
- // Use debug to avoid: error: ‘debug’ defined but not used.
- fmt.Fprintf(w, "\tdebug(\"%v\\n\");\n", name)
- }
- if opts.Repro {
- fmt.Fprintf(w, "\tsyscall(SYS_write, 1, \"executing program\\n\", strlen(\"executing program\\n\"));\n")
- }
- fmt.Fprintf(w, "\tmemset(r, -1, sizeof(r));\n")
- for _, c := range calls {
- fmt.Fprintf(w, "%s", c)
- }
- fmt.Fprintf(w, "}\n\n")
- } else {
- fmt.Fprintf(w, "void *thr(void *arg)\n{\n")
- fmt.Fprintf(w, "\tswitch ((long)arg) {\n")
- for i, c := range calls {
- fmt.Fprintf(w, "\tcase %v:\n", i)
- fmt.Fprintf(w, "%s", strings.Replace(c, "\t", "\t\t", -1))
- fmt.Fprintf(w, "\t\tbreak;\n")
- }
- fmt.Fprintf(w, "\t}\n")
- fmt.Fprintf(w, "\treturn 0;\n}\n\n")
-
- fmt.Fprintf(w, "void %v()\n{\n", name)
- fmt.Fprintf(w, "\tlong i;\n")
- fmt.Fprintf(w, "\tpthread_t th[%v];\n", 2*len(calls))
- fmt.Fprintf(w, "\n")
- if opts.Debug {
- // Use debug to avoid: error: ‘debug’ defined but not used.
- fmt.Fprintf(w, "\tdebug(\"%v\\n\");\n", name)
- }
- if opts.Repro {
- fmt.Fprintf(w, "\tsyscall(SYS_write, 1, \"executing program\\n\", strlen(\"executing program\\n\"));\n")
- }
- fmt.Fprintf(w, "\tmemset(r, -1, sizeof(r));\n")
- if opts.Collide {
- fmt.Fprintf(w, "\tsrand(getpid());\n")
- }
- fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", len(calls))
- fmt.Fprintf(w, "\t\tpthread_create(&th[i], 0, thr, (void*)i);\n")
- fmt.Fprintf(w, "\t\tusleep(10000);\n")
- fmt.Fprintf(w, "\t}\n")
- if opts.Collide {
- fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", len(calls))
- fmt.Fprintf(w, "\t\tpthread_create(&th[%v+i], 0, thr, (void*)i);\n", len(calls))
- fmt.Fprintf(w, "\t\tif (rand()%%2)\n")
- fmt.Fprintf(w, "\t\t\tusleep(rand()%%10000);\n")
- fmt.Fprintf(w, "\t}\n")
- }
- fmt.Fprintf(w, "\tusleep(100000);\n")
- fmt.Fprintf(w, "}\n\n")
- }
-}
-
-func generateCalls(exec []byte, opts Options) ([]string, int) {
- read := func() uintptr {
- if len(exec) < 8 {
- panic("exec program overflow")
- }
- v := *(*uint64)(unsafe.Pointer(&exec[0]))
- exec = exec[8:]
- return uintptr(v)
- }
- resultRef := func() string {
- arg := read()
- res := fmt.Sprintf("r[%v]", arg)
- if opDiv := read(); opDiv != 0 {
- res = fmt.Sprintf("%v/%v", res, opDiv)
- }
- if opAdd := read(); opAdd != 0 {
- res = fmt.Sprintf("%v+%v", res, opAdd)
- }
- return res
- }
- lastCall := 0
- seenCall := false
- var calls []string
- w := new(bytes.Buffer)
- newCall := func() {
- if seenCall {
- seenCall = false
- calls = append(calls, w.String())
- w = new(bytes.Buffer)
- }
- }
- n := 0
-loop:
- for ; ; n++ {
- switch instr := read(); instr {
- case prog.ExecInstrEOF:
- break loop
- case prog.ExecInstrCopyin:
- newCall()
- addr := read()
- typ := read()
- size := read()
- switch typ {
- case prog.ExecArgConst:
- arg := read()
- bfOff := read()
- bfLen := read()
- if bfOff == 0 && bfLen == 0 {
- fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = (uint%v_t)0x%x);\n", size*8, addr, size*8, arg)
- } else {
- fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v_t, 0x%x, 0x%x, %v, %v));\n", size*8, addr, arg, bfOff, bfLen)
- }
- case prog.ExecArgResult:
- fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = %v);\n", size*8, addr, resultRef())
- case prog.ExecArgData:
- data := exec[:size]
- exec = exec[(size+7)/8*8:]
- var esc []byte
- for _, v := range data {
- hex := func(v byte) byte {
- if v < 10 {
- return '0' + v
- }
- return 'a' + v - 10
- }
- esc = append(esc, '\\', 'x', hex(v>>4), hex(v<<4>>4))
- }
- fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n", addr, esc, size)
- case prog.ExecArgCsum:
- csum_kind := read()
- switch csum_kind {
- case prog.ExecArgCsumInet:
- fmt.Fprintf(w, "\tstruct csum_inet csum_%d;\n", n)
- fmt.Fprintf(w, "\tcsum_inet_init(&csum_%d);\n", n)
- csum_chunks_num := read()
- for i := uintptr(0); i < csum_chunks_num; i++ {
- chunk_kind := read()
- chunk_value := read()
- chunk_size := read()
- switch chunk_kind {
- case prog.ExecArgCsumChunkData:
- fmt.Fprintf(w, "\tNONFAILING(csum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d));\n", n, chunk_value, chunk_size)
- case prog.ExecArgCsumChunkConst:
- fmt.Fprintf(w, "\tuint%d_t csum_%d_chunk_%d = 0x%x;\n", chunk_size*8, n, i, chunk_value)
- fmt.Fprintf(w, "\tcsum_inet_update(&csum_%d, (const uint8_t*)&csum_%d_chunk_%d, %d);\n", n, n, i, chunk_size)
- default:
- panic(fmt.Sprintf("unknown checksum chunk kind %v", chunk_kind))
- }
- }
- fmt.Fprintf(w, "\tNONFAILING(*(uint16_t*)0x%x = csum_inet_digest(&csum_%d));\n", addr, n)
- default:
- panic(fmt.Sprintf("unknown csum kind %v", csum_kind))
- }
- default:
- panic(fmt.Sprintf("bad argument type %v", instr))
- }
- case prog.ExecInstrCopyout:
- addr := read()
- size := read()
- fmt.Fprintf(w, "\tif (r[%v] != -1)\n", lastCall)
- fmt.Fprintf(w, "\t\tNONFAILING(r[%v] = *(uint%v_t*)0x%x);\n", n, size*8, addr)
- default:
- // Normal syscall.
- newCall()
- if opts.Fault && opts.FaultCall == len(calls) {
- fmt.Fprintf(w, "\twrite_file(\"/sys/kernel/debug/failslab/ignore-gfp-wait\", \"N\");\n")
- fmt.Fprintf(w, "\twrite_file(\"/sys/kernel/debug/fail_futex/ignore-private\", \"N\");\n")
- fmt.Fprintf(w, "\tinject_fault(%v);\n", opts.FaultNth)
- }
- meta := sys.Calls[instr]
- emitCall := true
- if meta.CallName == "syz_test" {
- emitCall = false
- }
- if !opts.EnableTun && (meta.CallName == "syz_emit_ethernet" || meta.CallName == "syz_extract_tcp_res") {
- emitCall = false
- }
- if emitCall {
- if meta.Native {
- fmt.Fprintf(w, "\tr[%v] = syscall(__NR_%v", n, meta.CallName)
- } else {
- fmt.Fprintf(w, "\tr[%v] = %v(", n, meta.CallName)
- }
- }
- nargs := read()
- for i := uintptr(0); i < nargs; i++ {
- typ := read()
- size := read()
- _ = size
- if emitCall && (meta.Native || i > 0) {
- fmt.Fprintf(w, ", ")
- }
- switch typ {
- case prog.ExecArgConst:
- value := read()
- if emitCall {
- fmt.Fprintf(w, "0x%xul", value)
- }
- // Bitfields can't be args of a normal syscall, so just ignore them.
- read() // bit field offset
- read() // bit field length
- case prog.ExecArgResult:
- ref := resultRef()
- if emitCall {
- fmt.Fprintf(w, "%v", ref)
- }
- default:
- panic(fmt.Sprintf("unknown arg type %v", typ))
- }
- }
- if emitCall {
- fmt.Fprintf(w, ");\n")
- }
- lastCall = n
- seenCall = true
- }
- }
- newCall()
- return calls, n
-}
-
-func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks, useChecksums bool) (string, error) {
- var defines []string
- if useBitmasks {
- defines = append(defines, "SYZ_USE_BITMASKS")
- }
- if useChecksums {
- defines = append(defines, "SYZ_USE_CHECKSUMS")
- }
- switch opts.Sandbox {
- case "":
- // No sandbox, do nothing.
- case "none":
- defines = append(defines, "SYZ_SANDBOX_NONE")
- case "setuid":
- defines = append(defines, "SYZ_SANDBOX_SETUID")
- case "namespace":
- defines = append(defines, "SYZ_SANDBOX_NAMESPACE")
- default:
- return "", fmt.Errorf("unknown sandbox mode: %v", opts.Sandbox)
- }
- if opts.Threaded {
- defines = append(defines, "SYZ_THREADED")
- }
- if opts.Collide {
- defines = append(defines, "SYZ_COLLIDE")
- }
- if opts.Repeat {
- defines = append(defines, "SYZ_REPEAT")
- }
- if opts.Fault {
- defines = append(defines, "SYZ_FAULT_INJECTION")
- }
- if opts.EnableTun {
- defines = append(defines, "SYZ_TUN_ENABLE")
- }
- if opts.UseTmpDir {
- defines = append(defines, "SYZ_USE_TMP_DIR")
- }
- if opts.HandleSegv {
- defines = append(defines, "SYZ_HANDLE_SEGV")
- }
- if opts.WaitRepeat {
- defines = append(defines, "SYZ_WAIT_REPEAT")
- }
- if opts.Debug {
- defines = append(defines, "SYZ_DEBUG")
- }
- for name, _ := range handled {
- defines = append(defines, "__NR_"+name)
- }
- // TODO: need to know target arch + do cross-compilation
- defines = append(defines, "__x86_64__")
-
- cmd := exec.Command("cpp", "-nostdinc", "-undef", "-fdirectives-only", "-dDI", "-E", "-P", "-")
- for _, def := range defines {
- cmd.Args = append(cmd.Args, "-D"+def)
- }
- cmd.Stdin = strings.NewReader(commonHeader)
- stderr := new(bytes.Buffer)
- stdout := new(bytes.Buffer)
- cmd.Stderr = stderr
- cmd.Stdout = stdout
- if err := cmd.Run(); len(stdout.Bytes()) == 0 {
- return "", fmt.Errorf("cpp failed: %v\n%v\n%v\n", err, stdout.String(), stderr.String())
- }
- remove := append(defines, []string{
- "__STDC__",
- "__STDC_HOSTED__",
- "__STDC_UTF_16__",
- "__STDC_UTF_32__",
- }...)
- out := stdout.String()
- for _, def := range remove {
- out = strings.Replace(out, "#define "+def+" 1\n", "", -1)
- }
- // strip: #define __STDC_VERSION__ 201112L
- for _, def := range []string{"__STDC_VERSION__"} {
- pos := strings.Index(out, "#define "+def)
- if pos == -1 {
- continue
- }
- end := strings.IndexByte(out[pos:], '\n')
- if end == -1 {
- continue
- }
- out = strings.Replace(out, out[pos:end+1], "", -1)
- }
- return out, nil
-}
-
-// Build builds a C/C++ program from source src and returns name of the resulting binary.
-// lang can be "c" or "c++".
-func Build(lang, src string) (string, error) {
- bin, err := ioutil.TempFile("", "syzkaller")
- if err != nil {
- return "", fmt.Errorf("failed to create temp file: %v", err)
- }
- bin.Close()
- out, err := exec.Command("gcc", "-x", lang, "-Wall", "-Werror", src, "-o", bin.Name(), "-pthread", "-static", "-O1", "-g").CombinedOutput()
- if err != nil {
- // Some distributions don't have static libraries.
- out, err = exec.Command("gcc", "-x", lang, "-Wall", "-Werror", src, "-o", bin.Name(), "-pthread", "-O1", "-g").CombinedOutput()
- }
- if err != nil {
- os.Remove(bin.Name())
- data, _ := ioutil.ReadFile(src)
- return "", fmt.Errorf("failed to build program:\n%s\n%s", data, out)
- }
- return bin.Name(), nil
-}
-
-// Format reformats C source using clang-format.
-func Format(src []byte) ([]byte, error) {
- stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
- cmd := exec.Command("clang-format", "-assume-filename=/src.c", "-style", style)
- cmd.Stdin = bytes.NewReader(src)
- cmd.Stdout = stdout
- cmd.Stderr = stderr
- if err := cmd.Run(); err != nil {
- return src, fmt.Errorf("failed to format source: %v\n%v", err, stderr.String())
- }
- return stdout.Bytes(), nil
-}
-
-// Something acceptable for kernel developers and email-friendly.
-var style = `{
-BasedOnStyle: LLVM,
-IndentWidth: 2,
-UseTab: Never,
-BreakBeforeBraces: Linux,
-IndentCaseLabels: false,
-DerivePointerAlignment: false,
-PointerAlignment: Left,
-AlignTrailingComments: true,
-AllowShortBlocksOnASingleLine: false,
-AllowShortCaseLabelsOnASingleLine: false,
-AllowShortFunctionsOnASingleLine: false,
-AllowShortIfStatementsOnASingleLine: false,
-AllowShortLoopsOnASingleLine: false,
-ColumnLimit: 72,
-}`
diff --git a/csource/csource_test.go b/csource/csource_test.go
deleted file mode 100644
index 9357dcf65..000000000
--- a/csource/csource_test.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2015 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.
-
-package csource
-
-import (
- "fmt"
- "math/rand"
- "os"
- "reflect"
- "testing"
- "time"
-
- "github.com/google/syzkaller/pkg/fileutil"
- "github.com/google/syzkaller/prog"
-)
-
-func initTest(t *testing.T) (rand.Source, int) {
- t.Parallel()
- iters := 1
- seed := int64(time.Now().UnixNano())
- rs := rand.NewSource(seed)
- t.Logf("seed=%v", seed)
- return rs, iters
-}
-
-func enumerateField(opt Options, field int) []Options {
- var opts []Options
- s := reflect.ValueOf(&opt).Elem()
- fldName := s.Type().Field(field).Name
- fld := s.Field(field)
- if fldName == "Sandbox" {
- for _, sandbox := range []string{"", "none", "setuid", "namespace"} {
- fld.SetString(sandbox)
- opts = append(opts, opt)
- }
- } else if fldName == "Procs" {
- for _, procs := range []int64{1, 4} {
- fld.SetInt(procs)
- opts = append(opts, opt)
- }
- } else if fldName == "FaultCall" {
- opts = append(opts, opt)
- } else if fldName == "FaultNth" {
- opts = append(opts, opt)
- } else if fld.Kind() == reflect.Bool {
- for _, v := range []bool{false, true} {
- fld.SetBool(v)
- opts = append(opts, opt)
- }
- } else {
- panic(fmt.Sprintf("field '%v' is not boolean", fldName))
- }
- return opts
-}
-
-func allOptionsSingle() []Options {
- var opts []Options
- fields := reflect.TypeOf(Options{}).NumField()
- for i := 0; i < fields; i++ {
- opts = append(opts, enumerateField(Options{}, i)...)
- }
- return opts
-}
-
-func allOptionsPermutations() []Options {
- opts := []Options{Options{}}
- fields := reflect.TypeOf(Options{}).NumField()
- for i := 0; i < fields; i++ {
- var newOpts []Options
- for _, opt := range opts {
- newOpts = append(newOpts, enumerateField(opt, i)...)
- }
- opts = newOpts
- }
- return opts
-}
-
-func TestOne(t *testing.T) {
- rs, _ := initTest(t)
- opts := Options{
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: 2,
- Sandbox: "namespace",
- Repro: true,
- }
- p := prog.GenerateAllSyzProg(rs)
- testOne(t, p, opts)
-}
-
-func TestOptions(t *testing.T) {
- rs, _ := initTest(t)
- syzProg := prog.GenerateAllSyzProg(rs)
- t.Logf("syz program:\n%s\n", syzProg.Serialize())
- permutations := allOptionsSingle()
- allPermutations := allOptionsPermutations()
- if testing.Short() {
- r := rand.New(rs)
- for i := 0; i < 32; i++ {
- permutations = append(permutations, allPermutations[r.Intn(len(allPermutations))])
- }
- } else {
- permutations = append(permutations, allPermutations...)
- }
- for i, opts := range permutations {
- t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
- rs, iters := initTest(t)
- t.Logf("opts: %+v", opts)
- for i := 0; i < iters; i++ {
- p := prog.Generate(rs, 10, nil)
- testOne(t, p, opts)
- }
- testOne(t, syzProg, opts)
- })
- }
-}
-
-func testOne(t *testing.T, p *prog.Prog, opts Options) {
- src, err := Write(p, opts)
- if err != nil {
- t.Logf("program:\n%s\n", p.Serialize())
- t.Fatalf("%v", err)
- }
- srcf, err := fileutil.WriteTempFile(src)
- if err != nil {
- t.Logf("program:\n%s\n", p.Serialize())
- t.Fatalf("%v", err)
- }
- defer os.Remove(srcf)
- bin, err := Build("c", srcf)
- if err != nil {
- t.Logf("program:\n%s\n", p.Serialize())
- t.Fatalf("%v", err)
- }
- defer os.Remove(bin)
-}