aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-22 11:09:53 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-22 13:10:55 +0200
commit913d592f973a0155647473eaa032711fe956f8a5 (patch)
tree29b1b2083c00d199cf4d9a30917411d923b49ef4 /executor
parentc26ea367cfa790e86800ac025638ad50f95b8287 (diff)
all: more assorted fuchsia support
Diffstat (limited to 'executor')
-rw-r--r--executor/common.h918
-rw-r--r--executor/common_fuchsia.h51
-rw-r--r--executor/common_linux.h877
-rw-r--r--executor/executor.h684
-rw-r--r--executor/executor_fuchsia.cc139
-rw-r--r--executor/executor_linux.cc728
-rw-r--r--executor/syscalls_fuchsia.h29
-rw-r--r--executor/syscalls_linux.h1050
-rw-r--r--executor/test_executor_linux.cc6
9 files changed, 2370 insertions, 2112 deletions
diff --git a/executor/common.h b/executor/common.h
index 23cc02bb1..9eb5ea2c5 100644
--- a/executor/common.h
+++ b/executor/common.h
@@ -3,23 +3,12 @@
// This file is shared between executor and csource package.
-#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>
#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>
@@ -27,102 +16,42 @@
#include <stdlib.h>
#include <sys/stat.h>
#endif
-#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT))
-#include <errno.h>
+#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
+#include <setjmp.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>
+#include <string.h>
#endif
-#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE)
+#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT))
#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>
+#include <time.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>
+
+#if defined(SYZ_EXECUTOR)
+typedef long (*syscall_t)(long, long, long, long, long, long, long, long, long);
+
+struct call_t {
+ const char* name;
+ int sys_nr;
+ syscall_t call;
+};
+
+// Defined in generated syscalls_OS.h files.
+extern call_t syscalls[];
+extern unsigned syscall_count;
#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)
+#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
@@ -131,39 +60,9 @@ const int kRetryStatus = 69;
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)
-// One does not simply exit.
-// _exit can in fact fail.
-// syzkaller did manage to generate a seccomp filter that prohibits exit_group syscall.
-// Previously, we get into infinite recursion via segv_handler in such case
-// and corrupted output_data, which does matter in our case since it is shared
-// with fuzzer process. Loop infinitely instead. Parent will kill us.
-// But one does not simply loop either. Compilers are sure that _exit never returns,
-// so they remove all code after _exit as dead. Call _exit via volatile indirection.
-// And this does not work as well. _exit has own handling of failing exit_group
-// in the form of HLT instruction, it will divert control flow from our loop.
-// So call the syscall directly.
-__attribute__((noreturn)) static void doexit(int status)
-{
- volatile unsigned i;
- syscall(__NR_exit_group, status);
- for (i = 0;; i++) {
- }
-}
-#endif
-
-#if defined(SYZ_EXECUTOR)
-// exit/_exit do not necessary work.
-#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)
+#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)
// logical error (e.g. invalid input program), use as an assert() alernative
__attribute__((noreturn)) static void fail(const char* msg, ...)
{
@@ -265,25 +164,6 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx)
}
}
-static void install_segv_handler()
-{
- struct sigaction sa;
-
- // Don't need that SIGCANCEL/SIGSETXID glibc stuff.
- // SIGCANCEL sent to main thread causes it to exit
- // without bringing down the whole group.
- 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); \
@@ -294,162 +174,6 @@ static void install_segv_handler()
}
#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;
-
-// We just need this to be large enough to hold headers that we parse (ethernet/ip/tcp).
-// Rest of the packet (if any) will be silently truncated which is fine.
-#define SYZ_TUN_MAX_PACKET_SIZE 1000
-
-// sysgen knowns about this constant (maxPids)
-#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);
-
- // Disable IPv6 DAD, otherwise the address remains unusable until DAD completes.
- execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
-
- // Disable IPv6 router solicitation to prevent IPv6 spam.
- execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
- // There seems to be no way to disable IPv6 MTD to prevent more IPv6 spam.
-
- 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;
@@ -482,523 +206,6 @@ static uint16_t csum_inet_digest(struct csum_inet* csum)
}
#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)
-{
- // syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet])
-
- 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))
-#ifndef __ANDROID__
-// Can't include <linux/ipv6.h>, since it causes
-// conflicts due to some structs redefinition.
-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;
-};
-#endif
-
-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)
-{
- // syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32)
-
- 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)];
- // TODO: parse and skip extension headers.
- 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) {
- // syz_open_dev$char(dev const[0xc], major intptr, minor intptr) fd
- // syz_open_dev$block(dev const[0xb], major intptr, minor intptr) fd
- 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 {
- // syz_open_dev(dev strconst, id intptr, flags flags[open_flags]) fd
- 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); // 10 devices should be enough for everyone.
- 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)
-{
- // syz_openpts(fd fd[tty], flags flags[open_flags]) fd[tty]
- 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)
-{
- // syz_fuse_mount(target filename, mode flags[fuse_mode], uid uid, gid gid, maxread intptr, flags flags[mount_flags]) fd[fuse]
- 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);
- // Ignore errors, maybe fuzzer can do something useful with fd alone.
- 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)
-{
- // syz_fuseblk_mount(target filename, blkdev filename, mode flags[fuse_mode], uid uid, gid gid, maxread intptr, blksize intptr, flags flags[mount_flags]) fd[fuse]
- 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);
- // Ignore errors, maybe fuzzer can do something useful with fd alone.
- return fd;
-}
-#endif
-
-#ifdef __NR_syz_kvm_setup_cpu
-#if defined(__x86_64__)
-#include "common_kvm_amd64.h"
-#elif defined(__aarch64__)
-#include "common_kvm_arm64.h"
-#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 __NR_syz_kvm_setup_cpu
-
-#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 = 8 << 20;
- setrlimit(RLIMIT_MEMLOCK, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 1 << 20;
- setrlimit(RLIMIT_FSIZE, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 1 << 20;
- setrlimit(RLIMIT_STACK, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 0;
- setrlimit(RLIMIT_CORE, &rlim);
-
- // CLONE_NEWIPC/CLONE_IO cause EINVAL on some systems, so we do them separately of clone.
- 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");
-
- // This is required to open /proc/self/* files.
- // Otherwise they are owned by root and we can't open them after setuid.
- // See task_dump_owner function in kernel.
- 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();
-
- // /proc/self/setgroups is not present on some systems, ignore error.
- 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)
- // For sandbox namespace we setup tun after initializing uid mapping,
- // otherwise ip commands fail.
- 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");
-
- // Drop CAP_SYS_PTRACE so that test processes can't attach to parent processes.
- // Previously it lead to hangs because the loop process stopped due to SIGSTOP.
- // Note that a process can always ptrace its direct children, which is enough
- // for testing purposes.
- 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); // to catch stack underflows
- 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))
-// One does not simply remove a directory.
-// There can be mounts, so we need to try to umount.
-// Moreover, a mount can be mounted several times, so we need to try to umount in a loop.
-// Moreover, after umount a dir can become non-empty again, so we need another loop.
-// Moreover, a mount can be re-mounted as read-only and then we will fail to make a dir empty.
-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) {
- // This happens when the test process casts prlimit(NOFILE) on us.
- // Ideally we somehow prevent test processes from messing with parent processes.
- // But full sandboxing is expensive, so let's ignore this error for now.
- 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()
{
@@ -1009,80 +216,3 @@ static uint64_t current_time_ms()
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/executor/common_fuchsia.h b/executor/common_fuchsia.h
new file mode 100644
index 000000000..189e7bc3c
--- /dev/null
+++ b/executor/common_fuchsia.h
@@ -0,0 +1,51 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// This file is shared between executor and csource package.
+
+#include <zircon/process.h>
+#include <zircon/syscalls.h>
+
+#define doexit exit
+
+#include "common.h"
+
+#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
+static void install_segv_handler()
+{
+ struct sigaction sa;
+
+ 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);
+}
+#endif
+
+#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION)
+static int inject_fault(int nth)
+{
+ return 0;
+}
+
+static int fault_injected(int fail_fd)
+{
+ return 0;
+}
+#endif
+
+#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mmap)
+long syz_mmap(size_t addr, size_t size)
+{
+ zx_handle_t mapping = 0;
+ uintptr_t res = 0;
+ uintptr_t offset = 16 << 20;
+ zx_status_t status = zx_vmar_allocate(zx_vmar_root_self(), addr - offset, size,
+ ZX_VM_FLAG_SPECIFIC | ZX_VM_FLAG_CAN_MAP_READ | ZX_VM_FLAG_CAN_MAP_WRITE,
+ &mapping, &res);
+ if (addr != res)
+ error("zx_vmar_allocate allocated wrong address: %p, want %p", (void*)res, (void*)addr);
+ return status;
+}
+#endif
diff --git a/executor/common_linux.h b/executor/common_linux.h
new file mode 100644
index 000000000..dd7d0ac31
--- /dev/null
+++ b/executor/common_linux.h
@@ -0,0 +1,877 @@
+// Copyright 2016 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.
+
+// This file is shared between executor and csource package.
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT))
+#include <sys/prctl.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(__NR_syz_open_dev)
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#endif
+#if defined(SYZ_EXECUTOR) || 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
+#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_pts)
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#endif
+#if defined(SYZ_EXECUTOR) || defined(__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_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)
+// One does not simply exit.
+// _exit can in fact fail.
+// syzkaller did manage to generate a seccomp filter that prohibits exit_group syscall.
+// Previously, we get into infinite recursion via segv_handler in such case
+// and corrupted output_data, which does matter in our case since it is shared
+// with fuzzer process. Loop infinitely instead. Parent will kill us.
+// But one does not simply loop either. Compilers are sure that _exit never returns,
+// so they remove all code after _exit as dead. Call _exit via volatile indirection.
+// And this does not work as well. _exit has own handling of failing exit_group
+// in the form of HLT instruction, it will divert control flow from our loop.
+// So call the syscall directly.
+__attribute__((noreturn)) static void doexit(int status)
+{
+ volatile unsigned i;
+ syscall(__NR_exit_group, status);
+ for (i = 0;; i++) {
+ }
+}
+#endif
+
+#if defined(SYZ_EXECUTOR)
+// exit/_exit do not necessary work.
+#define exit use_doexit_instead
+#define _exit use_doexit_instead
+#endif
+
+#include "common.h"
+
+#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
+static void install_segv_handler()
+{
+ struct sigaction sa;
+
+ // Don't need that SIGCANCEL/SIGSETXID glibc stuff.
+ // SIGCANCEL sent to main thread causes it to exit
+ // without bringing down the whole group.
+ 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);
+}
+#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;
+
+// We just need this to be large enough to hold headers that we parse (ethernet/ip/tcp).
+// Rest of the packet (if any) will be silently truncated which is fine.
+#define SYZ_TUN_MAX_PACKET_SIZE 1000
+
+// sysgen knowns about this constant (maxPids)
+#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);
+
+ // Disable IPv6 DAD, otherwise the address remains unusable until DAD completes.
+ execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
+
+ // Disable IPv6 router solicitation to prevent IPv6 spam.
+ execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
+ // There seems to be no way to disable IPv6 MTD to prevent more IPv6 spam.
+
+ 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(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE))
+static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
+{
+ // syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet])
+
+ 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))
+#ifndef __ANDROID__
+// Can't include <linux/ipv6.h>, since it causes
+// conflicts due to some structs redefinition.
+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;
+};
+#endif
+
+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)
+{
+ // syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32)
+
+ 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)];
+ // TODO: parse and skip extension headers.
+ 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
+
+#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_dev)
+static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
+{
+ if (a0 == 0xc || a0 == 0xb) {
+ // syz_open_dev$char(dev const[0xc], major intptr, minor intptr) fd
+ // syz_open_dev$block(dev const[0xb], major intptr, minor intptr) fd
+ 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 {
+ // syz_open_dev(dev strconst, id intptr, flags flags[open_flags]) fd
+ 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); // 10 devices should be enough for everyone.
+ a1 /= 10;
+ }
+ return open(buf, a2, 0);
+ }
+}
+#endif
+
+#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_pts)
+static uintptr_t syz_open_pts(uintptr_t a0, uintptr_t a1)
+{
+ // syz_openpts(fd fd[tty], flags flags[open_flags]) fd[tty]
+ 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
+
+#if defined(SYZ_EXECUTOR) || defined(__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)
+{
+ // syz_fuse_mount(target filename, mode flags[fuse_mode], uid uid, gid gid, maxread intptr, flags flags[mount_flags]) fd[fuse]
+ 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);
+ // Ignore errors, maybe fuzzer can do something useful with fd alone.
+ return fd;
+}
+#endif
+
+#if defined(SYZ_EXECUTOR) || defined(__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)
+{
+ // syz_fuseblk_mount(target filename, blkdev filename, mode flags[fuse_mode], uid uid, gid gid, maxread intptr, blksize intptr, flags flags[mount_flags]) fd[fuse]
+ 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);
+ // Ignore errors, maybe fuzzer can do something useful with fd alone.
+ return fd;
+}
+#endif
+
+#if defined(SYZ_EXECUTOR) || defined(__NR_syz_kvm_setup_cpu)
+#if defined(__x86_64__)
+#include "common_kvm_amd64.h"
+#elif defined(__aarch64__)
+#include "common_kvm_arm64.h"
+#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 __NR_syz_kvm_setup_cpu
+
+#if defined(SYZ_EXECUTOR)
+// TODO(dvyukov): syz_test call should be moved to a "test" target.
+static uintptr_t syz_test()
+{
+ return 0;
+}
+#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 = 8 << 20;
+ setrlimit(RLIMIT_MEMLOCK, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 1 << 20;
+ setrlimit(RLIMIT_FSIZE, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 1 << 20;
+ setrlimit(RLIMIT_STACK, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+
+ // CLONE_NEWIPC/CLONE_IO cause EINVAL on some systems, so we do them separately of clone.
+ 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");
+
+ // This is required to open /proc/self/* files.
+ // Otherwise they are owned by root and we can't open them after setuid.
+ // See task_dump_owner function in kernel.
+ 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();
+
+ // /proc/self/setgroups is not present on some systems, ignore error.
+ 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)
+ // For sandbox namespace we setup tun after initializing uid mapping,
+ // otherwise ip commands fail.
+ 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");
+
+ // Drop CAP_SYS_PTRACE so that test processes can't attach to parent processes.
+ // Previously it lead to hangs because the loop process stopped due to SIGSTOP.
+ // Note that a process can always ptrace its direct children, which is enough
+ // for testing purposes.
+ 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); // to catch stack underflows
+ 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))
+// One does not simply remove a directory.
+// There can be mounts, so we need to try to umount.
+// Moreover, a mount can be mounted several times, so we need to try to umount in a loop.
+// Moreover, after umount a dir can become non-empty again, so we need another loop.
+// Moreover, a mount can be re-mounted as read-only and then we will fail to make a dir empty.
+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) {
+ // This happens when the test process casts prlimit(NOFILE) on us.
+ // Ideally we somehow prevent test processes from messing with parent processes.
+ // But full sandboxing is expensive, so let's ignore this error for now.
+ 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_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_EXECUTOR)
+static int fault_injected(int fail_fd)
+{
+ char buf[16];
+ int n = read(fail_fd, buf, sizeof(buf) - 1);
+ if (n <= 0)
+ fail("failed to read /proc/self/task/tid/fail-nth");
+ int res = n == 2 && buf[0] == '0' && buf[1] == '\n';
+ buf[0] = '0';
+ if (write(fail_fd, buf, 1) != 1)
+ fail("failed to write /proc/self/task/tid/fail-nth");
+ close(fail_fd);
+ return res;
+}
+#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/executor/executor.h b/executor/executor.h
new file mode 100644
index 000000000..08112ec5d
--- /dev/null
+++ b/executor/executor.h
@@ -0,0 +1,684 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+#include <algorithm>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef GIT_REVISION
+#define GIT_REVISION "unknown"
+#endif
+
+const int kMaxInput = 2 << 20;
+const int kMaxOutput = 16 << 20;
+const int kMaxArgs = 9;
+const int kMaxThreads = 16;
+const int kMaxCommands = 16 << 10;
+
+const uint64_t instr_eof = -1;
+const uint64_t instr_copyin = -2;
+const uint64_t instr_copyout = -3;
+
+const uint64_t arg_const = 0;
+const uint64_t arg_result = 1;
+const uint64_t arg_data = 2;
+const uint64_t arg_csum = 3;
+
+enum sandbox_type {
+ sandbox_none,
+ sandbox_setuid,
+ sandbox_namespace,
+};
+
+bool flag_cover;
+bool flag_threaded;
+bool flag_collide;
+bool flag_sandbox_privs;
+sandbox_type flag_sandbox;
+bool flag_enable_tun;
+bool flag_enable_fault_injection;
+
+bool flag_collect_cover;
+bool flag_dedup_cover;
+
+// If true, then executor should write the comparisons data to fuzzer.
+bool flag_collect_comps;
+
+// Inject fault into flag_fault_nth-th operation in flag_fault_call-th syscall.
+bool flag_inject_fault;
+int flag_fault_call;
+int flag_fault_nth;
+
+int running;
+uint32_t completed;
+bool collide;
+
+// We use the default value instead of results of failed syscalls.
+// -1 is an invalid fd and an invalid address and deterministic,
+// so good enough for our purposes.
+const uint64_t default_value = -1;
+
+// Checksum kinds.
+const uint64_t arg_csum_inet = 0;
+
+// Checksum chunk kinds.
+const uint64_t arg_csum_chunk_data = 0;
+const uint64_t arg_csum_chunk_const = 1;
+
+struct thread_t {
+ bool created;
+ int id;
+ pthread_t th;
+ // TODO(dvyukov): this assumes 64-bit kernel. This must be "kernel long" somehow.
+ uint64_t* cover_data;
+ // Pointer to the size of coverage (stored as first word of memory).
+ uint64_t* cover_size_ptr;
+
+ event_t ready;
+ event_t done;
+ uint64_t* copyout_pos;
+ bool handled;
+ int call_n;
+ int call_index;
+ int call_num;
+ int num_args;
+ long args[kMaxArgs];
+ long res;
+ uint32_t reserrno;
+ uint64_t cover_size;
+ bool fault_injected;
+ int cover_fd;
+};
+
+thread_t threads[kMaxThreads];
+
+struct res_t {
+ bool executed;
+ uint64_t val;
+};
+
+res_t results[kMaxCommands];
+
+enum {
+ KCOV_CMP_CONST = 1,
+ KCOV_CMP_SIZE1 = 0,
+ KCOV_CMP_SIZE2 = 2,
+ KCOV_CMP_SIZE4 = 4,
+ KCOV_CMP_SIZE8 = 6,
+ KCOV_CMP_SIZE_MASK = 6,
+};
+
+struct kcov_comparison_t {
+ uint64_t type;
+ uint64_t arg1;
+ uint64_t arg2;
+
+ // Writes the structure using the write_one function for each field.
+ // Inspired by write_output() function.
+ void write(uint32_t* (*write_one)(uint32_t));
+ bool operator==(const struct kcov_comparison_t& other) const;
+ bool operator<(const struct kcov_comparison_t& other) const;
+};
+
+long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8);
+thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, uint64_t* args, uint64_t* pos);
+void handle_completion(thread_t* th);
+void execute_call(thread_t* th);
+void thread_create(thread_t* th, int id);
+void* worker_thread(void* arg);
+void event_init(event_t* ev);
+void event_set(event_t* ev);
+void event_reset(event_t* ev);
+void event_wait(event_t* ev);
+bool event_isset(event_t* ev);
+bool event_timedwait(event_t* ev, uint64_t timeout_ms);
+uint32_t* write_output(uint32_t v);
+void write_completed(uint32_t completed);
+uint64_t read_input(uint64_t** input_posp, bool peek = false);
+uint64_t read_arg(uint64_t** input_posp);
+uint64_t read_result(uint64_t** input_posp);
+void copyin(char* addr, uint64_t val, uint64_t size, uint64_t bf_off, uint64_t bf_len);
+uint64_t copyout(char* addr, uint64_t size);
+void cover_open();
+void cover_enable(thread_t* th);
+void cover_reset(thread_t* th);
+uint64_t read_cover_size(thread_t* th);
+static uint32_t hash(uint32_t a);
+static bool dedup(uint32_t sig);
+
+void execute_one(uint64_t* input_data)
+{
+retry:
+ uint64_t* input_pos = input_data;
+ write_output(0); // Number of executed syscalls (updated later).
+
+ if (!collide && !flag_threaded)
+ cover_enable(&threads[0]);
+
+ int call_index = 0;
+ for (int n = 0;; n++) {
+ uint64_t call_num = read_input(&input_pos);
+ if (call_num == instr_eof)
+ break;
+ if (call_num == instr_copyin) {
+ char* addr = (char*)read_input(&input_pos);
+ uint64_t typ = read_input(&input_pos);
+ uint64_t size = read_input(&input_pos);
+ debug("copyin to %p\n", addr);
+ switch (typ) {
+ case arg_const: {
+ uint64_t arg = read_input(&input_pos);
+ uint64_t bf_off = read_input(&input_pos);
+ uint64_t bf_len = read_input(&input_pos);
+ copyin(addr, arg, size, bf_off, bf_len);
+ break;
+ }
+ case arg_result: {
+ uint64_t val = read_result(&input_pos);
+ copyin(addr, val, size, 0, 0);
+ break;
+ }
+ case arg_data: {
+ NONFAILING(memcpy(addr, input_pos, size));
+ // Read out the data.
+ for (uint64_t i = 0; i < (size + 7) / 8; i++)
+ read_input(&input_pos);
+ break;
+ }
+ case arg_csum: {
+ debug("checksum found at %llx\n", addr);
+ char* csum_addr = addr;
+ uint64_t csum_size = size;
+ uint64_t csum_kind = read_input(&input_pos);
+ switch (csum_kind) {
+ case arg_csum_inet: {
+ if (csum_size != 2) {
+ fail("inet checksum must be 2 bytes, not %lu", size);
+ }
+ debug("calculating checksum for %llx\n", csum_addr);
+ struct csum_inet csum;
+ csum_inet_init(&csum);
+ uint64_t chunks_num = read_input(&input_pos);
+ uint64_t chunk;
+ for (chunk = 0; chunk < chunks_num; chunk++) {
+ uint64_t chunk_kind = read_input(&input_pos);
+ uint64_t chunk_value = read_input(&input_pos);
+ uint64_t chunk_size = read_input(&input_pos);
+ switch (chunk_kind) {
+ case arg_csum_chunk_data:
+ debug("#%d: data chunk, addr: %llx, size: %llu\n", chunk, chunk_value, chunk_size);
+ NONFAILING(csum_inet_update(&csum, (const uint8_t*)chunk_value, chunk_size));
+ break;
+ case arg_csum_chunk_const:
+ if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) {
+ fail("bad checksum const chunk size %lld\n", chunk_size);
+ }
+ // Here we assume that const values come to us big endian.
+ debug("#%d: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size);
+ csum_inet_update(&csum, (const uint8_t*)&chunk_value, chunk_size);
+ break;
+ default:
+ fail("bad checksum chunk kind %lu", chunk_kind);
+ }
+ }
+ int16_t csum_value = csum_inet_digest(&csum);
+ debug("writing inet checksum %hx to %llx\n", csum_value, csum_addr);
+ NONFAILING(copyin(csum_addr, csum_value, 2, 0, 0));
+ break;
+ }
+ default:
+ fail("bad checksum kind %lu", csum_kind);
+ }
+ break;
+ }
+ default:
+ fail("bad argument type %lu", typ);
+ }
+ continue;
+ }
+ if (call_num == instr_copyout) {
+ read_input(&input_pos); // addr
+ read_input(&input_pos); // size
+ // The copyout will happen when/if the call completes.
+ continue;
+ }
+
+ // Normal syscall.
+ if (call_num >= syscall_count)
+ fail("invalid command number %lu", call_num);
+ uint64_t num_args = read_input(&input_pos);
+ if (num_args > kMaxArgs)
+ fail("command has bad number of arguments %lu", num_args);
+ uint64_t args[kMaxArgs] = {};
+ for (uint64_t i = 0; i < num_args; i++)
+ args[i] = read_arg(&input_pos);
+ for (uint64_t i = num_args; i < 6; i++)
+ args[i] = 0;
+ thread_t* th = schedule_call(n, call_index++, call_num, num_args, args, input_pos);
+
+ if (collide && (call_index % 2) == 0) {
+ // Don't wait for every other call.
+ // We already have results from the previous execution.
+ } else if (flag_threaded) {
+ // Wait for call completion.
+ // Note: sys knows about this 20ms timeout when it generates
+ // timespec/timeval values.
+ const uint64_t timeout_ms = flag_debug ? 500 : 20;
+ if (event_timedwait(&th->done, timeout_ms))
+ handle_completion(th);
+ // Check if any of previous calls have completed.
+ // Give them some additional time, because they could have been
+ // just unblocked by the current call.
+ if (running < 0)
+ fail("running = %d", running);
+ if (running > 0) {
+ bool last = read_input(&input_pos, true) == instr_eof;
+ usleep(last ? 1000 : 100);
+ for (int i = 0; i < kMaxThreads; i++) {
+ th = &threads[i];
+ if (!th->handled && event_isset(&th->done))
+ handle_completion(th);
+ }
+ }
+ } else {
+ // Execute directly.
+ if (th != &threads[0])
+ fail("using non-main thread in non-thread mode");
+ execute_call(th);
+ handle_completion(th);
+ }
+ }
+
+ if (flag_collide && !flag_inject_fault && !collide) {
+ debug("enabling collider\n");
+ collide = true;
+ goto retry;
+ }
+}
+
+thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, uint64_t* args, uint64_t* pos)
+{
+ // Find a spare thread to execute the call.
+ int i;
+ for (i = 0; i < kMaxThreads; i++) {
+ thread_t* th = &threads[i];
+ if (!th->created)
+ thread_create(th, i);
+ if (event_isset(&th->done)) {
+ if (!th->handled)
+ handle_completion(th);
+ break;
+ }
+ }
+ if (i == kMaxThreads)
+ exitf("out of threads");
+ thread_t* th = &threads[i];
+ debug("scheduling call %d [%s] on thread %d\n", call_index, syscalls[call_num].name, th->id);
+ if (event_isset(&th->ready) || !event_isset(&th->done) || !th->handled)
+ fail("bad thread state in schedule: ready=%d done=%d handled=%d",
+ event_isset(&th->ready), event_isset(&th->done), th->handled);
+ th->copyout_pos = pos;
+ event_reset(&th->done);
+ th->handled = false;
+ th->call_n = n;
+ th->call_index = call_index;
+ th->call_num = call_num;
+ th->num_args = num_args;
+ for (int i = 0; i < kMaxArgs; i++)
+ th->args[i] = args[i];
+ event_set(&th->ready);
+ running++;
+ return th;
+}
+
+void handle_completion(thread_t* th)
+{
+ debug("completion of call %d [%s] on thread %d\n", th->call_index, syscalls[th->call_num].name, th->id);
+ if (event_isset(&th->ready) || !event_isset(&th->done) || th->handled)
+ fail("bad thread state in completion: ready=%d done=%d handled=%d",
+ event_isset(&th->ready), event_isset(&th->done), th->handled);
+ if (th->res != (long)-1) {
+ if (th->call_n >= kMaxCommands)
+ fail("result idx %ld overflows kMaxCommands", th->call_n);
+ results[th->call_n].executed = true;
+ results[th->call_n].val = th->res;
+ for (bool done = false; !done;) {
+ th->call_n++;
+ uint64_t call_num = read_input(&th->copyout_pos);
+ switch (call_num) {
+ case instr_copyout: {
+ char* addr = (char*)read_input(&th->copyout_pos);
+ uint64_t size = read_input(&th->copyout_pos);
+ uint64_t val = copyout(addr, size);
+ if (th->call_n >= kMaxCommands)
+ fail("result idx %ld overflows kMaxCommands", th->call_n);
+ results[th->call_n].executed = true;
+ results[th->call_n].val = val;
+ debug("copyout from %p\n", addr);
+ break;
+ }
+ default:
+ done = true;
+ break;
+ }
+ }
+ }
+ if (!collide) {
+ write_output(th->call_index);
+ write_output(th->call_num);
+ uint32_t reserrno = th->res != (uint32_t)-1 ? 0 : th->reserrno;
+ write_output(reserrno);
+ write_output(th->fault_injected);
+ uint32_t* signal_count_pos = write_output(0); // filled in later
+ uint32_t* cover_count_pos = write_output(0); // filled in later
+ uint32_t* comps_count_pos = write_output(0); // filled in later
+ uint32_t nsig = 0, cover_size = 0, comps_size = 0;
+
+ if (flag_collect_comps) {
+ // Collect only the comparisons
+ comps_size = th->cover_size;
+ kcov_comparison_t* start = (kcov_comparison_t*)th->cover_data;
+ kcov_comparison_t* end = start + comps_size;
+ std::sort(start, end);
+ comps_size = std::unique(start, end) - start;
+ for (uint32_t i = 0; i < comps_size; ++i)
+ start[i].write(write_output);
+ } else {
+ // Write out feedback signals.
+ // Currently it is code edges computed as xor of
+ // two subsequent basic block PCs.
+ uint32_t prev = 0;
+ for (uint32_t i = 0; i < th->cover_size; i++) {
+ uint32_t pc = (uint32_t)th->cover_data[i];
+ uint32_t sig = pc ^ prev;
+ prev = hash(pc);
+ if (dedup(sig))
+ continue;
+ write_output(sig);
+ nsig++;
+ }
+ if (flag_collect_cover) {
+ // Write out real coverage (basic block PCs).
+ cover_size = th->cover_size;
+ if (flag_dedup_cover) {
+ uint64_t* start = (uint64_t*)th->cover_data;
+ uint64_t* end = start + cover_size;
+ std::sort(start, end);
+ cover_size = std::unique(start, end) - start;
+ }
+ // Truncate PCs to uint32_t assuming that they fit into 32-bits.
+ // True for x86_64 and arm64 without KASLR.
+ for (uint32_t i = 0; i < cover_size; i++)
+ write_output((uint32_t)th->cover_data[i]);
+ }
+ }
+ // Write out real coverage (basic block PCs).
+ *cover_count_pos = cover_size;
+ // Write out number of comparisons
+ *comps_count_pos = comps_size;
+ // Write out number of signals
+ *signal_count_pos = nsig;
+ debug("out #%u: index=%u num=%u errno=%d sig=%u cover=%u comps=%u\n",
+ completed, th->call_index, th->call_num, reserrno, nsig,
+ cover_size, comps_size);
+ completed++;
+ write_completed(completed);
+ }
+ th->handled = true;
+ running--;
+}
+
+void thread_create(thread_t* th, int id)
+{
+ th->created = true;
+ th->id = id;
+ th->handled = true;
+ event_init(&th->ready);
+ event_init(&th->done);
+ event_set(&th->done);
+ if (flag_threaded) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 128 << 10);
+ if (pthread_create(&th->th, &attr, worker_thread, th))
+ exitf("pthread_create failed");
+ pthread_attr_destroy(&attr);
+ }
+}
+
+void* worker_thread(void* arg)
+{
+ thread_t* th = (thread_t*)arg;
+
+ cover_enable(th);
+ for (;;) {
+ event_wait(&th->ready);
+ execute_call(th);
+ }
+ return 0;
+}
+
+void execute_call(thread_t* th)
+{
+ event_reset(&th->ready);
+ call_t* call = &syscalls[th->call_num];
+ debug("#%d: %s(", th->id, call->name);
+ for (int i = 0; i < th->num_args; i++) {
+ if (i != 0)
+ debug(", ");
+ debug("0x%lx", th->args[i]);
+ }
+ debug(")\n");
+
+ int fail_fd = -1;
+ if (flag_inject_fault && th->call_index == flag_fault_call) {
+ if (collide)
+ fail("both collide and fault injection are enabled");
+ debug("injecting fault into %d-th operation\n", flag_fault_nth);
+ fail_fd = inject_fault(flag_fault_nth);
+ }
+
+ cover_reset(th);
+ th->res = execute_syscall(call, th->args[0], th->args[1], th->args[2],
+ th->args[3], th->args[4], th->args[5],
+ th->args[6], th->args[7], th->args[8]);
+ th->reserrno = errno;
+ th->cover_size = read_cover_size(th);
+ th->fault_injected = false;
+
+ if (flag_inject_fault && th->call_index == flag_fault_call) {
+ th->fault_injected = fault_injected(fail_fd);
+ debug("fault injected: %d\n", th->fault_injected);
+ }
+
+ if (th->res == (uint32_t)-1)
+ debug("#%d: %s = errno(%d)\n", th->id, call->name, th->reserrno);
+ else
+ debug("#%d: %s = 0x%lx\n", th->id, call->name, th->res);
+ event_set(&th->done);
+}
+
+static uint32_t hash(uint32_t a)
+{
+ a = (a ^ 61) ^ (a >> 16);
+ a = a + (a << 3);
+ a = a ^ (a >> 4);
+ a = a * 0x27d4eb2d;
+ a = a ^ (a >> 15);
+ return a;
+}
+
+const uint32_t dedup_table_size = 8 << 10;
+uint32_t dedup_table[dedup_table_size];
+
+// Poorman's best-effort hashmap-based deduplication.
+// The hashmap is global which means that we deduplicate across different calls.
+// This is OK because we are interested only in new signals.
+static bool dedup(uint32_t sig)
+{
+ for (uint32_t i = 0; i < 4; i++) {
+ uint32_t pos = (sig + i) % dedup_table_size;
+ if (dedup_table[pos] == sig)
+ return true;
+ if (dedup_table[pos] == 0) {
+ dedup_table[pos] = sig;
+ return false;
+ }
+ }
+ dedup_table[sig % dedup_table_size] = sig;
+ return false;
+}
+
+void copyin(char* addr, uint64_t val, uint64_t size, uint64_t bf_off, uint64_t bf_len)
+{
+ NONFAILING(switch (size) {
+ case 1:
+ STORE_BY_BITMASK(uint8_t, addr, val, bf_off, bf_len);
+ break;
+ case 2:
+ STORE_BY_BITMASK(uint16_t, addr, val, bf_off, bf_len);
+ break;
+ case 4:
+ STORE_BY_BITMASK(uint32_t, addr, val, bf_off, bf_len);
+ break;
+ case 8:
+ STORE_BY_BITMASK(uint64_t, addr, val, bf_off, bf_len);
+ break;
+ default:
+ fail("copyin: bad argument size %lu", size);
+ });
+}
+
+uint64_t copyout(char* addr, uint64_t size)
+{
+ uint64_t res = default_value;
+ NONFAILING(switch (size) {
+ case 1:
+ res = *(uint8_t*)addr;
+ break;
+ case 2:
+ res = *(uint16_t*)addr;
+ break;
+ case 4:
+ res = *(uint32_t*)addr;
+ break;
+ case 8:
+ res = *(uint64_t*)addr;
+ break;
+ default:
+ fail("copyout: bad argument size %lu", size);
+ });
+ return res;
+}
+
+uint64_t read_arg(uint64_t** input_posp)
+{
+ uint64_t typ = read_input(input_posp);
+ uint64_t size = read_input(input_posp);
+ (void)size;
+ uint64_t arg = 0;
+ switch (typ) {
+ case arg_const: {
+ arg = read_input(input_posp);
+ // Bitfields can't be args of a normal syscall, so just ignore them.
+ read_input(input_posp); // bit field offset
+ read_input(input_posp); // bit field length
+ break;
+ }
+ case arg_result: {
+ arg = read_result(input_posp);
+ break;
+ }
+ default:
+ fail("bad argument type %lu", typ);
+ }
+ return arg;
+}
+
+uint64_t read_result(uint64_t** input_posp)
+{
+ uint64_t idx = read_input(input_posp);
+ uint64_t op_div = read_input(input_posp);
+ uint64_t op_add = read_input(input_posp);
+ if (idx >= kMaxCommands)
+ fail("command refers to bad result %ld", idx);
+ uint64_t arg = default_value;
+ if (results[idx].executed) {
+ arg = results[idx].val;
+ if (op_div != 0)
+ arg = arg / op_div;
+ arg += op_add;
+ }
+ return arg;
+}
+
+uint64_t read_input(uint64_t** input_posp, bool peek)
+{
+ uint64_t* input_pos = *input_posp;
+ //if ((char*)input_pos >= input_data + kMaxInput)
+ // fail("input command overflows input");
+ if (!peek)
+ *input_posp = input_pos + 1;
+ return *input_pos;
+}
+
+void kcov_comparison_t::write(uint32_t* (*write_one)(uint32_t))
+{
+ // Write order: type arg1 arg2.
+ write_one((uint32_t)type);
+
+ // KCOV converts all arguments of size x first to uintx_t and then to
+ // uint64_t. We want to properly extend signed values, e.g we want
+ // int8_t c = 0xfe to be represented as 0xfffffffffffffffe.
+ // Note that uint8_t c = 0xfe will be represented the same way.
+ // This is ok because during hints processing we will anyways try
+ // the value 0x00000000000000fe.
+ switch (type & KCOV_CMP_SIZE_MASK) {
+ case KCOV_CMP_SIZE1:
+ arg1 = (uint64_t)(int64_t)(int8_t)arg1;
+ arg2 = (uint64_t)(int64_t)(int8_t)arg2;
+ break;
+ case KCOV_CMP_SIZE2:
+ arg1 = (uint64_t)(int64_t)(int16_t)arg1;
+ arg2 = (uint64_t)(int64_t)(int16_t)arg2;
+ break;
+ case KCOV_CMP_SIZE4:
+ arg1 = (uint64_t)(int64_t)(int32_t)arg1;
+ arg2 = (uint64_t)(int64_t)(int32_t)arg2;
+ break;
+ }
+ bool is_size_8 = (type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8;
+ if (!is_size_8) {
+ write_one((uint32_t)arg1);
+ write_one((uint32_t)arg2);
+ return;
+ }
+ // If we have 64 bits arguments then write them in Little-endian.
+ write_one((uint32_t)(arg1 & 0xFFFFFFFF));
+ write_one((uint32_t)(arg1 >> 32));
+ write_one((uint32_t)(arg2 & 0xFFFFFFFF));
+ write_one((uint32_t)(arg2 >> 32));
+}
+
+bool kcov_comparison_t::operator==(const struct kcov_comparison_t& other) const
+{
+ return type == other.type && arg1 == other.arg1 && arg2 == other.arg2;
+}
+
+bool kcov_comparison_t::operator<(const struct kcov_comparison_t& other) const
+{
+ if (type != other.type)
+ return type < other.type;
+ if (arg1 != other.arg1)
+ return arg1 < other.arg1;
+ return arg2 < other.arg2;
+}
diff --git a/executor/executor_fuchsia.cc b/executor/executor_fuchsia.cc
index 3a214e4ac..4ff293350 100644
--- a/executor/executor_fuchsia.cc
+++ b/executor/executor_fuchsia.cc
@@ -3,10 +3,145 @@
// +build
+#define SYZ_EXECUTOR
+#include "common_fuchsia.h"
+
+struct event_t {
+ pthread_mutex_t mu;
+ pthread_cond_t cv;
+ bool state;
+};
+
+#include "executor.h"
+
#include "syscalls_fuchsia.h"
-int main()
+char input_data[kMaxInput];
+uint32_t output;
+
+int main(int argc, char** argv)
+{
+ if (argc == 2 && strcmp(argv[1], "version") == 0) {
+ puts("linux " GOARCH " " SYZ_REVISION " " GIT_REVISION);
+ return 0;
+ }
+
+ int pos = 0;
+ for (;;) {
+ int rv = read(0, input_data + pos, sizeof(input_data) - pos);
+ if (rv < 0)
+ fail("read failed");
+ if (rv == 0)
+ break;
+ pos += rv;
+ }
+ if (pos < 24)
+ fail("truncated input");
+
+ uint64_t flags = *(uint64_t*)input_data;
+ flag_debug = flags & (1 << 0);
+ flag_threaded = flags & (1 << 2);
+ flag_collide = flags & (1 << 3);
+ if (!flag_threaded)
+ flag_collide = false;
+ uint64_t executor_pid = *((uint64_t*)input_data + 2);
+ debug("input %d, threaded=%d collide=%d pid=%llu\n",
+ pos, flag_threaded, flag_collide, executor_pid);
+
+ execute_one(((uint64_t*)input_data) + 3);
+ return 0;
+}
+
+long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8)
+{
+ debug("%s = %p\n", c->name, c->call);
+ long res = c->call(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+ debug("%s = %ld\n", c->name, res);
+ return res;
+}
+
+void cover_open()
+{
+}
+
+void cover_enable(thread_t* th)
+{
+}
+
+void cover_reset(thread_t* th)
+{
+}
+
+uint64_t read_cover_size(thread_t* th)
{
- (void)syscalls;
return 0;
}
+
+uint32_t* write_output(uint32_t v)
+{
+ return &output;
+}
+
+void write_completed(uint32_t completed)
+{
+}
+
+void event_init(event_t* ev)
+{
+ if (pthread_mutex_init(&ev->mu, 0))
+ fail("pthread_mutex_init failed");
+ if (pthread_cond_init(&ev->cv, 0))
+ fail("pthread_cond_init failed");
+ ev->state = false;
+}
+
+void event_reset(event_t* ev)
+{
+ ev->state = false;
+}
+
+void event_set(event_t* ev)
+{
+ pthread_mutex_lock(&ev->mu);
+ if (ev->state)
+ fail("event already set");
+ ev->state = true;
+ pthread_mutex_unlock(&ev->mu);
+ pthread_cond_broadcast(&ev->cv);
+}
+
+void event_wait(event_t* ev)
+{
+ pthread_mutex_lock(&ev->mu);
+ while (!ev->state)
+ pthread_cond_wait(&ev->cv, &ev->mu);
+ pthread_mutex_unlock(&ev->mu);
+}
+
+bool event_isset(event_t* ev)
+{
+ pthread_mutex_lock(&ev->mu);
+ bool res = ev->state;
+ pthread_mutex_unlock(&ev->mu);
+ return res;
+}
+
+bool event_timedwait(event_t* ev, uint64_t timeout_ms)
+{
+ pthread_mutex_lock(&ev->mu);
+ uint64_t start = current_time_ms();
+ for (;;) {
+ if (ev->state)
+ break;
+ uint64_t now = current_time_ms();
+ if (now - start > timeout_ms)
+ break;
+ timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = (timeout_ms - (now - start)) * 1000 * 1000;
+ pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
+ }
+ bool res = ev->state;
+ pthread_mutex_unlock(&ev->mu);
+ return res;
+}
diff --git a/executor/executor_linux.cc b/executor/executor_linux.cc
index d428fc1ea..85a0b29c8 100644
--- a/executor/executor_linux.cc
+++ b/executor/executor_linux.cc
@@ -3,19 +3,9 @@
// +build
-#include <algorithm>
-#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <linux/futex.h>
-#include <pthread.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/stat.h>
@@ -23,13 +13,17 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <time.h>
#include <unistd.h>
-#include "syscalls_linux.h"
+struct event_t {
+ int state;
+};
#define SYZ_EXECUTOR
-#include "common.h"
+#include "common_linux.h"
+#include "executor.h"
+
+#include "syscalls_linux.h"
#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long long)
#define KCOV_INIT_CMP _IOR('c', 2, unsigned long long)
@@ -43,192 +37,12 @@ const int kInFd = 3;
const int kOutFd = 4;
const int kInPipeFd = 5;
const int kOutPipeFd = 6;
-const int kMaxInput = 2 << 20;
-const int kMaxOutput = 16 << 20;
-const int kMaxArgs = 9;
-const int kMaxThreads = 16;
-const int kMaxCommands = 16 << 10;
const int kCoverSize = 64 << 10;
const int kPageSize = 4 << 10;
-const uint64_t instr_eof = -1;
-const uint64_t instr_copyin = -2;
-const uint64_t instr_copyout = -3;
-
-const uint64_t arg_const = 0;
-const uint64_t arg_result = 1;
-const uint64_t arg_data = 2;
-const uint64_t arg_csum = 3;
-
-// We use the default value instead of results of failed syscalls.
-// -1 is an invalid fd and an invalid address and deterministic,
-// so good enough for our purposes.
-const uint64_t default_value = -1;
-
-enum sandbox_type {
- sandbox_none,
- sandbox_setuid,
- sandbox_namespace,
-};
-
-bool flag_cover;
-bool flag_threaded;
-bool flag_collide;
-bool flag_sandbox_privs;
-sandbox_type flag_sandbox;
-bool flag_enable_tun;
-bool flag_enable_fault_injection;
-
-bool flag_collect_cover;
-bool flag_dedup_cover;
-
-// If true, then executor should write the comparisons data to fuzzer.
-bool flag_collect_comps;
-
-// Inject fault into flag_fault_nth-th operation in flag_fault_call-th syscall.
-bool flag_inject_fault;
-int flag_fault_call;
-int flag_fault_nth;
-
__attribute__((aligned(64 << 10))) char input_data[kMaxInput];
uint32_t* output_data;
uint32_t* output_pos;
-uint32_t completed;
-int running;
-bool collide;
-
-struct res_t {
- bool executed;
- uint64_t val;
-};
-
-res_t results[kMaxCommands];
-
-enum {
- KCOV_CMP_CONST = 1,
- KCOV_CMP_SIZE1 = 0,
- KCOV_CMP_SIZE2 = 2,
- KCOV_CMP_SIZE4 = 4,
- KCOV_CMP_SIZE8 = 6,
- KCOV_CMP_SIZE_MASK = 6,
-};
-
-struct kcov_comparison_t {
- uint64_t type;
- uint64_t arg1;
- uint64_t arg2;
-
- bool operator==(const struct kcov_comparison_t& other) const
- {
- return type == other.type && arg1 == other.arg1 && arg2 == other.arg2;
- }
-
- bool operator<(const struct kcov_comparison_t& other) const
- {
- if (type != other.type)
- return type < other.type;
- if (arg1 != other.arg1)
- return arg1 < other.arg1;
- return arg2 < other.arg2;
- }
-
- // Writes the structure using the write_one function for each field.
- // Inspired by write_output() function.
- void write(uint32_t* (*write_one)(uint32_t))
- {
- // Write order: type arg1 arg2.
- write_one((uint32_t)type);
-
- // KCOV converts all arguments of size x first to uintx_t and then to
- // uint64_t. We want to properly extend signed values, e.g we want
- // int8_t c = 0xfe to be represented as 0xfffffffffffffffe.
- // Note that uint8_t c = 0xfe will be represented the same way.
- // This is ok because during hints processing we will anyways try
- // the value 0x00000000000000fe.
- switch (type & KCOV_CMP_SIZE_MASK) {
- case KCOV_CMP_SIZE1:
- arg1 = (uint64_t)(int64_t)(int8_t)arg1;
- arg2 = (uint64_t)(int64_t)(int8_t)arg2;
- break;
- case KCOV_CMP_SIZE2:
- arg1 = (uint64_t)(int64_t)(int16_t)arg1;
- arg2 = (uint64_t)(int64_t)(int16_t)arg2;
- break;
- case KCOV_CMP_SIZE4:
- arg1 = (uint64_t)(int64_t)(int32_t)arg1;
- arg2 = (uint64_t)(int64_t)(int32_t)arg2;
- break;
- }
- bool is_size_8 = (type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8;
- if (!is_size_8) {
- write_one((uint32_t)arg1);
- write_one((uint32_t)arg2);
- return;
- }
- // If we have 64 bits arguments then write them in Little-endian.
- write_one((uint32_t)(arg1 & 0xFFFFFFFF));
- write_one((uint32_t)(arg1 >> 32));
- write_one((uint32_t)(arg2 & 0xFFFFFFFF));
- write_one((uint32_t)(arg2 >> 32));
- }
-};
-
-struct thread_t {
- bool created;
- int id;
- pthread_t th;
- // TODO(dvyukov): this assumes 64-bit kernel. This must be "kernel long" somehow.
- uint64_t* cover_data;
- // Pointer to the size of coverage (stored as first word of memory).
- uint64_t* cover_size_ptr;
-
- uint64_t* copyout_pos;
- int ready;
- int done;
- bool handled;
- int call_n;
- int call_index;
- int call_num;
- int num_args;
- uintptr_t args[kMaxArgs];
- uintptr_t res;
- uint32_t reserrno;
- uint64_t cover_size;
- bool fault_injected;
- int cover_fd;
-};
-
-thread_t threads[kMaxThreads];
-
-// Checksum kinds.
-const uint64_t arg_csum_inet = 0;
-
-// Checksum chunk kinds.
-const uint64_t arg_csum_chunk_data = 0;
-const uint64_t arg_csum_chunk_const = 1;
-
-void execute_one();
-uint64_t read_input(uint64_t** input_posp, bool peek = false);
-uint64_t read_arg(uint64_t** input_posp);
-uint64_t read_result(uint64_t** input_posp);
-uint32_t* write_output(uint32_t v);
-void copyin(char* addr, uint64_t val, uint64_t size, uint64_t bf_off, uint64_t bf_len);
-uint64_t copyout(char* addr, uint64_t size);
-thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, uint64_t* args, uint64_t* pos);
-void execute_call(thread_t* th);
-void handle_completion(thread_t* th);
-void thread_create(thread_t* th, int id);
-void* worker_thread(void* arg);
-void cover_open();
-void cover_enable(thread_t* th);
-void cover_reset(thread_t* th);
-uint64_t read_cover_size(thread_t* th);
-static uint32_t hash(uint32_t a);
-static bool dedup(uint32_t sig);
-
-#ifndef GIT_REVISION
-#define GIT_REVISION "unknown"
-#endif
int main(int argc, char** argv)
{
@@ -373,7 +187,9 @@ void loop()
// isolate consequently executing programs.
flush_tun();
}
- execute_one();
+ uint64_t* input_pos = ((uint64_t*)&input_data[0]) + 2; // skip flags and pid
+ output_pos = output_data;
+ execute_one(input_pos);
debug("worker exiting\n");
doexit(0);
}
@@ -437,380 +253,11 @@ void loop()
}
}
-void execute_one()
-{
-retry:
- uint64_t* input_pos = (uint64_t*)&input_data[0];
- read_input(&input_pos); // flags
- read_input(&input_pos); // pid
- output_pos = output_data;
- write_output(0); // Number of executed syscalls (updated later).
-
- if (!collide && !flag_threaded)
- cover_enable(&threads[0]);
-
- int call_index = 0;
- for (int n = 0;; n++) {
- uint64_t call_num = read_input(&input_pos);
- if (call_num == instr_eof)
- break;
- if (call_num == instr_copyin) {
- char* addr = (char*)read_input(&input_pos);
- uint64_t typ = read_input(&input_pos);
- uint64_t size = read_input(&input_pos);
- debug("copyin to %p\n", addr);
- switch (typ) {
- case arg_const: {
- uint64_t arg = read_input(&input_pos);
- uint64_t bf_off = read_input(&input_pos);
- uint64_t bf_len = read_input(&input_pos);
- copyin(addr, arg, size, bf_off, bf_len);
- break;
- }
- case arg_result: {
- uint64_t val = read_result(&input_pos);
- copyin(addr, val, size, 0, 0);
- break;
- }
- case arg_data: {
- NONFAILING(memcpy(addr, input_pos, size));
- // Read out the data.
- for (uint64_t i = 0; i < (size + 7) / 8; i++)
- read_input(&input_pos);
- break;
- }
- case arg_csum: {
- debug("checksum found at %llx\n", addr);
- char* csum_addr = addr;
- uint64_t csum_size = size;
- uint64_t csum_kind = read_input(&input_pos);
- switch (csum_kind) {
- case arg_csum_inet: {
- if (csum_size != 2) {
- fail("inet checksum must be 2 bytes, not %lu", size);
- }
- debug("calculating checksum for %llx\n", csum_addr);
- struct csum_inet csum;
- csum_inet_init(&csum);
- uint64_t chunks_num = read_input(&input_pos);
- uint64_t chunk;
- for (chunk = 0; chunk < chunks_num; chunk++) {
- uint64_t chunk_kind = read_input(&input_pos);
- uint64_t chunk_value = read_input(&input_pos);
- uint64_t chunk_size = read_input(&input_pos);
- switch (chunk_kind) {
- case arg_csum_chunk_data:
- debug("#%d: data chunk, addr: %llx, size: %llu\n", chunk, chunk_value, chunk_size);
- NONFAILING(csum_inet_update(&csum, (const uint8_t*)chunk_value, chunk_size));
- break;
- case arg_csum_chunk_const:
- if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) {
- fail("bad checksum const chunk size %lld\n", chunk_size);
- }
- // Here we assume that const values come to us big endian.
- debug("#%d: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size);
- csum_inet_update(&csum, (const uint8_t*)&chunk_value, chunk_size);
- break;
- default:
- fail("bad checksum chunk kind %lu", chunk_kind);
- }
- }
- int16_t csum_value = csum_inet_digest(&csum);
- debug("writing inet checksum %hx to %llx\n", csum_value, csum_addr);
- NONFAILING(copyin(csum_addr, csum_value, 2, 0, 0));
- break;
- }
- default:
- fail("bad checksum kind %lu", csum_kind);
- }
- break;
- }
- default:
- fail("bad argument type %lu", typ);
- }
- continue;
- }
- if (call_num == instr_copyout) {
- read_input(&input_pos); // addr
- read_input(&input_pos); // size
- // The copyout will happen when/if the call completes.
- continue;
- }
-
- // Normal syscall.
- if (call_num >= sizeof(syscalls) / sizeof(syscalls[0]))
- fail("invalid command number %lu", call_num);
- uint64_t num_args = read_input(&input_pos);
- if (num_args > kMaxArgs)
- fail("command has bad number of arguments %lu", num_args);
- uint64_t args[kMaxArgs] = {};
- for (uint64_t i = 0; i < num_args; i++)
- args[i] = read_arg(&input_pos);
- for (uint64_t i = num_args; i < 6; i++)
- args[i] = 0;
- thread_t* th = schedule_call(n, call_index++, call_num, num_args, args, input_pos);
-
- if (collide && (call_index % 2) == 0) {
- // Don't wait for every other call.
- // We already have results from the previous execution.
- } else if (flag_threaded) {
- // Wait for call completion.
- uint64_t start = current_time_ms();
- uint64_t now = start;
- // Note: sys knows about this 20ms timeout when it generates
- // timespec/timeval values.
- const uint64_t timeout_ms = flag_debug ? 500 : 20;
- for (;;) {
- timespec ts = {};
- ts.tv_sec = 0;
- ts.tv_nsec = (timeout_ms - (now - start)) * 1000 * 1000;
- syscall(SYS_futex, &th->done, FUTEX_WAIT, 0, &ts);
- if (__atomic_load_n(&th->done, __ATOMIC_RELAXED))
- break;
- now = current_time_ms();
- if (now - start > 20)
- break;
- }
- if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE))
- handle_completion(th);
- // Check if any of previous calls have completed.
- // Give them some additional time, because they could have been
- // just unblocked by the current call.
- if (running < 0)
- fail("running = %d", running);
- if (running > 0) {
- bool last = read_input(&input_pos, true) == instr_eof;
- usleep(last ? 1000 : 100);
- for (int i = 0; i < kMaxThreads; i++) {
- th = &threads[i];
- if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE) && !th->handled)
- handle_completion(th);
- }
- }
- } else {
- // Execute directly.
- if (th != &threads[0])
- fail("using non-main thread in non-thread mode");
- execute_call(th);
- handle_completion(th);
- }
- }
-
- if (flag_collide && !flag_inject_fault && !collide) {
- debug("enabling collider\n");
- collide = true;
- goto retry;
- }
-}
-
-thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, uint64_t* args, uint64_t* pos)
-{
- // Find a spare thread to execute the call.
- int i;
- for (i = 0; i < kMaxThreads; i++) {
- thread_t* th = &threads[i];
- if (!th->created)
- thread_create(th, i);
- if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE)) {
- if (!th->handled)
- handle_completion(th);
- break;
- }
- }
- if (i == kMaxThreads)
- exitf("out of threads");
- thread_t* th = &threads[i];
- debug("scheduling call %d [%s] on thread %d\n", call_index, syscalls[call_num].name, th->id);
- if (th->ready || !th->done || !th->handled)
- fail("bad thread state in schedule: ready=%d done=%d handled=%d", th->ready, th->done, th->handled);
- th->copyout_pos = pos;
- th->done = false;
- th->handled = false;
- th->call_n = n;
- th->call_index = call_index;
- th->call_num = call_num;
- th->num_args = num_args;
- for (int i = 0; i < kMaxArgs; i++)
- th->args[i] = args[i];
- __atomic_store_n(&th->ready, 1, __ATOMIC_RELEASE);
- syscall(SYS_futex, &th->ready, FUTEX_WAKE);
- running++;
- return th;
-}
-
-void handle_completion(thread_t* th)
-{
- debug("completion of call %d [%s] on thread %d\n", th->call_index, syscalls[th->call_num].name, th->id);
- if (th->ready || !th->done || th->handled)
- fail("bad thread state in completion: ready=%d done=%d handled=%d",
- th->ready, th->done, th->handled);
- if (th->res != (uintptr_t)-1) {
- if (th->call_n >= kMaxCommands)
- fail("result idx %ld overflows kMaxCommands", th->call_n);
- results[th->call_n].executed = true;
- results[th->call_n].val = th->res;
- for (bool done = false; !done;) {
- th->call_n++;
- uint64_t call_num = read_input(&th->copyout_pos);
- switch (call_num) {
- case instr_copyout: {
- char* addr = (char*)read_input(&th->copyout_pos);
- uint64_t size = read_input(&th->copyout_pos);
- uint64_t val = copyout(addr, size);
- if (th->call_n >= kMaxCommands)
- fail("result idx %ld overflows kMaxCommands", th->call_n);
- results[th->call_n].executed = true;
- results[th->call_n].val = val;
- debug("copyout from %p\n", addr);
- break;
- }
- default:
- done = true;
- break;
- }
- }
- }
- if (!collide) {
- write_output(th->call_index);
- write_output(th->call_num);
- uint32_t reserrno = th->res != (uint32_t)-1 ? 0 : th->reserrno;
- write_output(reserrno);
- write_output(th->fault_injected);
- uint32_t* signal_count_pos = write_output(0); // filled in later
- uint32_t* cover_count_pos = write_output(0); // filled in later
- uint32_t* comps_count_pos = write_output(0); // filled in later
- uint32_t nsig = 0, cover_size = 0, comps_size = 0;
-
- if (flag_collect_comps) {
- // Collect only the comparisons
- comps_size = th->cover_size;
- kcov_comparison_t* start = (kcov_comparison_t*)th->cover_data;
- kcov_comparison_t* end = start + comps_size;
- std::sort(start, end);
- comps_size = std::unique(start, end) - start;
- for (uint32_t i = 0; i < comps_size; ++i)
- start[i].write(write_output);
- } else {
- // Write out feedback signals.
- // Currently it is code edges computed as xor of
- // two subsequent basic block PCs.
- uint32_t prev = 0;
- for (uint32_t i = 0; i < th->cover_size; i++) {
- uint32_t pc = (uint32_t)th->cover_data[i];
- uint32_t sig = pc ^ prev;
- prev = hash(pc);
- if (dedup(sig))
- continue;
- write_output(sig);
- nsig++;
- }
- if (flag_collect_cover) {
- // Write out real coverage (basic block PCs).
- cover_size = th->cover_size;
- if (flag_dedup_cover) {
- uint64_t* start = (uint64_t*)th->cover_data;
- uint64_t* end = start + cover_size;
- std::sort(start, end);
- cover_size = std::unique(start, end) - start;
- }
- // Truncate PCs to uint32_t assuming that they fit into 32-bits.
- // True for x86_64 and arm64 without KASLR.
- for (uint32_t i = 0; i < cover_size; i++)
- write_output((uint32_t)th->cover_data[i]);
- }
- }
- // Write out real coverage (basic block PCs).
- *cover_count_pos = cover_size;
- // Write out number of comparisons
- *comps_count_pos = comps_size;
- // Write out number of signals
- *signal_count_pos = nsig;
- debug("out #%u: index=%u num=%u errno=%d sig=%u cover=%u comps=%u\n",
- completed, th->call_index, th->call_num, reserrno, nsig,
- cover_size, comps_size);
- completed++;
- __atomic_store_n(output_data, completed, __ATOMIC_RELEASE);
- }
- th->handled = true;
- running--;
-}
-
-void thread_create(thread_t* th, int id)
-{
- th->created = true;
- th->id = id;
- th->done = true;
- th->handled = true;
- if (flag_threaded) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, 128 << 10);
- if (pthread_create(&th->th, &attr, worker_thread, th))
- exitf("pthread_create failed");
- pthread_attr_destroy(&attr);
- }
-}
-
-void* worker_thread(void* arg)
+long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8)
{
- thread_t* th = (thread_t*)arg;
-
- cover_enable(th);
- for (;;) {
- while (!__atomic_load_n(&th->ready, __ATOMIC_ACQUIRE))
- syscall(SYS_futex, &th->ready, FUTEX_WAIT, 0, 0);
- execute_call(th);
- }
- return 0;
-}
-
-void execute_call(thread_t* th)
-{
- th->ready = false;
- call_t* call = &syscalls[th->call_num];
- debug("#%d: %s(", th->id, call->name);
- for (int i = 0; i < th->num_args; i++) {
- if (i != 0)
- debug(", ");
- debug("0x%lx", th->args[i]);
- }
- debug(")\n");
-
- int fail_fd = -1;
- if (flag_inject_fault && th->call_index == flag_fault_call) {
- if (collide)
- fail("both collide and fault injection are enabled");
- debug("injecting fault into %d-th operation\n", flag_fault_nth);
- fail_fd = inject_fault(flag_fault_nth);
- }
-
- cover_reset(th);
- th->res = execute_syscall(call->sys_nr, th->args[0], th->args[1],
- th->args[2], th->args[3], th->args[4], th->args[5],
- th->args[6], th->args[7], th->args[8]);
- th->reserrno = errno;
- th->cover_size = read_cover_size(th);
- th->fault_injected = false;
-
- if (flag_inject_fault && th->call_index == flag_fault_call) {
- char buf[16];
- int n = read(fail_fd, buf, sizeof(buf) - 1);
- if (n <= 0)
- fail("failed to read /proc/self/task/tid/fail-nth");
- th->fault_injected = n == 2 && buf[0] == '0' && buf[1] == '\n';
- buf[0] = '0';
- if (write(fail_fd, buf, 1) != 1)
- fail("failed to write /proc/self/task/tid/fail-nth");
- close(fail_fd);
- debug("fault injected: %d\n", th->fault_injected);
- }
-
- if (th->res == (uint32_t)-1)
- debug("#%d: %s = errno(%d)\n", th->id, call->name, th->reserrno);
- else
- debug("#%d: %s = 0x%lx\n", th->id, call->name, th->res);
- __atomic_store_n(&th->done, 1, __ATOMIC_RELEASE);
- syscall(SYS_futex, &th->done, FUTEX_WAKE);
+ if (c->call)
+ return c->call(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+ return syscall(c->sys_nr, a0, a1, a2, a3, a4, a5);
}
void cover_open()
@@ -866,136 +313,63 @@ uint64_t read_cover_size(thread_t* th)
return n;
}
-static uint32_t hash(uint32_t a)
+uint32_t* write_output(uint32_t v)
{
- a = (a ^ 61) ^ (a >> 16);
- a = a + (a << 3);
- a = a ^ (a >> 4);
- a = a * 0x27d4eb2d;
- a = a ^ (a >> 15);
- return a;
+ if (collide)
+ return 0;
+ if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput)
+ fail("output overflow");
+ *output_pos = v;
+ return output_pos++;
}
-const uint32_t dedup_table_size = 8 << 10;
-uint32_t dedup_table[dedup_table_size];
-
-// Poorman's best-effort hashmap-based deduplication.
-// The hashmap is global which means that we deduplicate across different calls.
-// This is OK because we are interested only in new signals.
-static bool dedup(uint32_t sig)
+void write_completed(uint32_t completed)
{
- for (uint32_t i = 0; i < 4; i++) {
- uint32_t pos = (sig + i) % dedup_table_size;
- if (dedup_table[pos] == sig)
- return true;
- if (dedup_table[pos] == 0) {
- dedup_table[pos] = sig;
- return false;
- }
- }
- dedup_table[sig % dedup_table_size] = sig;
- return false;
+ __atomic_store_n(output_data, completed, __ATOMIC_RELEASE);
}
-void copyin(char* addr, uint64_t val, uint64_t size, uint64_t bf_off, uint64_t bf_len)
+void event_init(event_t* ev)
{
- NONFAILING(switch (size) {
- case 1:
- STORE_BY_BITMASK(uint8_t, addr, val, bf_off, bf_len);
- break;
- case 2:
- STORE_BY_BITMASK(uint16_t, addr, val, bf_off, bf_len);
- break;
- case 4:
- STORE_BY_BITMASK(uint32_t, addr, val, bf_off, bf_len);
- break;
- case 8:
- STORE_BY_BITMASK(uint64_t, addr, val, bf_off, bf_len);
- break;
- default:
- fail("copyin: bad argument size %lu", size);
- });
+ ev->state = 0;
}
-uint64_t copyout(char* addr, uint64_t size)
+void event_reset(event_t* ev)
{
- uint64_t res = default_value;
- NONFAILING(switch (size) {
- case 1:
- res = *(uint8_t*)addr;
- break;
- case 2:
- res = *(uint16_t*)addr;
- break;
- case 4:
- res = *(uint32_t*)addr;
- break;
- case 8:
- res = *(uint64_t*)addr;
- break;
- default:
- fail("copyout: bad argument size %lu", size);
- });
- return res;
+ ev->state = 0;
}
-uint64_t read_arg(uint64_t** input_posp)
+void event_set(event_t* ev)
{
- uint64_t typ = read_input(input_posp);
- uint64_t size = read_input(input_posp);
- (void)size;
- uint64_t arg = 0;
- switch (typ) {
- case arg_const: {
- arg = read_input(input_posp);
- // Bitfields can't be args of a normal syscall, so just ignore them.
- read_input(input_posp); // bit field offset
- read_input(input_posp); // bit field length
- break;
- }
- case arg_result: {
- arg = read_result(input_posp);
- break;
- }
- default:
- fail("bad argument type %lu", typ);
- }
- return arg;
+ if (ev->state)
+ fail("event already set");
+ __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
+ syscall(SYS_futex, &ev->state, FUTEX_WAKE);
}
-uint64_t read_result(uint64_t** input_posp)
+void event_wait(event_t* ev)
{
- uint64_t idx = read_input(input_posp);
- uint64_t op_div = read_input(input_posp);
- uint64_t op_add = read_input(input_posp);
- if (idx >= kMaxCommands)
- fail("command refers to bad result %ld", idx);
- uint64_t arg = default_value;
- if (results[idx].executed) {
- arg = results[idx].val;
- if (op_div != 0)
- arg = arg / op_div;
- arg += op_add;
- }
- return arg;
+ while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
+ syscall(SYS_futex, &ev->state, FUTEX_WAIT, 0, 0);
}
-uint64_t read_input(uint64_t** input_posp, bool peek)
+bool event_isset(event_t* ev)
{
- uint64_t* input_pos = *input_posp;
- if ((char*)input_pos >= input_data + kMaxInput)
- fail("input command overflows input");
- if (!peek)
- *input_posp = input_pos + 1;
- return *input_pos;
+ return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
-uint32_t* write_output(uint32_t v)
+bool event_timedwait(event_t* ev, uint64_t timeout_ms)
{
- if (collide)
- return 0;
- if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput)
- fail("output overflow");
- *output_pos = v;
- return output_pos++;
+ uint64_t start = current_time_ms();
+ uint64_t now = start;
+ for (;;) {
+ timespec ts = {};
+ ts.tv_sec = 0;
+ ts.tv_nsec = (timeout_ms - (now - start)) * 1000 * 1000;
+ syscall(SYS_futex, &ev->state, FUTEX_WAIT, 0, &ts);
+ if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED))
+ return true;
+ now = current_time_ms();
+ if (now - start > timeout_ms)
+ return false;
+ }
}
diff --git a/executor/syscalls_fuchsia.h b/executor/syscalls_fuchsia.h
index 6919aec79..f64ef023c 100644
--- a/executor/syscalls_fuchsia.h
+++ b/executor/syscalls_fuchsia.h
@@ -1,26 +1,33 @@
// AUTOGENERATED FILE
-struct call_t {
- const char* name;
- int sys_nr;
-};
-
#if defined(__x86_64__) || 0
#define GOARCH "amd64"
-#define SYZ_REVISION "d65b9adb4853817be6f471df44fc8347ebf6dfc6"
+#define SYZ_REVISION "640bc9ab193d2488d41793c10c5a44bab3ad33f9"
+#define __NR_syz_mmap 1000000
-static call_t syscalls[] = {
- {"mx_time_get", 0},
+unsigned syscall_count = 5;
+call_t syscalls[] = {
+ {"syz_mmap", 1000000, (syscall_t)syz_mmap},
+ {"zx_handle_close", 0, (syscall_t)zx_handle_close},
+ {"zx_handle_duplicate", 0, (syscall_t)zx_handle_duplicate},
+ {"zx_handle_replace", 0, (syscall_t)zx_handle_replace},
+ {"zx_time_get", 0, (syscall_t)zx_time_get},
};
#endif
#if defined(__aarch64__) || 0
#define GOARCH "arm64"
-#define SYZ_REVISION "bd2655e6d85f1fecceb1648649e1ad5adda81dc8"
+#define SYZ_REVISION "8c364809f3ccf951f9c9ac974a817dfaf8d1713c"
+#define __NR_syz_mmap 1000000
-static call_t syscalls[] = {
- {"mx_time_get", 0},
+unsigned syscall_count = 5;
+call_t syscalls[] = {
+ {"syz_mmap", 1000000, (syscall_t)syz_mmap},
+ {"zx_handle_close", 0, (syscall_t)zx_handle_close},
+ {"zx_handle_duplicate", 0, (syscall_t)zx_handle_duplicate},
+ {"zx_handle_replace", 0, (syscall_t)zx_handle_replace},
+ {"zx_time_get", 0, (syscall_t)zx_time_get},
};
#endif
diff --git a/executor/syscalls_linux.h b/executor/syscalls_linux.h
index 48ea44e1c..b30807290 100644
--- a/executor/syscalls_linux.h
+++ b/executor/syscalls_linux.h
@@ -1,10 +1,5 @@
// AUTOGENERATED FILE
-struct call_t {
- const char* name;
- int sys_nr;
-};
-
#if defined(__i386__) || 0
#define GOARCH "386"
#define SYZ_REVISION "7b2f1949d48094cf3369932d0743db166049457b"
@@ -17,7 +12,8 @@ struct call_t {
#define __NR_syz_open_pts 1000006
#define __NR_syz_test 1000007
-static call_t syscalls[] = {
+unsigned syscall_count = 1481;
+call_t syscalls[] = {
{"accept4", 364},
{"accept4$ax25", 364},
{"accept4$inet", 364},
@@ -1351,109 +1347,109 @@ static call_t syscalls[] = {
{"sysfs$3", 135},
{"sysinfo", 116},
{"syslog", 103},
- {"syz_emit_ethernet", 1000000},
- {"syz_extract_tcp_res", 1000001},
- {"syz_extract_tcp_res$synack", 1000001},
- {"syz_fuse_mount", 1000002},
- {"syz_fuseblk_mount", 1000003},
- {"syz_kvm_setup_cpu$arm64", 1000004},
- {"syz_kvm_setup_cpu$x86", 1000004},
- {"syz_open_dev$admmidi", 1000005},
- {"syz_open_dev$adsp", 1000005},
- {"syz_open_dev$amidi", 1000005},
- {"syz_open_dev$audion", 1000005},
- {"syz_open_dev$dmmidi", 1000005},
- {"syz_open_dev$dri", 1000005},
- {"syz_open_dev$dricontrol", 1000005},
- {"syz_open_dev$drirender", 1000005},
- {"syz_open_dev$dspn", 1000005},
- {"syz_open_dev$evdev", 1000005},
- {"syz_open_dev$floppy", 1000005},
- {"syz_open_dev$ircomm", 1000005},
- {"syz_open_dev$loop", 1000005},
- {"syz_open_dev$mice", 1000005},
- {"syz_open_dev$midi", 1000005},
- {"syz_open_dev$mouse", 1000005},
- {"syz_open_dev$random", 1000005},
- {"syz_open_dev$sg", 1000005},
- {"syz_open_dev$sndctrl", 1000005},
- {"syz_open_dev$sndhw", 1000005},
- {"syz_open_dev$sndmidi", 1000005},
- {"syz_open_dev$sndpcmc", 1000005},
- {"syz_open_dev$sndpcmp", 1000005},
- {"syz_open_dev$sndseq", 1000005},
- {"syz_open_dev$sndtimer", 1000005},
- {"syz_open_dev$tlk_device", 1000005},
- {"syz_open_dev$tun", 1000005},
- {"syz_open_dev$urandom", 1000005},
- {"syz_open_dev$usb", 1000005},
- {"syz_open_dev$usbmon", 1000005},
- {"syz_open_dev$vcsa", 1000005},
- {"syz_open_dev$vcsn", 1000005},
- {"syz_open_pts", 1000006},
- {"syz_test", 1000007},
- {"syz_test$align0", 1000007},
- {"syz_test$align1", 1000007},
- {"syz_test$align2", 1000007},
- {"syz_test$align3", 1000007},
- {"syz_test$align4", 1000007},
- {"syz_test$align5", 1000007},
- {"syz_test$align6", 1000007},
- {"syz_test$array0", 1000007},
- {"syz_test$array1", 1000007},
- {"syz_test$array2", 1000007},
- {"syz_test$bf0", 1000007},
- {"syz_test$bf1", 1000007},
- {"syz_test$csum_encode", 1000007},
- {"syz_test$csum_ipv4", 1000007},
- {"syz_test$csum_ipv4_tcp", 1000007},
- {"syz_test$csum_ipv4_udp", 1000007},
- {"syz_test$csum_ipv6_icmp", 1000007},
- {"syz_test$csum_ipv6_tcp", 1000007},
- {"syz_test$csum_ipv6_udp", 1000007},
- {"syz_test$end0", 1000007},
- {"syz_test$end1", 1000007},
- {"syz_test$int", 1000007},
- {"syz_test$length0", 1000007},
- {"syz_test$length1", 1000007},
- {"syz_test$length10", 1000007},
- {"syz_test$length11", 1000007},
- {"syz_test$length12", 1000007},
- {"syz_test$length13", 1000007},
- {"syz_test$length14", 1000007},
- {"syz_test$length15", 1000007},
- {"syz_test$length16", 1000007},
- {"syz_test$length17", 1000007},
- {"syz_test$length18", 1000007},
- {"syz_test$length19", 1000007},
- {"syz_test$length2", 1000007},
- {"syz_test$length20", 1000007},
- {"syz_test$length3", 1000007},
- {"syz_test$length4", 1000007},
- {"syz_test$length5", 1000007},
- {"syz_test$length6", 1000007},
- {"syz_test$length7", 1000007},
- {"syz_test$length8", 1000007},
- {"syz_test$length9", 1000007},
- {"syz_test$missing_resource", 1000007},
- {"syz_test$opt0", 1000007},
- {"syz_test$opt1", 1000007},
- {"syz_test$opt2", 1000007},
- {"syz_test$recur0", 1000007},
- {"syz_test$recur1", 1000007},
- {"syz_test$recur2", 1000007},
- {"syz_test$regression0", 1000007},
- {"syz_test$res0", 1000007},
- {"syz_test$res1", 1000007},
- {"syz_test$struct", 1000007},
- {"syz_test$text_x86_16", 1000007},
- {"syz_test$text_x86_32", 1000007},
- {"syz_test$text_x86_64", 1000007},
- {"syz_test$text_x86_real", 1000007},
- {"syz_test$union0", 1000007},
- {"syz_test$union1", 1000007},
- {"syz_test$union2", 1000007},
- {"syz_test$vma0", 1000007},
+ {"syz_emit_ethernet", 1000000, (syscall_t)syz_emit_ethernet},
+ {"syz_extract_tcp_res", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_extract_tcp_res$synack", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_fuse_mount", 1000002, (syscall_t)syz_fuse_mount},
+ {"syz_fuseblk_mount", 1000003, (syscall_t)syz_fuseblk_mount},
+ {"syz_kvm_setup_cpu$arm64", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_kvm_setup_cpu$x86", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_open_dev$admmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$adsp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$amidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$audion", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dmmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dri", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dricontrol", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$drirender", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dspn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$evdev", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$floppy", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$ircomm", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$loop", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mice", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$midi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mouse", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$random", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sg", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndctrl", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndhw", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmc", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndseq", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndtimer", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tlk_device", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tun", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$urandom", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usb", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usbmon", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsa", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_pts", 1000006, (syscall_t)syz_open_pts},
+ {"syz_test", 1000007, (syscall_t)syz_test},
+ {"syz_test$align0", 1000007, (syscall_t)syz_test},
+ {"syz_test$align1", 1000007, (syscall_t)syz_test},
+ {"syz_test$align2", 1000007, (syscall_t)syz_test},
+ {"syz_test$align3", 1000007, (syscall_t)syz_test},
+ {"syz_test$align4", 1000007, (syscall_t)syz_test},
+ {"syz_test$align5", 1000007, (syscall_t)syz_test},
+ {"syz_test$align6", 1000007, (syscall_t)syz_test},
+ {"syz_test$array0", 1000007, (syscall_t)syz_test},
+ {"syz_test$array1", 1000007, (syscall_t)syz_test},
+ {"syz_test$array2", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf0", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf1", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_encode", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_icmp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$end0", 1000007, (syscall_t)syz_test},
+ {"syz_test$end1", 1000007, (syscall_t)syz_test},
+ {"syz_test$int", 1000007, (syscall_t)syz_test},
+ {"syz_test$length0", 1000007, (syscall_t)syz_test},
+ {"syz_test$length1", 1000007, (syscall_t)syz_test},
+ {"syz_test$length10", 1000007, (syscall_t)syz_test},
+ {"syz_test$length11", 1000007, (syscall_t)syz_test},
+ {"syz_test$length12", 1000007, (syscall_t)syz_test},
+ {"syz_test$length13", 1000007, (syscall_t)syz_test},
+ {"syz_test$length14", 1000007, (syscall_t)syz_test},
+ {"syz_test$length15", 1000007, (syscall_t)syz_test},
+ {"syz_test$length16", 1000007, (syscall_t)syz_test},
+ {"syz_test$length17", 1000007, (syscall_t)syz_test},
+ {"syz_test$length18", 1000007, (syscall_t)syz_test},
+ {"syz_test$length19", 1000007, (syscall_t)syz_test},
+ {"syz_test$length2", 1000007, (syscall_t)syz_test},
+ {"syz_test$length20", 1000007, (syscall_t)syz_test},
+ {"syz_test$length3", 1000007, (syscall_t)syz_test},
+ {"syz_test$length4", 1000007, (syscall_t)syz_test},
+ {"syz_test$length5", 1000007, (syscall_t)syz_test},
+ {"syz_test$length6", 1000007, (syscall_t)syz_test},
+ {"syz_test$length7", 1000007, (syscall_t)syz_test},
+ {"syz_test$length8", 1000007, (syscall_t)syz_test},
+ {"syz_test$length9", 1000007, (syscall_t)syz_test},
+ {"syz_test$missing_resource", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt0", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt1", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt2", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur0", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur1", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur2", 1000007, (syscall_t)syz_test},
+ {"syz_test$regression0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res1", 1000007, (syscall_t)syz_test},
+ {"syz_test$struct", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_16", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_32", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_64", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_real", 1000007, (syscall_t)syz_test},
+ {"syz_test$union0", 1000007, (syscall_t)syz_test},
+ {"syz_test$union1", 1000007, (syscall_t)syz_test},
+ {"syz_test$union2", 1000007, (syscall_t)syz_test},
+ {"syz_test$vma0", 1000007, (syscall_t)syz_test},
{"tee", 315},
{"tgkill", 270},
{"time", 13},
@@ -1515,7 +1511,8 @@ static call_t syscalls[] = {
#define __NR_syz_open_pts 1000006
#define __NR_syz_test 1000007
-static call_t syscalls[] = {
+unsigned syscall_count = 1542;
+call_t syscalls[] = {
{"accept", 43},
{"accept$alg", 43},
{"accept$ax25", 43},
@@ -2910,109 +2907,109 @@ static call_t syscalls[] = {
{"sysfs$3", 139},
{"sysinfo", 99},
{"syslog", 103},
- {"syz_emit_ethernet", 1000000},
- {"syz_extract_tcp_res", 1000001},
- {"syz_extract_tcp_res$synack", 1000001},
- {"syz_fuse_mount", 1000002},
- {"syz_fuseblk_mount", 1000003},
- {"syz_kvm_setup_cpu$arm64", 1000004},
- {"syz_kvm_setup_cpu$x86", 1000004},
- {"syz_open_dev$admmidi", 1000005},
- {"syz_open_dev$adsp", 1000005},
- {"syz_open_dev$amidi", 1000005},
- {"syz_open_dev$audion", 1000005},
- {"syz_open_dev$dmmidi", 1000005},
- {"syz_open_dev$dri", 1000005},
- {"syz_open_dev$dricontrol", 1000005},
- {"syz_open_dev$drirender", 1000005},
- {"syz_open_dev$dspn", 1000005},
- {"syz_open_dev$evdev", 1000005},
- {"syz_open_dev$floppy", 1000005},
- {"syz_open_dev$ircomm", 1000005},
- {"syz_open_dev$loop", 1000005},
- {"syz_open_dev$mice", 1000005},
- {"syz_open_dev$midi", 1000005},
- {"syz_open_dev$mouse", 1000005},
- {"syz_open_dev$random", 1000005},
- {"syz_open_dev$sg", 1000005},
- {"syz_open_dev$sndctrl", 1000005},
- {"syz_open_dev$sndhw", 1000005},
- {"syz_open_dev$sndmidi", 1000005},
- {"syz_open_dev$sndpcmc", 1000005},
- {"syz_open_dev$sndpcmp", 1000005},
- {"syz_open_dev$sndseq", 1000005},
- {"syz_open_dev$sndtimer", 1000005},
- {"syz_open_dev$tlk_device", 1000005},
- {"syz_open_dev$tun", 1000005},
- {"syz_open_dev$urandom", 1000005},
- {"syz_open_dev$usb", 1000005},
- {"syz_open_dev$usbmon", 1000005},
- {"syz_open_dev$vcsa", 1000005},
- {"syz_open_dev$vcsn", 1000005},
- {"syz_open_pts", 1000006},
- {"syz_test", 1000007},
- {"syz_test$align0", 1000007},
- {"syz_test$align1", 1000007},
- {"syz_test$align2", 1000007},
- {"syz_test$align3", 1000007},
- {"syz_test$align4", 1000007},
- {"syz_test$align5", 1000007},
- {"syz_test$align6", 1000007},
- {"syz_test$array0", 1000007},
- {"syz_test$array1", 1000007},
- {"syz_test$array2", 1000007},
- {"syz_test$bf0", 1000007},
- {"syz_test$bf1", 1000007},
- {"syz_test$csum_encode", 1000007},
- {"syz_test$csum_ipv4", 1000007},
- {"syz_test$csum_ipv4_tcp", 1000007},
- {"syz_test$csum_ipv4_udp", 1000007},
- {"syz_test$csum_ipv6_icmp", 1000007},
- {"syz_test$csum_ipv6_tcp", 1000007},
- {"syz_test$csum_ipv6_udp", 1000007},
- {"syz_test$end0", 1000007},
- {"syz_test$end1", 1000007},
- {"syz_test$int", 1000007},
- {"syz_test$length0", 1000007},
- {"syz_test$length1", 1000007},
- {"syz_test$length10", 1000007},
- {"syz_test$length11", 1000007},
- {"syz_test$length12", 1000007},
- {"syz_test$length13", 1000007},
- {"syz_test$length14", 1000007},
- {"syz_test$length15", 1000007},
- {"syz_test$length16", 1000007},
- {"syz_test$length17", 1000007},
- {"syz_test$length18", 1000007},
- {"syz_test$length19", 1000007},
- {"syz_test$length2", 1000007},
- {"syz_test$length20", 1000007},
- {"syz_test$length3", 1000007},
- {"syz_test$length4", 1000007},
- {"syz_test$length5", 1000007},
- {"syz_test$length6", 1000007},
- {"syz_test$length7", 1000007},
- {"syz_test$length8", 1000007},
- {"syz_test$length9", 1000007},
- {"syz_test$missing_resource", 1000007},
- {"syz_test$opt0", 1000007},
- {"syz_test$opt1", 1000007},
- {"syz_test$opt2", 1000007},
- {"syz_test$recur0", 1000007},
- {"syz_test$recur1", 1000007},
- {"syz_test$recur2", 1000007},
- {"syz_test$regression0", 1000007},
- {"syz_test$res0", 1000007},
- {"syz_test$res1", 1000007},
- {"syz_test$struct", 1000007},
- {"syz_test$text_x86_16", 1000007},
- {"syz_test$text_x86_32", 1000007},
- {"syz_test$text_x86_64", 1000007},
- {"syz_test$text_x86_real", 1000007},
- {"syz_test$union0", 1000007},
- {"syz_test$union1", 1000007},
- {"syz_test$union2", 1000007},
- {"syz_test$vma0", 1000007},
+ {"syz_emit_ethernet", 1000000, (syscall_t)syz_emit_ethernet},
+ {"syz_extract_tcp_res", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_extract_tcp_res$synack", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_fuse_mount", 1000002, (syscall_t)syz_fuse_mount},
+ {"syz_fuseblk_mount", 1000003, (syscall_t)syz_fuseblk_mount},
+ {"syz_kvm_setup_cpu$arm64", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_kvm_setup_cpu$x86", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_open_dev$admmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$adsp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$amidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$audion", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dmmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dri", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dricontrol", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$drirender", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dspn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$evdev", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$floppy", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$ircomm", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$loop", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mice", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$midi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mouse", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$random", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sg", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndctrl", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndhw", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmc", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndseq", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndtimer", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tlk_device", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tun", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$urandom", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usb", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usbmon", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsa", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_pts", 1000006, (syscall_t)syz_open_pts},
+ {"syz_test", 1000007, (syscall_t)syz_test},
+ {"syz_test$align0", 1000007, (syscall_t)syz_test},
+ {"syz_test$align1", 1000007, (syscall_t)syz_test},
+ {"syz_test$align2", 1000007, (syscall_t)syz_test},
+ {"syz_test$align3", 1000007, (syscall_t)syz_test},
+ {"syz_test$align4", 1000007, (syscall_t)syz_test},
+ {"syz_test$align5", 1000007, (syscall_t)syz_test},
+ {"syz_test$align6", 1000007, (syscall_t)syz_test},
+ {"syz_test$array0", 1000007, (syscall_t)syz_test},
+ {"syz_test$array1", 1000007, (syscall_t)syz_test},
+ {"syz_test$array2", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf0", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf1", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_encode", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_icmp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$end0", 1000007, (syscall_t)syz_test},
+ {"syz_test$end1", 1000007, (syscall_t)syz_test},
+ {"syz_test$int", 1000007, (syscall_t)syz_test},
+ {"syz_test$length0", 1000007, (syscall_t)syz_test},
+ {"syz_test$length1", 1000007, (syscall_t)syz_test},
+ {"syz_test$length10", 1000007, (syscall_t)syz_test},
+ {"syz_test$length11", 1000007, (syscall_t)syz_test},
+ {"syz_test$length12", 1000007, (syscall_t)syz_test},
+ {"syz_test$length13", 1000007, (syscall_t)syz_test},
+ {"syz_test$length14", 1000007, (syscall_t)syz_test},
+ {"syz_test$length15", 1000007, (syscall_t)syz_test},
+ {"syz_test$length16", 1000007, (syscall_t)syz_test},
+ {"syz_test$length17", 1000007, (syscall_t)syz_test},
+ {"syz_test$length18", 1000007, (syscall_t)syz_test},
+ {"syz_test$length19", 1000007, (syscall_t)syz_test},
+ {"syz_test$length2", 1000007, (syscall_t)syz_test},
+ {"syz_test$length20", 1000007, (syscall_t)syz_test},
+ {"syz_test$length3", 1000007, (syscall_t)syz_test},
+ {"syz_test$length4", 1000007, (syscall_t)syz_test},
+ {"syz_test$length5", 1000007, (syscall_t)syz_test},
+ {"syz_test$length6", 1000007, (syscall_t)syz_test},
+ {"syz_test$length7", 1000007, (syscall_t)syz_test},
+ {"syz_test$length8", 1000007, (syscall_t)syz_test},
+ {"syz_test$length9", 1000007, (syscall_t)syz_test},
+ {"syz_test$missing_resource", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt0", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt1", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt2", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur0", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur1", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur2", 1000007, (syscall_t)syz_test},
+ {"syz_test$regression0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res1", 1000007, (syscall_t)syz_test},
+ {"syz_test$struct", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_16", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_32", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_64", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_real", 1000007, (syscall_t)syz_test},
+ {"syz_test$union0", 1000007, (syscall_t)syz_test},
+ {"syz_test$union1", 1000007, (syscall_t)syz_test},
+ {"syz_test$union2", 1000007, (syscall_t)syz_test},
+ {"syz_test$vma0", 1000007, (syscall_t)syz_test},
{"tee", 276},
{"tgkill", 234},
{"time", 201},
@@ -3074,7 +3071,8 @@ static call_t syscalls[] = {
#define __NR_syz_open_pts 1000006
#define __NR_syz_test 1000007
-static call_t syscalls[] = {
+unsigned syscall_count = 1495;
+call_t syscalls[] = {
{"accept", 9437469},
{"accept$alg", 9437469},
{"accept$ax25", 9437469},
@@ -4422,109 +4420,109 @@ static call_t syscalls[] = {
{"sysfs$3", 9437319},
{"sysinfo", 9437300},
{"syslog", 9437287},
- {"syz_emit_ethernet", 1000000},
- {"syz_extract_tcp_res", 1000001},
- {"syz_extract_tcp_res$synack", 1000001},
- {"syz_fuse_mount", 1000002},
- {"syz_fuseblk_mount", 1000003},
- {"syz_kvm_setup_cpu$arm64", 1000004},
- {"syz_kvm_setup_cpu$x86", 1000004},
- {"syz_open_dev$admmidi", 1000005},
- {"syz_open_dev$adsp", 1000005},
- {"syz_open_dev$amidi", 1000005},
- {"syz_open_dev$audion", 1000005},
- {"syz_open_dev$dmmidi", 1000005},
- {"syz_open_dev$dri", 1000005},
- {"syz_open_dev$dricontrol", 1000005},
- {"syz_open_dev$drirender", 1000005},
- {"syz_open_dev$dspn", 1000005},
- {"syz_open_dev$evdev", 1000005},
- {"syz_open_dev$floppy", 1000005},
- {"syz_open_dev$ircomm", 1000005},
- {"syz_open_dev$loop", 1000005},
- {"syz_open_dev$mice", 1000005},
- {"syz_open_dev$midi", 1000005},
- {"syz_open_dev$mouse", 1000005},
- {"syz_open_dev$random", 1000005},
- {"syz_open_dev$sg", 1000005},
- {"syz_open_dev$sndctrl", 1000005},
- {"syz_open_dev$sndhw", 1000005},
- {"syz_open_dev$sndmidi", 1000005},
- {"syz_open_dev$sndpcmc", 1000005},
- {"syz_open_dev$sndpcmp", 1000005},
- {"syz_open_dev$sndseq", 1000005},
- {"syz_open_dev$sndtimer", 1000005},
- {"syz_open_dev$tlk_device", 1000005},
- {"syz_open_dev$tun", 1000005},
- {"syz_open_dev$urandom", 1000005},
- {"syz_open_dev$usb", 1000005},
- {"syz_open_dev$usbmon", 1000005},
- {"syz_open_dev$vcsa", 1000005},
- {"syz_open_dev$vcsn", 1000005},
- {"syz_open_pts", 1000006},
- {"syz_test", 1000007},
- {"syz_test$align0", 1000007},
- {"syz_test$align1", 1000007},
- {"syz_test$align2", 1000007},
- {"syz_test$align3", 1000007},
- {"syz_test$align4", 1000007},
- {"syz_test$align5", 1000007},
- {"syz_test$align6", 1000007},
- {"syz_test$array0", 1000007},
- {"syz_test$array1", 1000007},
- {"syz_test$array2", 1000007},
- {"syz_test$bf0", 1000007},
- {"syz_test$bf1", 1000007},
- {"syz_test$csum_encode", 1000007},
- {"syz_test$csum_ipv4", 1000007},
- {"syz_test$csum_ipv4_tcp", 1000007},
- {"syz_test$csum_ipv4_udp", 1000007},
- {"syz_test$csum_ipv6_icmp", 1000007},
- {"syz_test$csum_ipv6_tcp", 1000007},
- {"syz_test$csum_ipv6_udp", 1000007},
- {"syz_test$end0", 1000007},
- {"syz_test$end1", 1000007},
- {"syz_test$int", 1000007},
- {"syz_test$length0", 1000007},
- {"syz_test$length1", 1000007},
- {"syz_test$length10", 1000007},
- {"syz_test$length11", 1000007},
- {"syz_test$length12", 1000007},
- {"syz_test$length13", 1000007},
- {"syz_test$length14", 1000007},
- {"syz_test$length15", 1000007},
- {"syz_test$length16", 1000007},
- {"syz_test$length17", 1000007},
- {"syz_test$length18", 1000007},
- {"syz_test$length19", 1000007},
- {"syz_test$length2", 1000007},
- {"syz_test$length20", 1000007},
- {"syz_test$length3", 1000007},
- {"syz_test$length4", 1000007},
- {"syz_test$length5", 1000007},
- {"syz_test$length6", 1000007},
- {"syz_test$length7", 1000007},
- {"syz_test$length8", 1000007},
- {"syz_test$length9", 1000007},
- {"syz_test$missing_resource", 1000007},
- {"syz_test$opt0", 1000007},
- {"syz_test$opt1", 1000007},
- {"syz_test$opt2", 1000007},
- {"syz_test$recur0", 1000007},
- {"syz_test$recur1", 1000007},
- {"syz_test$recur2", 1000007},
- {"syz_test$regression0", 1000007},
- {"syz_test$res0", 1000007},
- {"syz_test$res1", 1000007},
- {"syz_test$struct", 1000007},
- {"syz_test$text_x86_16", 1000007},
- {"syz_test$text_x86_32", 1000007},
- {"syz_test$text_x86_64", 1000007},
- {"syz_test$text_x86_real", 1000007},
- {"syz_test$union0", 1000007},
- {"syz_test$union1", 1000007},
- {"syz_test$union2", 1000007},
- {"syz_test$vma0", 1000007},
+ {"syz_emit_ethernet", 1000000, (syscall_t)syz_emit_ethernet},
+ {"syz_extract_tcp_res", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_extract_tcp_res$synack", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_fuse_mount", 1000002, (syscall_t)syz_fuse_mount},
+ {"syz_fuseblk_mount", 1000003, (syscall_t)syz_fuseblk_mount},
+ {"syz_kvm_setup_cpu$arm64", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_kvm_setup_cpu$x86", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_open_dev$admmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$adsp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$amidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$audion", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dmmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dri", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dricontrol", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$drirender", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dspn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$evdev", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$floppy", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$ircomm", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$loop", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mice", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$midi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mouse", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$random", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sg", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndctrl", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndhw", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmc", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndseq", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndtimer", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tlk_device", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tun", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$urandom", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usb", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usbmon", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsa", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_pts", 1000006, (syscall_t)syz_open_pts},
+ {"syz_test", 1000007, (syscall_t)syz_test},
+ {"syz_test$align0", 1000007, (syscall_t)syz_test},
+ {"syz_test$align1", 1000007, (syscall_t)syz_test},
+ {"syz_test$align2", 1000007, (syscall_t)syz_test},
+ {"syz_test$align3", 1000007, (syscall_t)syz_test},
+ {"syz_test$align4", 1000007, (syscall_t)syz_test},
+ {"syz_test$align5", 1000007, (syscall_t)syz_test},
+ {"syz_test$align6", 1000007, (syscall_t)syz_test},
+ {"syz_test$array0", 1000007, (syscall_t)syz_test},
+ {"syz_test$array1", 1000007, (syscall_t)syz_test},
+ {"syz_test$array2", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf0", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf1", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_encode", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_icmp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$end0", 1000007, (syscall_t)syz_test},
+ {"syz_test$end1", 1000007, (syscall_t)syz_test},
+ {"syz_test$int", 1000007, (syscall_t)syz_test},
+ {"syz_test$length0", 1000007, (syscall_t)syz_test},
+ {"syz_test$length1", 1000007, (syscall_t)syz_test},
+ {"syz_test$length10", 1000007, (syscall_t)syz_test},
+ {"syz_test$length11", 1000007, (syscall_t)syz_test},
+ {"syz_test$length12", 1000007, (syscall_t)syz_test},
+ {"syz_test$length13", 1000007, (syscall_t)syz_test},
+ {"syz_test$length14", 1000007, (syscall_t)syz_test},
+ {"syz_test$length15", 1000007, (syscall_t)syz_test},
+ {"syz_test$length16", 1000007, (syscall_t)syz_test},
+ {"syz_test$length17", 1000007, (syscall_t)syz_test},
+ {"syz_test$length18", 1000007, (syscall_t)syz_test},
+ {"syz_test$length19", 1000007, (syscall_t)syz_test},
+ {"syz_test$length2", 1000007, (syscall_t)syz_test},
+ {"syz_test$length20", 1000007, (syscall_t)syz_test},
+ {"syz_test$length3", 1000007, (syscall_t)syz_test},
+ {"syz_test$length4", 1000007, (syscall_t)syz_test},
+ {"syz_test$length5", 1000007, (syscall_t)syz_test},
+ {"syz_test$length6", 1000007, (syscall_t)syz_test},
+ {"syz_test$length7", 1000007, (syscall_t)syz_test},
+ {"syz_test$length8", 1000007, (syscall_t)syz_test},
+ {"syz_test$length9", 1000007, (syscall_t)syz_test},
+ {"syz_test$missing_resource", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt0", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt1", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt2", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur0", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur1", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur2", 1000007, (syscall_t)syz_test},
+ {"syz_test$regression0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res1", 1000007, (syscall_t)syz_test},
+ {"syz_test$struct", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_16", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_32", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_64", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_real", 1000007, (syscall_t)syz_test},
+ {"syz_test$union0", 1000007, (syscall_t)syz_test},
+ {"syz_test$union1", 1000007, (syscall_t)syz_test},
+ {"syz_test$union2", 1000007, (syscall_t)syz_test},
+ {"syz_test$vma0", 1000007, (syscall_t)syz_test},
{"tee", 9437526},
{"tgkill", 9437452},
{"time", 9437197},
@@ -4586,7 +4584,8 @@ static call_t syscalls[] = {
#define __NR_syz_open_pts 1000006
#define __NR_syz_test 1000007
-static call_t syscalls[] = {
+unsigned syscall_count = 1470;
+call_t syscalls[] = {
{"accept", 202},
{"accept$alg", 202},
{"accept$ax25", 202},
@@ -5915,109 +5914,109 @@ static call_t syscalls[] = {
{"syncfs", 267},
{"sysinfo", 179},
{"syslog", 116},
- {"syz_emit_ethernet", 1000000},
- {"syz_extract_tcp_res", 1000001},
- {"syz_extract_tcp_res$synack", 1000001},
- {"syz_fuse_mount", 1000002},
- {"syz_fuseblk_mount", 1000003},
- {"syz_kvm_setup_cpu$arm64", 1000004},
- {"syz_kvm_setup_cpu$x86", 1000004},
- {"syz_open_dev$admmidi", 1000005},
- {"syz_open_dev$adsp", 1000005},
- {"syz_open_dev$amidi", 1000005},
- {"syz_open_dev$audion", 1000005},
- {"syz_open_dev$dmmidi", 1000005},
- {"syz_open_dev$dri", 1000005},
- {"syz_open_dev$dricontrol", 1000005},
- {"syz_open_dev$drirender", 1000005},
- {"syz_open_dev$dspn", 1000005},
- {"syz_open_dev$evdev", 1000005},
- {"syz_open_dev$floppy", 1000005},
- {"syz_open_dev$ircomm", 1000005},
- {"syz_open_dev$loop", 1000005},
- {"syz_open_dev$mice", 1000005},
- {"syz_open_dev$midi", 1000005},
- {"syz_open_dev$mouse", 1000005},
- {"syz_open_dev$random", 1000005},
- {"syz_open_dev$sg", 1000005},
- {"syz_open_dev$sndctrl", 1000005},
- {"syz_open_dev$sndhw", 1000005},
- {"syz_open_dev$sndmidi", 1000005},
- {"syz_open_dev$sndpcmc", 1000005},
- {"syz_open_dev$sndpcmp", 1000005},
- {"syz_open_dev$sndseq", 1000005},
- {"syz_open_dev$sndtimer", 1000005},
- {"syz_open_dev$tlk_device", 1000005},
- {"syz_open_dev$tun", 1000005},
- {"syz_open_dev$urandom", 1000005},
- {"syz_open_dev$usb", 1000005},
- {"syz_open_dev$usbmon", 1000005},
- {"syz_open_dev$vcsa", 1000005},
- {"syz_open_dev$vcsn", 1000005},
- {"syz_open_pts", 1000006},
- {"syz_test", 1000007},
- {"syz_test$align0", 1000007},
- {"syz_test$align1", 1000007},
- {"syz_test$align2", 1000007},
- {"syz_test$align3", 1000007},
- {"syz_test$align4", 1000007},
- {"syz_test$align5", 1000007},
- {"syz_test$align6", 1000007},
- {"syz_test$array0", 1000007},
- {"syz_test$array1", 1000007},
- {"syz_test$array2", 1000007},
- {"syz_test$bf0", 1000007},
- {"syz_test$bf1", 1000007},
- {"syz_test$csum_encode", 1000007},
- {"syz_test$csum_ipv4", 1000007},
- {"syz_test$csum_ipv4_tcp", 1000007},
- {"syz_test$csum_ipv4_udp", 1000007},
- {"syz_test$csum_ipv6_icmp", 1000007},
- {"syz_test$csum_ipv6_tcp", 1000007},
- {"syz_test$csum_ipv6_udp", 1000007},
- {"syz_test$end0", 1000007},
- {"syz_test$end1", 1000007},
- {"syz_test$int", 1000007},
- {"syz_test$length0", 1000007},
- {"syz_test$length1", 1000007},
- {"syz_test$length10", 1000007},
- {"syz_test$length11", 1000007},
- {"syz_test$length12", 1000007},
- {"syz_test$length13", 1000007},
- {"syz_test$length14", 1000007},
- {"syz_test$length15", 1000007},
- {"syz_test$length16", 1000007},
- {"syz_test$length17", 1000007},
- {"syz_test$length18", 1000007},
- {"syz_test$length19", 1000007},
- {"syz_test$length2", 1000007},
- {"syz_test$length20", 1000007},
- {"syz_test$length3", 1000007},
- {"syz_test$length4", 1000007},
- {"syz_test$length5", 1000007},
- {"syz_test$length6", 1000007},
- {"syz_test$length7", 1000007},
- {"syz_test$length8", 1000007},
- {"syz_test$length9", 1000007},
- {"syz_test$missing_resource", 1000007},
- {"syz_test$opt0", 1000007},
- {"syz_test$opt1", 1000007},
- {"syz_test$opt2", 1000007},
- {"syz_test$recur0", 1000007},
- {"syz_test$recur1", 1000007},
- {"syz_test$recur2", 1000007},
- {"syz_test$regression0", 1000007},
- {"syz_test$res0", 1000007},
- {"syz_test$res1", 1000007},
- {"syz_test$struct", 1000007},
- {"syz_test$text_x86_16", 1000007},
- {"syz_test$text_x86_32", 1000007},
- {"syz_test$text_x86_64", 1000007},
- {"syz_test$text_x86_real", 1000007},
- {"syz_test$union0", 1000007},
- {"syz_test$union1", 1000007},
- {"syz_test$union2", 1000007},
- {"syz_test$vma0", 1000007},
+ {"syz_emit_ethernet", 1000000, (syscall_t)syz_emit_ethernet},
+ {"syz_extract_tcp_res", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_extract_tcp_res$synack", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_fuse_mount", 1000002, (syscall_t)syz_fuse_mount},
+ {"syz_fuseblk_mount", 1000003, (syscall_t)syz_fuseblk_mount},
+ {"syz_kvm_setup_cpu$arm64", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_kvm_setup_cpu$x86", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_open_dev$admmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$adsp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$amidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$audion", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dmmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dri", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dricontrol", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$drirender", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dspn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$evdev", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$floppy", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$ircomm", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$loop", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mice", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$midi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mouse", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$random", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sg", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndctrl", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndhw", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmc", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndseq", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndtimer", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tlk_device", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tun", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$urandom", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usb", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usbmon", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsa", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_pts", 1000006, (syscall_t)syz_open_pts},
+ {"syz_test", 1000007, (syscall_t)syz_test},
+ {"syz_test$align0", 1000007, (syscall_t)syz_test},
+ {"syz_test$align1", 1000007, (syscall_t)syz_test},
+ {"syz_test$align2", 1000007, (syscall_t)syz_test},
+ {"syz_test$align3", 1000007, (syscall_t)syz_test},
+ {"syz_test$align4", 1000007, (syscall_t)syz_test},
+ {"syz_test$align5", 1000007, (syscall_t)syz_test},
+ {"syz_test$align6", 1000007, (syscall_t)syz_test},
+ {"syz_test$array0", 1000007, (syscall_t)syz_test},
+ {"syz_test$array1", 1000007, (syscall_t)syz_test},
+ {"syz_test$array2", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf0", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf1", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_encode", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_icmp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$end0", 1000007, (syscall_t)syz_test},
+ {"syz_test$end1", 1000007, (syscall_t)syz_test},
+ {"syz_test$int", 1000007, (syscall_t)syz_test},
+ {"syz_test$length0", 1000007, (syscall_t)syz_test},
+ {"syz_test$length1", 1000007, (syscall_t)syz_test},
+ {"syz_test$length10", 1000007, (syscall_t)syz_test},
+ {"syz_test$length11", 1000007, (syscall_t)syz_test},
+ {"syz_test$length12", 1000007, (syscall_t)syz_test},
+ {"syz_test$length13", 1000007, (syscall_t)syz_test},
+ {"syz_test$length14", 1000007, (syscall_t)syz_test},
+ {"syz_test$length15", 1000007, (syscall_t)syz_test},
+ {"syz_test$length16", 1000007, (syscall_t)syz_test},
+ {"syz_test$length17", 1000007, (syscall_t)syz_test},
+ {"syz_test$length18", 1000007, (syscall_t)syz_test},
+ {"syz_test$length19", 1000007, (syscall_t)syz_test},
+ {"syz_test$length2", 1000007, (syscall_t)syz_test},
+ {"syz_test$length20", 1000007, (syscall_t)syz_test},
+ {"syz_test$length3", 1000007, (syscall_t)syz_test},
+ {"syz_test$length4", 1000007, (syscall_t)syz_test},
+ {"syz_test$length5", 1000007, (syscall_t)syz_test},
+ {"syz_test$length6", 1000007, (syscall_t)syz_test},
+ {"syz_test$length7", 1000007, (syscall_t)syz_test},
+ {"syz_test$length8", 1000007, (syscall_t)syz_test},
+ {"syz_test$length9", 1000007, (syscall_t)syz_test},
+ {"syz_test$missing_resource", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt0", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt1", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt2", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur0", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur1", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur2", 1000007, (syscall_t)syz_test},
+ {"syz_test$regression0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res1", 1000007, (syscall_t)syz_test},
+ {"syz_test$struct", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_16", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_32", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_64", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_real", 1000007, (syscall_t)syz_test},
+ {"syz_test$union0", 1000007, (syscall_t)syz_test},
+ {"syz_test$union1", 1000007, (syscall_t)syz_test},
+ {"syz_test$union2", 1000007, (syscall_t)syz_test},
+ {"syz_test$vma0", 1000007, (syscall_t)syz_test},
{"tee", 77},
{"tgkill", 131},
{"timer_create", 107},
@@ -6073,7 +6072,8 @@ static call_t syscalls[] = {
#define __NR_syz_open_pts 1000006
#define __NR_syz_test 1000007
-static call_t syscalls[] = {
+unsigned syscall_count = 1451;
+call_t syscalls[] = {
{"accept", 330},
{"accept$alg", 330},
{"accept$ax25", 330},
@@ -7377,109 +7377,109 @@ static call_t syscalls[] = {
{"sysfs$3", 135},
{"sysinfo", 116},
{"syslog", 103},
- {"syz_emit_ethernet", 1000000},
- {"syz_extract_tcp_res", 1000001},
- {"syz_extract_tcp_res$synack", 1000001},
- {"syz_fuse_mount", 1000002},
- {"syz_fuseblk_mount", 1000003},
- {"syz_kvm_setup_cpu$arm64", 1000004},
- {"syz_kvm_setup_cpu$x86", 1000004},
- {"syz_open_dev$admmidi", 1000005},
- {"syz_open_dev$adsp", 1000005},
- {"syz_open_dev$amidi", 1000005},
- {"syz_open_dev$audion", 1000005},
- {"syz_open_dev$dmmidi", 1000005},
- {"syz_open_dev$dri", 1000005},
- {"syz_open_dev$dricontrol", 1000005},
- {"syz_open_dev$drirender", 1000005},
- {"syz_open_dev$dspn", 1000005},
- {"syz_open_dev$evdev", 1000005},
- {"syz_open_dev$floppy", 1000005},
- {"syz_open_dev$ircomm", 1000005},
- {"syz_open_dev$loop", 1000005},
- {"syz_open_dev$mice", 1000005},
- {"syz_open_dev$midi", 1000005},
- {"syz_open_dev$mouse", 1000005},
- {"syz_open_dev$random", 1000005},
- {"syz_open_dev$sg", 1000005},
- {"syz_open_dev$sndctrl", 1000005},
- {"syz_open_dev$sndhw", 1000005},
- {"syz_open_dev$sndmidi", 1000005},
- {"syz_open_dev$sndpcmc", 1000005},
- {"syz_open_dev$sndpcmp", 1000005},
- {"syz_open_dev$sndseq", 1000005},
- {"syz_open_dev$sndtimer", 1000005},
- {"syz_open_dev$tlk_device", 1000005},
- {"syz_open_dev$tun", 1000005},
- {"syz_open_dev$urandom", 1000005},
- {"syz_open_dev$usb", 1000005},
- {"syz_open_dev$usbmon", 1000005},
- {"syz_open_dev$vcsa", 1000005},
- {"syz_open_dev$vcsn", 1000005},
- {"syz_open_pts", 1000006},
- {"syz_test", 1000007},
- {"syz_test$align0", 1000007},
- {"syz_test$align1", 1000007},
- {"syz_test$align2", 1000007},
- {"syz_test$align3", 1000007},
- {"syz_test$align4", 1000007},
- {"syz_test$align5", 1000007},
- {"syz_test$align6", 1000007},
- {"syz_test$array0", 1000007},
- {"syz_test$array1", 1000007},
- {"syz_test$array2", 1000007},
- {"syz_test$bf0", 1000007},
- {"syz_test$bf1", 1000007},
- {"syz_test$csum_encode", 1000007},
- {"syz_test$csum_ipv4", 1000007},
- {"syz_test$csum_ipv4_tcp", 1000007},
- {"syz_test$csum_ipv4_udp", 1000007},
- {"syz_test$csum_ipv6_icmp", 1000007},
- {"syz_test$csum_ipv6_tcp", 1000007},
- {"syz_test$csum_ipv6_udp", 1000007},
- {"syz_test$end0", 1000007},
- {"syz_test$end1", 1000007},
- {"syz_test$int", 1000007},
- {"syz_test$length0", 1000007},
- {"syz_test$length1", 1000007},
- {"syz_test$length10", 1000007},
- {"syz_test$length11", 1000007},
- {"syz_test$length12", 1000007},
- {"syz_test$length13", 1000007},
- {"syz_test$length14", 1000007},
- {"syz_test$length15", 1000007},
- {"syz_test$length16", 1000007},
- {"syz_test$length17", 1000007},
- {"syz_test$length18", 1000007},
- {"syz_test$length19", 1000007},
- {"syz_test$length2", 1000007},
- {"syz_test$length20", 1000007},
- {"syz_test$length3", 1000007},
- {"syz_test$length4", 1000007},
- {"syz_test$length5", 1000007},
- {"syz_test$length6", 1000007},
- {"syz_test$length7", 1000007},
- {"syz_test$length8", 1000007},
- {"syz_test$length9", 1000007},
- {"syz_test$missing_resource", 1000007},
- {"syz_test$opt0", 1000007},
- {"syz_test$opt1", 1000007},
- {"syz_test$opt2", 1000007},
- {"syz_test$recur0", 1000007},
- {"syz_test$recur1", 1000007},
- {"syz_test$recur2", 1000007},
- {"syz_test$regression0", 1000007},
- {"syz_test$res0", 1000007},
- {"syz_test$res1", 1000007},
- {"syz_test$struct", 1000007},
- {"syz_test$text_x86_16", 1000007},
- {"syz_test$text_x86_32", 1000007},
- {"syz_test$text_x86_64", 1000007},
- {"syz_test$text_x86_real", 1000007},
- {"syz_test$union0", 1000007},
- {"syz_test$union1", 1000007},
- {"syz_test$union2", 1000007},
- {"syz_test$vma0", 1000007},
+ {"syz_emit_ethernet", 1000000, (syscall_t)syz_emit_ethernet},
+ {"syz_extract_tcp_res", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_extract_tcp_res$synack", 1000001, (syscall_t)syz_extract_tcp_res},
+ {"syz_fuse_mount", 1000002, (syscall_t)syz_fuse_mount},
+ {"syz_fuseblk_mount", 1000003, (syscall_t)syz_fuseblk_mount},
+ {"syz_kvm_setup_cpu$arm64", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_kvm_setup_cpu$x86", 1000004, (syscall_t)syz_kvm_setup_cpu},
+ {"syz_open_dev$admmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$adsp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$amidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$audion", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dmmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dri", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dricontrol", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$drirender", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$dspn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$evdev", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$floppy", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$ircomm", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$loop", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mice", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$midi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$mouse", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$random", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sg", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndctrl", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndhw", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndmidi", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmc", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndpcmp", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndseq", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$sndtimer", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tlk_device", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$tun", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$urandom", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usb", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$usbmon", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsa", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_dev$vcsn", 1000005, (syscall_t)syz_open_dev},
+ {"syz_open_pts", 1000006, (syscall_t)syz_open_pts},
+ {"syz_test", 1000007, (syscall_t)syz_test},
+ {"syz_test$align0", 1000007, (syscall_t)syz_test},
+ {"syz_test$align1", 1000007, (syscall_t)syz_test},
+ {"syz_test$align2", 1000007, (syscall_t)syz_test},
+ {"syz_test$align3", 1000007, (syscall_t)syz_test},
+ {"syz_test$align4", 1000007, (syscall_t)syz_test},
+ {"syz_test$align5", 1000007, (syscall_t)syz_test},
+ {"syz_test$align6", 1000007, (syscall_t)syz_test},
+ {"syz_test$array0", 1000007, (syscall_t)syz_test},
+ {"syz_test$array1", 1000007, (syscall_t)syz_test},
+ {"syz_test$array2", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf0", 1000007, (syscall_t)syz_test},
+ {"syz_test$bf1", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_encode", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv4_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_icmp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_tcp", 1000007, (syscall_t)syz_test},
+ {"syz_test$csum_ipv6_udp", 1000007, (syscall_t)syz_test},
+ {"syz_test$end0", 1000007, (syscall_t)syz_test},
+ {"syz_test$end1", 1000007, (syscall_t)syz_test},
+ {"syz_test$int", 1000007, (syscall_t)syz_test},
+ {"syz_test$length0", 1000007, (syscall_t)syz_test},
+ {"syz_test$length1", 1000007, (syscall_t)syz_test},
+ {"syz_test$length10", 1000007, (syscall_t)syz_test},
+ {"syz_test$length11", 1000007, (syscall_t)syz_test},
+ {"syz_test$length12", 1000007, (syscall_t)syz_test},
+ {"syz_test$length13", 1000007, (syscall_t)syz_test},
+ {"syz_test$length14", 1000007, (syscall_t)syz_test},
+ {"syz_test$length15", 1000007, (syscall_t)syz_test},
+ {"syz_test$length16", 1000007, (syscall_t)syz_test},
+ {"syz_test$length17", 1000007, (syscall_t)syz_test},
+ {"syz_test$length18", 1000007, (syscall_t)syz_test},
+ {"syz_test$length19", 1000007, (syscall_t)syz_test},
+ {"syz_test$length2", 1000007, (syscall_t)syz_test},
+ {"syz_test$length20", 1000007, (syscall_t)syz_test},
+ {"syz_test$length3", 1000007, (syscall_t)syz_test},
+ {"syz_test$length4", 1000007, (syscall_t)syz_test},
+ {"syz_test$length5", 1000007, (syscall_t)syz_test},
+ {"syz_test$length6", 1000007, (syscall_t)syz_test},
+ {"syz_test$length7", 1000007, (syscall_t)syz_test},
+ {"syz_test$length8", 1000007, (syscall_t)syz_test},
+ {"syz_test$length9", 1000007, (syscall_t)syz_test},
+ {"syz_test$missing_resource", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt0", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt1", 1000007, (syscall_t)syz_test},
+ {"syz_test$opt2", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur0", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur1", 1000007, (syscall_t)syz_test},
+ {"syz_test$recur2", 1000007, (syscall_t)syz_test},
+ {"syz_test$regression0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res0", 1000007, (syscall_t)syz_test},
+ {"syz_test$res1", 1000007, (syscall_t)syz_test},
+ {"syz_test$struct", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_16", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_32", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_64", 1000007, (syscall_t)syz_test},
+ {"syz_test$text_x86_real", 1000007, (syscall_t)syz_test},
+ {"syz_test$union0", 1000007, (syscall_t)syz_test},
+ {"syz_test$union1", 1000007, (syscall_t)syz_test},
+ {"syz_test$union2", 1000007, (syscall_t)syz_test},
+ {"syz_test$vma0", 1000007, (syscall_t)syz_test},
{"tee", 284},
{"tgkill", 250},
{"time", 13},
diff --git a/executor/test_executor_linux.cc b/executor/test_executor_linux.cc
index 8bbd56910..5ba8d91ca 100644
--- a/executor/test_executor_linux.cc
+++ b/executor/test_executor_linux.cc
@@ -1,10 +1,10 @@
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-#include "syscalls_linux.h"
-
#define SYZ_EXECUTOR
-#include "common.h"
+#include "common_linux.h"
+
+#include "syscalls_linux.h"
#include <sys/utsname.h>