aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/csource
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-05-08 12:24:46 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-05-08 12:26:59 +0000
commit4dbd403fd0978b91ffe3bb2f2a749511591644dd (patch)
treea43a92648849d5127c4165b744e05e38c90bf9ee /pkg/csource
parentdc488c459880e3f3af557dc336697138ecb8228b (diff)
pkg/csource: replace go:generate with go:embed
go:embed is a more modern way to do this and it does not require a special Makefile step. Since go:embed cannot use paths that contains "..", the actual embeding is moved to executor package.
Diffstat (limited to 'pkg/csource')
-rw-r--r--pkg/csource/common.go3
-rw-r--r--pkg/csource/csource_test.go3
-rw-r--r--pkg/csource/gen.go88
-rw-r--r--pkg/csource/generated.go12736
4 files changed, 4 insertions, 12826 deletions
diff --git a/pkg/csource/common.go b/pkg/csource/common.go
index 2d62f0707..600ac43b6 100644
--- a/pkg/csource/common.go
+++ b/pkg/csource/common.go
@@ -13,6 +13,7 @@ import (
"sort"
"strings"
+ "github.com/google/syzkaller/executor"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
@@ -35,7 +36,7 @@ func createCommonHeader(p, mmapProg *prog.Prog, replacements map[string]string,
for _, def := range defines {
cmd.Args = append(cmd.Args, "-D"+def)
}
- cmd.Stdin = strings.NewReader(commonHeader)
+ cmd.Stdin = bytes.NewReader(executor.CommonHeader)
stderr := new(bytes.Buffer)
stdout := new(bytes.Buffer)
cmd.Stderr = stderr
diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go
index 8b4d83296..86f18af39 100644
--- a/pkg/csource/csource_test.go
+++ b/pkg/csource/csource_test.go
@@ -13,6 +13,7 @@ import (
"sync/atomic"
"testing"
+ "github.com/google/syzkaller/executor"
"github.com/google/syzkaller/pkg/testutil"
"github.com/google/syzkaller/prog"
_ "github.com/google/syzkaller/sys"
@@ -163,7 +164,7 @@ func TestExecutorMacros(t *testing.T) {
expected["SYZ_HAVE_RESET_LOOP"] = true
expected["SYZ_HAVE_SETUP_TEST"] = true
expected["SYZ_TEST_COMMON_EXT_EXAMPLE"] = true
- macros := regexp.MustCompile("SYZ_[A-Za-z0-9_]+").FindAllString(commonHeader, -1)
+ macros := regexp.MustCompile("SYZ_[A-Za-z0-9_]+").FindAllString(string(executor.CommonHeader), -1)
for _, macro := range macros {
if strings.HasPrefix(macro, "SYZ_HAVE_") {
continue
diff --git a/pkg/csource/gen.go b/pkg/csource/gen.go
deleted file mode 100644
index 7faf1ddaa..000000000
--- a/pkg/csource/gen.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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.
-
-//go:build ignore
-
-package main
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "regexp"
-
- "github.com/google/syzkaller/pkg/tool"
-)
-
-func main() {
- out, err := os.Create("generated.go")
- if err != nil {
- tool.Fail(err)
- }
- defer out.Close()
- data, err := ioutil.ReadFile("../../executor/common.h")
- if err != nil {
- tool.Fail(err)
- }
- executorFilenames := []string{
- "common_linux.h",
- "common_bsd.h",
- "common_openbsd.h",
- "common_fuchsia.h",
- "common_windows.h",
- "common_test.h",
- "common_kvm_amd64.h",
- "common_kvm_arm64.h",
- "common_kvm_ppc64.h",
- "common_usb_linux.h",
- "common_usb_netbsd.h",
- "common_usb.h",
- "common_ext.h",
- "android/android_seccomp.h",
- "kvm.h",
- "kvm_amd64.S.h",
- "kvm_ppc64le.S.h",
- "common_zlib.h",
- }
- data = replaceIncludes(executorFilenames, "../../executor/", data)
- androidFilenames := []string{
- "arm64_app_policy.h",
- "arm_app_policy.h",
- "x86_64_app_policy.h",
- "x86_app_policy.h",
- "arm64_system_policy.h",
- "arm_system_policy.h",
- "x86_64_system_policy.h",
- "x86_system_policy.h",
- }
- data = replaceIncludes(androidFilenames, "../../executor/android/", data)
- // Remove `//` comments, but keep lines which start with `//%`.
- for _, remove := range []string{
- "(\n|^)\\s*//$",
- "(\n|^)\\s*//[^%].*",
- "\\s*//$",
- "\\s*//[^%].*",
- } {
- data = regexp.MustCompile(remove).ReplaceAll(data, nil)
- }
- fmt.Fprintf(out, "// Code generated by gen.go from executor/*.h. DO NOT EDIT.\n\n")
- fmt.Fprintf(out, "package csource\n\nvar commonHeader = `\n")
- out.Write(data)
- fmt.Fprintf(out, "`\n")
-}
-
-func replaceIncludes(filenames []string, location string, data []byte) []byte {
- for _, include := range filenames {
- contents, err := ioutil.ReadFile(location + include)
- if err != nil {
- tool.Fail(err)
- }
- replace := []byte("#include \"" + include + "\"")
- if bytes.Index(data, replace) == -1 {
- tool.Failf("can't find %v include", include)
- }
- data = bytes.Replace(data, replace, contents, -1)
- }
- return data
-}
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
deleted file mode 100644
index fd5e1d552..000000000
--- a/pkg/csource/generated.go
+++ /dev/null
@@ -1,12736 +0,0 @@
-// Code generated by gen.go from executor/*.h. DO NOT EDIT.
-
-package csource
-
-var commonHeader = `
-
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#if GOOS_freebsd || GOOS_test && HOSTGOOS_freebsd
-#include <sys/endian.h>
-#elif GOOS_darwin
-#include <libkern/OSByteOrder.h>
-#define htobe16(x) OSSwapHostToBigInt16(x)
-#define htobe32(x) OSSwapHostToBigInt32(x)
-#define htobe64(x) OSSwapHostToBigInt64(x)
-#define le16toh(x) OSSwapLittleToHostInt16(x)
-#define htole16(x) OSSwapHostToLittleInt16(x)
-#elif GOOS_windows
-#define htobe16 _byteswap_ushort
-#define htobe32 _byteswap_ulong
-#define htobe64 _byteswap_uint64
-#define le16toh(x) x
-#define htole16(x) x
-typedef signed int ssize_t;
-#else
-#include <endian.h>
-#endif
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if SYZ_TRACE
-#include <errno.h>
-#endif
-
-#if !SYZ_EXECUTOR
-/*{{{SYSCALL_DEFINES}}}*/
-#endif
-
-#if SYZ_EXECUTOR && !GOOS_linux
-#if !GOOS_windows
-#include <unistd.h>
-#endif
-NORETURN void doexit(int status)
-{
- _exit(status);
- for (;;) {
- }
-}
-#if !GOOS_fuchsia
-NORETURN void doexit_thread(int status)
-{
- doexit(status);
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS || \
- SYZ_NET_DEVICES || __NR_syz_mount_image || __NR_syz_read_part_table || \
- __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usbip_server_init || \
- (GOOS_freebsd || GOOS_darwin || GOOS_openbsd || GOOS_netbsd) && SYZ_NET_INJECTION
-static unsigned long long procid;
-#endif
-
-#if !GOOS_fuchsia && !GOOS_windows
-#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
-#include <setjmp.h>
-#include <signal.h>
-#include <string.h>
-
-#if GOOS_linux
-#include <sys/syscall.h>
-#endif
-
-static __thread int clone_ongoing;
-static __thread int skip_segv;
-static __thread jmp_buf segv_env;
-
-static void segv_handler(int sig, siginfo_t* info, void* ctx)
-{
-
- if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
- doexit_thread(sig);
- }
-
- uintptr_t addr = (uintptr_t)info->si_addr;
- const uintptr_t prog_start = 1 << 20;
- const uintptr_t prog_end = 100 << 20;
- int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
- int valid = addr < prog_start || addr > prog_end;
-#if GOOS_freebsd || (GOOS_test && HOSTGOOS_freebsd)
- if (sig == SIGBUS)
- valid = 1;
-#endif
- if (skip && valid) {
- debug("SIGSEGV on %p, skipping\n", (void*)addr);
- _longjmp(segv_env, 1);
- }
- debug("SIGSEGV on %p, exiting\n", (void*)addr);
- doexit(sig);
-}
-
-static void install_segv_handler(void)
-{
- struct sigaction sa;
-#if GOOS_linux
- 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);
-#endif
- 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(...) \
- ({ \
- int ok = 1; \
- __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- if (_setjmp(segv_env) == 0) { \
- __VA_ARGS__; \
- } else \
- ok = 0; \
- __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- ok; \
- })
-#endif
-#endif
-
-#if !GOOS_linux
-#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-static void kill_and_wait(int pid, int* status)
-{
- kill(pid, SIGKILL);
- while (waitpid(-1, status, 0) != pid) {
- }
-}
-#endif
-#endif
-
-#if !GOOS_windows
-#if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER || \
- __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_sleep_ms || \
- __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write || \
- __NR_syz_usb_disconnect
-static void sleep_ms(uint64 ms)
-{
- usleep(ms * 1000);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER || \
- SYZ_LEAK
-#include <time.h>
-
-static uint64 current_time_ms(void)
-{
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts))
- fail("clock_gettime failed");
- return (uint64)ts.tv_sec * 1000 + (uint64)ts.tv_nsec / 1000000;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_ANDROID || SYZ_USE_TMP_DIR
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static void use_temporary_dir(void)
-{
-#if SYZ_SANDBOX_ANDROID
- char tmpdir_template[] = "/data/local/tmp/syzkaller.XXXXXX";
-#elif GOOS_fuchsia
- char tmpdir_template[] = "/tmp/syzkaller.XXXXXX";
-#else
- char tmpdir_template[] = "./syzkaller.XXXXXX";
-#endif
- 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
-#endif
-
-#if GOOS_netbsd || GOOS_freebsd || GOOS_darwin || GOOS_openbsd || GOOS_test
-#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER && (SYZ_EXECUTOR || SYZ_USE_TMP_DIR)
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#if GOOS_freebsd
-static void reset_flags(const char* filename)
-{
- struct stat st;
- if (lstat(filename, &st))
- exitf("lstat(%s) failed", filename);
- st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | SF_APPEND | UF_APPEND);
- if (lchflags(filename, st.st_flags))
- exitf("lchflags(%s) failed", filename);
-}
-#endif
-static void __attribute__((noinline)) remove_dir(const char* dir)
-{
- DIR* dp = opendir(dir);
- if (dp == NULL) {
- if (errno == EACCES) {
- if (rmdir(dir))
- exitf("rmdir(%s) failed", dir);
- return;
- }
- exitf("opendir(%s) failed", dir);
- }
- struct dirent* ep = 0;
- 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;
- }
- if (unlink(filename)) {
-#if GOOS_freebsd
- if (errno == EPERM) {
- reset_flags(filename);
- reset_flags(dir);
- if (unlink(filename) == 0)
- continue;
- }
-#endif
- exitf("unlink(%s) failed", filename);
- }
- }
- closedir(dp);
- while (rmdir(dir)) {
-#if GOOS_freebsd
- if (errno == EPERM) {
- reset_flags(dir);
- if (rmdir(dir) == 0)
- break;
- }
-#endif
- exitf("rmdir(%s) failed", dir);
- }
-}
-#endif
-#endif
-
-#if !GOOS_linux && !GOOS_netbsd
-#if SYZ_EXECUTOR || SYZ_FAULT
-static int inject_fault(int nth)
-{
- return 0;
-}
-#endif
-
-#if SYZ_FAULT
-static void setup_fault()
-{
-}
-#endif
-
-#if SYZ_EXECUTOR
-static int fault_injected(int fail_fd)
-{
- return 0;
-}
-#endif
-#endif
-
-#if !GOOS_windows
-#if SYZ_EXECUTOR || SYZ_THREADED
-#include <errno.h>
-#include <pthread.h>
-
-static void thread_start(void* (*fn)(void*), void* arg)
-{
- pthread_t th;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, 128 << 10);
- int i = 0;
- for (; i < 100; i++) {
- if (pthread_create(&th, &attr, fn, arg) == 0) {
- pthread_attr_destroy(&attr);
- return;
- }
- if (errno == EAGAIN) {
- usleep(50);
- continue;
- }
- break;
- }
- exitf("pthread_create failed");
-}
-
-#endif
-#endif
-
-#if GOOS_freebsd || GOOS_darwin || GOOS_netbsd || GOOS_openbsd || GOOS_test
-#if SYZ_EXECUTOR || SYZ_THREADED
-
-#include <pthread.h>
-#include <time.h>
-
-typedef struct {
- pthread_mutex_t mu;
- pthread_cond_t cv;
- int state;
-} event_t;
-
-static void event_init(event_t* ev)
-{
- if (pthread_mutex_init(&ev->mu, 0))
- exitf("pthread_mutex_init failed");
- if (pthread_cond_init(&ev->cv, 0))
- exitf("pthread_cond_init failed");
- ev->state = 0;
-}
-
-static void event_reset(event_t* ev)
-{
- ev->state = 0;
-}
-
-static void event_set(event_t* ev)
-{
- pthread_mutex_lock(&ev->mu);
- if (ev->state)
- exitf("event already set");
- ev->state = 1;
- pthread_mutex_unlock(&ev->mu);
- pthread_cond_broadcast(&ev->cv);
-}
-
-static 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);
-}
-
-static int event_isset(event_t* ev)
-{
- pthread_mutex_lock(&ev->mu);
- int res = ev->state;
- pthread_mutex_unlock(&ev->mu);
- return res;
-}
-
-static int event_timedwait(event_t* ev, uint64 timeout)
-{
- uint64 start = current_time_ms();
- uint64 now = start;
- pthread_mutex_lock(&ev->mu);
- for (;;) {
- if (ev->state)
- break;
- uint64 remain = timeout - (now - start);
- struct timespec ts;
- ts.tv_sec = remain / 1000;
- ts.tv_nsec = (remain % 1000) * 1000 * 1000;
- pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
- now = current_time_ms();
- if (now - start > timeout)
- break;
- }
- int res = ev->state;
- pthread_mutex_unlock(&ev->mu);
- return res;
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_USE_BITMASKS
-#define BITMASK(bf_off, bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
-#define STORE_BY_BITMASK(type, htobe, addr, val, bf_off, bf_len) \
- *(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | \
- (((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))
-#endif
-
-#if SYZ_EXECUTOR || SYZ_USE_CHECKSUMS
-struct csum_inet {
- uint32 acc;
-};
-
-static void csum_inet_init(struct csum_inet* csum)
-{
- csum->acc = 0;
-}
-
-static void csum_inet_update(struct csum_inet* csum, const uint8* data, size_t length)
-{
- if (length == 0)
- return;
-
- size_t i = 0;
- for (; i < length - 1; i += 2)
- csum->acc += *(uint16*)&data[i];
-
- if (length & 1)
- csum->acc += le16toh((uint16)data[length - 1]);
-
- while (csum->acc > 0xffff)
- csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16);
-}
-
-static uint16 csum_inet_digest(struct csum_inet* csum)
-{
- return ~csum->acc;
-}
-#endif
-
-#if GOOS_freebsd || GOOS_darwin || GOOS_netbsd
-
-#include <unistd.h>
-
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/syscall.h>
-
-#if GOOS_netbsd
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_disconnect
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbhid.h>
-#include <dev/usb/vhci.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-struct usb_endpoint_descriptor {
- uint8 bLength;
- uint8 bDescriptorType;
- uint8 bEndpointAddress;
- uint8 bmAttributes;
- uint16 wMaxPacketSize;
- uint8 bInterval;
- uint8 bRefresh;
- uint8 bSynchAddress;
-} __attribute__((packed));
-
-struct usb_device_descriptor {
- uint8 bLength;
- uint8 bDescriptorType;
- uint16 bcdUSB;
- uint8 bDeviceClass;
- uint8 bDeviceSubClass;
- uint8 bDeviceProtocol;
- uint8 bMaxPacketSize0;
- uint16 idVendor;
- uint16 idProduct;
- uint16 bcdDevice;
- uint8 iManufacturer;
- uint8 iProduct;
- uint8 iSerialNumber;
- uint8 bNumConfigurations;
-} __attribute__((packed));
-
-struct usb_config_descriptor {
- uint8 bLength;
- uint8 bDescriptorType;
-
- uint16 wTotalLength;
- uint8 bNumInterfaces;
- uint8 bConfigurationValue;
- uint8 iConfiguration;
- uint8 bmAttributes;
- uint8 bMaxPower;
-} __attribute__((packed));
-
-struct usb_interface_descriptor {
- uint8 bLength;
- uint8 bDescriptorType;
- uint8 bInterfaceNumber;
- uint8 bAlternateSetting;
- uint8 bNumEndpoints;
- uint8 bInterfaceClass;
- uint8 bInterfaceSubClass;
- uint8 bInterfaceProtocol;
- uint8 iInterface;
-} __attribute__((packed));
-
-struct usb_ctrlrequest {
- uint8 bRequestType;
- uint8 bRequest;
- uint16 wValue;
- uint16 wIndex;
- uint16 wLength;
-} __attribute__((packed));
-
-struct usb_qualifier_descriptor {
- uint8 bLength;
- uint8 bDescriptorType;
- uint16 bcdUSB;
- uint8 bDeviceClass;
- uint8 bDeviceSubClass;
- uint8 bDeviceProtocol;
- uint8 bMaxPacketSize0;
- uint8 bNumConfigurations;
- uint8 bRESERVED;
-} __attribute__((packed));
-
-#define USB_TYPE_MASK (0x03 << 5)
-#define USB_TYPE_STANDARD (0x00 << 5)
-#define USB_TYPE_CLASS (0x01 << 5)
-#define USB_TYPE_VENDOR (0x02 << 5)
-#define USB_TYPE_RESERVED (0x03 << 5)
-
-#define USB_DT_DEVICE 0x01
-#define USB_DT_CONFIG 0x02
-#define USB_DT_STRING 0x03
-#define USB_DT_INTERFACE 0x04
-#define USB_DT_ENDPOINT 0x05
-#define USB_DT_DEVICE_QUALIFIER 0x06
-#define USB_DT_OTHER_SPEED_CONFIG 0x07
-#define USB_DT_INTERFACE_POWER 0x08
-#define USB_DT_OTG 0x09
-#define USB_DT_DEBUG 0x0a
-#define USB_DT_INTERFACE_ASSOCIATION 0x0b
-#define USB_DT_SECURITY 0x0c
-#define USB_DT_KEY 0x0d
-#define USB_DT_ENCRYPTION_TYPE 0x0e
-#define USB_DT_BOS 0x0f
-#define USB_DT_DEVICE_CAPABILITY 0x10
-#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
-#define USB_DT_WIRE_ADAPTER 0x21
-#define USB_DT_RPIPE 0x22
-#define USB_DT_CS_RADIO_CONTROL 0x23
-#define USB_DT_PIPE_USAGE 0x24
-#define USB_DT_SS_ENDPOINT_COMP 0x30
-#define USB_DT_SSP_ISOC_ENDPOINT_COMP 0x31
-
-#define USB_REQ_GET_STATUS 0x00
-#define USB_REQ_CLEAR_FEATURE 0x01
-#define USB_REQ_SET_FEATURE 0x03
-#define USB_REQ_SET_ADDRESS 0x05
-#define USB_REQ_GET_DESCRIPTOR 0x06
-#define USB_REQ_SET_DESCRIPTOR 0x07
-#define USB_REQ_GET_CONFIGURATION 0x08
-#define USB_REQ_SET_CONFIGURATION 0x09
-#define USB_REQ_GET_INTERFACE 0x0A
-#define USB_REQ_SET_INTERFACE 0x0B
-#define USB_REQ_SYNCH_FRAME 0x0C
-#define USB_REQ_SET_SEL 0x30
-#define USB_REQ_SET_ISOCH_DELAY 0x31
-
-#define USB_REQ_SET_ENCRYPTION 0x0D
-#define USB_REQ_GET_ENCRYPTION 0x0E
-#define USB_REQ_RPIPE_ABORT 0x0E
-#define USB_REQ_SET_HANDSHAKE 0x0F
-#define USB_REQ_RPIPE_RESET 0x0F
-#define USB_REQ_GET_HANDSHAKE 0x10
-#define USB_REQ_SET_CONNECTION 0x11
-#define USB_REQ_SET_SECURITY_DATA 0x12
-#define USB_REQ_GET_SECURITY_DATA 0x13
-#define USB_REQ_SET_WUSB_DATA 0x14
-#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
-#define USB_REQ_LOOPBACK_DATA_READ 0x16
-#define USB_REQ_SET_INTERFACE_DS 0x17
-
-#define USB_REQ_GET_PARTNER_PDO 20
-#define USB_REQ_GET_BATTERY_STATUS 21
-#define USB_REQ_SET_PDO 22
-#define USB_REQ_GET_VDM 23
-#define USB_REQ_SEND_VDM 24
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect
-
-#define USB_MAX_IFACE_NUM 4
-#define USB_MAX_EP_NUM 32
-#define USB_MAX_FDS 6
-
-struct usb_endpoint_index {
- struct usb_endpoint_descriptor desc;
- int handle;
-};
-
-struct usb_iface_index {
- struct usb_interface_descriptor* iface;
- uint8 bInterfaceNumber;
- uint8 bAlternateSetting;
- uint8 bInterfaceClass;
- struct usb_endpoint_index eps[USB_MAX_EP_NUM];
- int eps_num;
-};
-
-struct usb_device_index {
- struct usb_device_descriptor* dev;
- struct usb_config_descriptor* config;
- uint8 bDeviceClass;
- uint8 bMaxPower;
- int config_length;
- struct usb_iface_index ifaces[USB_MAX_IFACE_NUM];
- int ifaces_num;
- int iface_cur;
-};
-
-struct usb_info {
- int fd;
- struct usb_device_index index;
-};
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \
- __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write
-static struct usb_info usb_devices[USB_MAX_FDS];
-
-static struct usb_device_index* lookup_usb_index(int fd)
-{
- for (int i = 0; i < USB_MAX_FDS; i++) {
- if (__atomic_load_n(&usb_devices[i].fd, __ATOMIC_ACQUIRE) == fd)
- return &usb_devices[i].index;
- }
- return NULL;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-static int usb_devices_num;
-
-static bool parse_usb_descriptor(const char* buffer, size_t length, struct usb_device_index* index)
-{
- if (length < sizeof(*index->dev) + sizeof(*index->config))
- return false;
-
- memset(index, 0, sizeof(*index));
-
- index->dev = (struct usb_device_descriptor*)buffer;
- index->config = (struct usb_config_descriptor*)(buffer + sizeof(*index->dev));
- index->bDeviceClass = index->dev->bDeviceClass;
- index->bMaxPower = index->config->bMaxPower;
- index->config_length = length - sizeof(*index->dev);
- index->iface_cur = -1;
- size_t offset = 0;
-
- while (true) {
- if (offset + 1 >= length)
- break;
- uint8 desc_length = buffer[offset];
- uint8 desc_type = buffer[offset + 1];
- if (desc_length <= 2)
- break;
- if (offset + desc_length > length)
- break;
- if (desc_type == USB_DT_INTERFACE && index->ifaces_num < USB_MAX_IFACE_NUM) {
- struct usb_interface_descriptor* iface = (struct usb_interface_descriptor*)(buffer + offset);
- debug("parse_usb_descriptor: found interface #%u (%d, %d) at %p\n",
- index->ifaces_num, iface->bInterfaceNumber, iface->bAlternateSetting, iface);
- index->ifaces[index->ifaces_num].iface = iface;
- index->ifaces[index->ifaces_num].bInterfaceNumber = iface->bInterfaceNumber;
- index->ifaces[index->ifaces_num].bAlternateSetting = iface->bAlternateSetting;
- index->ifaces[index->ifaces_num].bInterfaceClass = iface->bInterfaceClass;
- index->ifaces_num++;
- }
- if (desc_type == USB_DT_ENDPOINT && index->ifaces_num > 0) {
- struct usb_iface_index* iface = &index->ifaces[index->ifaces_num - 1];
- debug("parse_usb_descriptor: found endpoint #%u at %p\n", iface->eps_num, buffer + offset);
- if (iface->eps_num < USB_MAX_EP_NUM) {
- memcpy(&iface->eps[iface->eps_num].desc, buffer + offset, sizeof(iface->eps[iface->eps_num].desc));
- iface->eps_num++;
- }
- }
- offset += desc_length;
- }
-
- return true;
-}
-
-static struct usb_device_index* add_usb_index(int fd, const char* dev, size_t dev_len)
-{
- int i = __atomic_fetch_add(&usb_devices_num, 1, __ATOMIC_RELAXED);
- if (i >= USB_MAX_FDS)
- return NULL;
-
- if (!parse_usb_descriptor(dev, dev_len, &usb_devices[i].index))
- return NULL;
-
- __atomic_store_n(&usb_devices[i].fd, fd, __ATOMIC_RELEASE);
- return &usb_devices[i].index;
-}
-
-#endif
-
-#if USB_DEBUG
-
-#include <linux/hid.h>
-#include <linux/usb/audio.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/ch11.h>
-#include <linux/usb/ch9.h>
-#define USBLP_REQ_GET_ID 0x00
-#define USBLP_REQ_GET_STATUS 0x01
-#define USBLP_REQ_RESET 0x02
-
-const char* usb_class_to_string(unsigned value)
-{
- switch (value) {
- case USB_CLASS_PER_INTERFACE:
- return "USB_CLASS_PER_INTERFACE";
- case USB_CLASS_AUDIO:
- return "USB_CLASS_AUDIO";
- case USB_CLASS_COMM:
- return "USB_CLASS_COMM";
- case USB_CLASS_HID:
- return "USB_CLASS_HID";
- case USB_CLASS_PHYSICAL:
- return "USB_CLASS_PHYSICAL";
- case USB_CLASS_STILL_IMAGE:
- return "USB_CLASS_STILL_IMAGE";
- case USB_CLASS_PRINTER:
- return "USB_CLASS_PRINTER";
- case USB_CLASS_MASS_STORAGE:
- return "USB_CLASS_MASS_STORAGE";
- case USB_CLASS_HUB:
- return "USB_CLASS_HUB";
- case USB_CLASS_CDC_DATA:
- return "USB_CLASS_CDC_DATA";
- case USB_CLASS_CSCID:
- return "USB_CLASS_CSCID";
- case USB_CLASS_CONTENT_SEC:
- return "USB_CLASS_CONTENT_SEC";
- case USB_CLASS_VIDEO:
- return "USB_CLASS_VIDEO";
- case USB_CLASS_WIRELESS_CONTROLLER:
- return "USB_CLASS_WIRELESS_CONTROLLER";
- case USB_CLASS_MISC:
- return "USB_CLASS_MISC";
- case USB_CLASS_APP_SPEC:
- return "USB_CLASS_APP_SPEC";
- case USB_CLASS_VENDOR_SPEC:
- return "USB_CLASS_VENDOR_SPEC";
- }
- return "unknown";
-}
-static void analyze_usb_device(struct usb_device_index* index)
-{
- debug("analyze_usb_device: idVendor = %04x\n", (unsigned)index->dev->idVendor);
- debug("analyze_usb_device: idProduct = %04x\n", (unsigned)index->dev->idProduct);
-
- debug("analyze_usb_device: bDeviceClass = %x (%s)\n", (unsigned)index->dev->bDeviceClass,
- usb_class_to_string(index->dev->bDeviceClass));
- debug("analyze_usb_device: bDeviceSubClass = %x\n", (unsigned)index->dev->bDeviceSubClass);
- debug("analyze_usb_device: bDeviceProtocol = %x\n", (unsigned)index->dev->bDeviceProtocol);
-
- for (int i = 0; i < index->ifaces_num; i++) {
- struct usb_interface_descriptor* iface = index->ifaces[i].iface;
- debug("analyze_usb_device: interface #%d:\n", i);
- debug("analyze_usb_device: bInterfaceClass = %x (%s)\n", (unsigned)iface->bInterfaceClass,
- usb_class_to_string(iface->bInterfaceClass));
- debug("analyze_usb_device: bInterfaceSubClass = %x\n", (unsigned)iface->bInterfaceSubClass);
- debug("analyze_usb_device: bInterfaceProtocol = %x\n", (unsigned)iface->bInterfaceProtocol);
- }
-}
-
-static bool analyze_control_request_standard(struct usb_device_index* index, struct usb_ctrlrequest* ctrl)
-{
- uint8 bDeviceClass = index->bDeviceClass;
- uint8 bInterfaceClass = index->ifaces[index->iface_cur].bInterfaceClass;
- if (bDeviceClass == USB_CLASS_HID || bInterfaceClass == USB_CLASS_HID) {
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- debug("analyze_control_request: req = USB_REQ_GET_DESCRIPTOR\n");
- switch (ctrl->wValue >> 8) {
- case HID_DT_HID:
- debug("analyze_control_request: desc = HID_DT_HID\n");
- return true;
- case HID_DT_REPORT:
- debug("analyze_control_request: desc = HID_DT_REPORT\n");
- return true;
- case HID_DT_PHYSICAL:
- debug("analyze_control_request: desc = HID_DT_PHYSICAL\n");
- return false;
- }
- }
- }
-
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- debug("analyze_control_request: req = USB_REQ_GET_DESCRIPTOR\n");
- switch (ctrl->wValue >> 8) {
- case USB_DT_DEVICE:
- debug("analyze_control_request: desc = USB_DT_DEVICE\n");
- return true;
- case USB_DT_CONFIG:
- debug("analyze_control_request: desc = USB_DT_CONFIG, index = %d\n", (int)(ctrl->wValue & 0xff));
- return true;
- case USB_DT_STRING:
- debug("analyze_control_request: desc = USB_DT_STRING\n");
- return true;
- case USB_DT_INTERFACE:
- debug("analyze_control_request: desc = USB_DT_INTERFACE\n");
- break;
- case USB_DT_ENDPOINT:
- debug("analyze_control_request: desc = USB_DT_ENDPOINT\n");
- break;
- case USB_DT_DEVICE_QUALIFIER:
- debug("analyze_control_request: desc = USB_DT_DEVICE_QUALIFIER\n");
- return true;
- case USB_DT_OTHER_SPEED_CONFIG:
- debug("analyze_control_request: desc = USB_DT_OTHER_SPEED_CONFIG\n");
- break;
- case USB_DT_INTERFACE_POWER:
- debug("analyze_control_request: desc = USB_DT_INTERFACE_POWER\n");
- break;
- case USB_DT_OTG:
- debug("analyze_control_request: desc = USB_DT_OTG\n");
- break;
- case USB_DT_DEBUG:
- debug("analyze_control_request: desc = USB_DT_DEBUG\n");
- break;
- case USB_DT_INTERFACE_ASSOCIATION:
- debug("analyze_control_request: desc = USB_DT_INTERFACE_ASSOCIATION\n");
- break;
- case USB_DT_SECURITY:
- debug("analyze_control_request: desc = USB_DT_SECURITY\n");
- break;
- case USB_DT_KEY:
- debug("analyze_control_request: desc = USB_DT_KEY\n");
- break;
- case USB_DT_ENCRYPTION_TYPE:
- debug("analyze_control_request: desc = USB_DT_ENCRYPTION_TYPE\n");
- break;
- case USB_DT_BOS:
- debug("analyze_control_request: desc = USB_DT_BOS\n");
- return true;
- case USB_DT_DEVICE_CAPABILITY:
- debug("analyze_control_request: desc = USB_DT_DEVICE_CAPABILITY\n");
- break;
- case USB_DT_WIRELESS_ENDPOINT_COMP:
- debug("analyze_control_request: desc = USB_DT_WIRELESS_ENDPOINT_COMP\n");
- break;
- case USB_DT_WIRE_ADAPTER:
- debug("analyze_control_request: desc = USB_DT_WIRE_ADAPTER\n");
- break;
- case USB_DT_RPIPE:
- debug("analyze_control_request: desc = USB_DT_RPIPE\n");
- break;
- case USB_DT_CS_RADIO_CONTROL:
- debug("analyze_control_request: desc = USB_DT_CS_RADIO_CONTROL\n");
- break;
- case USB_DT_PIPE_USAGE:
- debug("analyze_control_request: desc = USB_DT_PIPE_USAGE\n");
- break;
- case USB_DT_SS_ENDPOINT_COMP:
- debug("analyze_control_request: desc = USB_DT_SS_ENDPOINT_COMP\n");
- break;
- case USB_DT_SSP_ISOC_ENDPOINT_COMP:
- debug("analyze_control_request: desc = USB_DT_SSP_ISOC_ENDPOINT_COMP\n");
- break;
- default:
- debug("analyze_control_request: desc = unknown = 0x%x\n", (int)(ctrl->wValue >> 8));
- break;
- }
- break;
- case USB_REQ_GET_STATUS:
- debug("analyze_control_request: req = USB_REQ_GET_STATUS\n");
- break;
- case USB_REQ_CLEAR_FEATURE:
- debug("analyze_control_request: req = USB_REQ_CLEAR_FEATURE\n");
- break;
- case USB_REQ_SET_FEATURE:
- debug("analyze_control_request: req = USB_REQ_SET_FEATURE\n");
- break;
- case USB_REQ_GET_CONFIGURATION:
- debug("analyze_control_request: req = USB_REQ_GET_CONFIGURATION\n");
- return true;
- case USB_REQ_SET_CONFIGURATION:
- debug("analyze_control_request: req = USB_REQ_SET_CONFIGURATION\n");
- break;
- case USB_REQ_GET_INTERFACE:
- debug("analyze_control_request: req = USB_REQ_GET_INTERFACE\n");
- return true;
- case USB_REQ_SET_INTERFACE:
- debug("analyze_control_request: req = USB_REQ_SET_INTERFACE\n");
- break;
- default:
- debug("analyze_control_request: req = unknown = 0x%x\n", (int)ctrl->bRequest);
- break;
- }
-
- return false;
-}
-
-static bool analyze_control_request_class(struct usb_device_index* index, struct usb_ctrlrequest* ctrl)
-{
- uint8 bDeviceClass = index->bDeviceClass;
- uint8 bInterfaceClass = index->ifaces[index->iface_cur].bInterfaceClass;
-
- if (bDeviceClass == USB_CLASS_HID || bInterfaceClass == USB_CLASS_HID) {
- switch (ctrl->bRequest) {
- case HID_REQ_GET_REPORT:
- debug("analyze_control_request: req = HID_REQ_GET_REPORT\n");
- return true;
- case HID_REQ_GET_IDLE:
- debug("analyze_control_request: req = HID_REQ_GET_IDLE\n");
- break;
- case HID_REQ_GET_PROTOCOL:
- debug("analyze_control_request: req = HID_REQ_GET_PROTOCOL\n");
- return true;
- case HID_REQ_SET_REPORT:
- debug("analyze_control_request: req = HID_REQ_SET_REPORT\n");
- break;
- case HID_REQ_SET_IDLE:
- debug("analyze_control_request: req = HID_REQ_SET_IDLE\n");
- break;
- case HID_REQ_SET_PROTOCOL:
- debug("analyze_control_request: req = HID_REQ_SET_PROTOCOL\n");
- break;
- }
- }
-
- if (bDeviceClass == USB_CLASS_AUDIO || bInterfaceClass == USB_CLASS_AUDIO) {
- switch (ctrl->bRequest) {
- case UAC_SET_CUR:
- debug("analyze_control_request: req = UAC_SET_CUR\n");
- break;
- case UAC_GET_CUR:
- debug("analyze_control_request: req = UAC_GET_CUR\n");
- return true;
- case UAC_SET_MIN:
- debug("analyze_control_request: req = UAC_SET_MIN\n");
- break;
- case UAC_GET_MIN:
- debug("analyze_control_request: req = UAC_GET_MIN\n");
- return true;
- case UAC_SET_MAX:
- debug("analyze_control_request: req = UAC_SET_MAX\n");
- break;
- case UAC_GET_MAX:
- debug("analyze_control_request: req = UAC_GET_MAX\n");
- return true;
- case UAC_SET_RES:
- debug("analyze_control_request: req = UAC_SET_RES\n");
- break;
- case UAC_GET_RES:
- debug("analyze_control_request: req = UAC_GET_RES\n");
- return true;
- case UAC_SET_MEM:
- debug("analyze_control_request: req = UAC_SET_MEM\n");
- break;
- case UAC_GET_MEM:
- debug("analyze_control_request: req = UAC_GET_MEM\n");
- return true;
- }
- }
-
- if (bDeviceClass == USB_CLASS_PRINTER || bInterfaceClass == USB_CLASS_PRINTER) {
- switch (ctrl->bRequest) {
- case USBLP_REQ_GET_ID:
- debug("analyze_control_request: req = USBLP_REQ_GET_ID\n");
- return true;
- case USBLP_REQ_GET_STATUS:
- debug("analyze_control_request: req = USBLP_REQ_GET_STATUS\n");
- return true;
- case USBLP_REQ_RESET:
- debug("analyze_control_request: req = USBLP_REQ_RESET\n");
- break;
- }
- }
-
- if (bDeviceClass == USB_CLASS_HUB || bInterfaceClass == USB_CLASS_HUB) {
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- switch (ctrl->wValue >> 8) {
- case USB_DT_HUB:
- debug("analyze_control_request: desc = USB_DT_HUB\n");
- return true;
- case USB_DT_SS_HUB:
- debug("analyze_control_request: desc = USB_DT_SS_HUB\n");
- return true;
- }
- case USB_REQ_GET_STATUS:
- debug("analyze_control_request: req = USB_REQ_GET_STATUS\n");
- return true;
- case HUB_SET_DEPTH:
- debug("analyze_control_request: req = HUB_SET_DEPTH\n");
- break;
- }
- }
-
- if (bInterfaceClass == USB_CLASS_COMM) {
- switch (ctrl->bRequest) {
- case USB_CDC_SEND_ENCAPSULATED_COMMAND:
- debug("analyze_control_request: req = USB_CDC_SEND_ENCAPSULATED_COMMAND\n");
- break;
- case USB_CDC_GET_ENCAPSULATED_RESPONSE:
- debug("analyze_control_request: req = USB_CDC_GET_ENCAPSULATED_RESPONSE\n");
- break;
- case USB_CDC_REQ_SET_LINE_CODING:
- debug("analyze_control_request: req = USB_CDC_REQ_SET_LINE_CODING\n");
- break;
- case USB_CDC_REQ_GET_LINE_CODING:
- debug("analyze_control_request: req = USB_CDC_REQ_GET_LINE_CODING\n");
- break;
- case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
- debug("analyze_control_request: req = USB_CDC_REQ_SET_CONTROL_LINE_STATE\n");
- break;
- case USB_CDC_REQ_SEND_BREAK:
- debug("analyze_control_request: req = USB_CDC_REQ_SEND_BREAK\n");
- break;
- case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
- debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_MULTICAST_FILTERS\n");
- break;
- case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
- debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER\n");
- break;
- case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
- debug("analyze_control_request: req = USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER\n");
- break;
- case USB_CDC_SET_ETHERNET_PACKET_FILTER:
- debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_PACKET_FILTER\n");
- break;
- case USB_CDC_GET_ETHERNET_STATISTIC:
- debug("analyze_control_request: req = USB_CDC_GET_ETHERNET_STATISTIC\n");
- break;
- case USB_CDC_GET_NTB_PARAMETERS:
- debug("analyze_control_request: req = USB_CDC_GET_NTB_PARAMETERS\n");
- return true;
- case USB_CDC_GET_NET_ADDRESS:
- debug("analyze_control_request: req = USB_CDC_GET_NET_ADDRESS\n");
- break;
- case USB_CDC_SET_NET_ADDRESS:
- debug("analyze_control_request: req = USB_CDC_SET_NET_ADDRESS\n");
- break;
- case USB_CDC_GET_NTB_FORMAT:
- debug("analyze_control_request: req = USB_CDC_GET_NTB_FORMAT\n");
- return true;
- case USB_CDC_SET_NTB_FORMAT:
- debug("analyze_control_request: req = USB_CDC_SET_NTB_FORMAT\n");
- break;
- case USB_CDC_GET_NTB_INPUT_SIZE:
- debug("analyze_control_request: req = USB_CDC_GET_NTB_INPUT_SIZE\n");
- return true;
- case USB_CDC_SET_NTB_INPUT_SIZE:
- debug("analyze_control_request: req = USB_CDC_SET_NTB_INPUT_SIZE\n");
- break;
- case USB_CDC_GET_MAX_DATAGRAM_SIZE:
- debug("analyze_control_request: req = USB_CDC_GET_MAX_DATAGRAM_SIZE\n");
- return true;
- case USB_CDC_SET_MAX_DATAGRAM_SIZE:
- debug("analyze_control_request: req = USB_CDC_SET_MAX_DATAGRAM_SIZE\n");
- break;
- case USB_CDC_GET_CRC_MODE:
- debug("analyze_control_request: req = USB_CDC_GET_CRC_MODE\n");
- return true;
- case USB_CDC_SET_CRC_MODE:
- debug("analyze_control_request: req = USB_CDC_SET_CRC_MODE\n");
- break;
- }
- }
-
- return false;
-}
-
-static bool analyze_control_request_vendor(struct usb_device_index* index, struct usb_ctrlrequest* ctrl)
-{
- return true;
-}
-static void analyze_control_request(int fd, struct usb_ctrlrequest* ctrl)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
-
- if (!index)
- return;
-
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- debug("analyze_control_request: type = USB_TYPE_STANDARD\n");
- if (analyze_control_request_standard(index, ctrl))
- return;
- break;
- case USB_TYPE_CLASS:
- debug("analyze_control_request: type = USB_TYPE_CLASS\n");
- if (analyze_control_request_class(index, ctrl))
- return;
- break;
- case USB_TYPE_VENDOR:
- debug("analyze_control_request: type = USB_TYPE_VENDOR\n");
- if (analyze_control_request_vendor(index, ctrl))
- return;
- break;
- }
-
- if (ctrl->bRequestType & USB_DIR_IN) {
- char message[128];
- debug("analyze_control_request: unknown control request\n");
- snprintf(&message[0], sizeof(message), "BUG: unknown control request (0x%x, 0x%x, 0x%x, 0x%x, %d)",
- ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, ctrl->wLength);
- write_file("/dev/kmsg", &message[0]);
- }
-}
-
-#endif
-
-struct vusb_connect_string_descriptor {
- uint32 len;
- char* str;
-} __attribute__((packed));
-
-struct vusb_connect_descriptors {
- uint32 qual_len;
- char* qual;
- uint32 bos_len;
- char* bos;
- uint32 strs_len;
- struct vusb_connect_string_descriptor strs[0];
-} __attribute__((packed));
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-
-static const char default_string[] = {
- 8, USB_DT_STRING,
- 's', 0, 'y', 0, 'z', 0
-};
-
-static const char default_lang_id[] = {
- 4, USB_DT_STRING,
- 0x09, 0x04
-};
-
-static bool lookup_connect_response_in(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl,
- struct usb_qualifier_descriptor* qual,
- char** response_data, uint32* response_length)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
- uint8 str_idx;
-
- if (!index)
- return false;
-
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- switch (ctrl->wValue >> 8) {
- case USB_DT_DEVICE:
- *response_data = (char*)index->dev;
- *response_length = sizeof(*index->dev);
- return true;
- case USB_DT_CONFIG:
- *response_data = (char*)index->config;
- *response_length = index->config_length;
- return true;
- case USB_DT_STRING:
- str_idx = (uint8)ctrl->wValue;
- if (descs && str_idx < descs->strs_len) {
- *response_data = descs->strs[str_idx].str;
- *response_length = descs->strs[str_idx].len;
- return true;
- }
- if (str_idx == 0) {
- *response_data = (char*)&default_lang_id[0];
- *response_length = default_lang_id[0];
- return true;
- }
- *response_data = (char*)&default_string[0];
- *response_length = default_string[0];
- return true;
- case USB_DT_BOS:
- *response_data = descs->bos;
- *response_length = descs->bos_len;
- return true;
- case USB_DT_DEVICE_QUALIFIER:
- if (!descs->qual) {
- qual->bLength = sizeof(*qual);
- qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
- qual->bcdUSB = index->dev->bcdUSB;
- qual->bDeviceClass = index->dev->bDeviceClass;
- qual->bDeviceSubClass = index->dev->bDeviceSubClass;
- qual->bDeviceProtocol = index->dev->bDeviceProtocol;
- qual->bMaxPacketSize0 = index->dev->bMaxPacketSize0;
- qual->bNumConfigurations = index->dev->bNumConfigurations;
- qual->bRESERVED = 0;
- *response_data = (char*)qual;
- *response_length = sizeof(*qual);
- return true;
- }
- *response_data = descs->qual;
- *response_length = descs->qual_len;
- return true;
- default:
- break;
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- debug("lookup_connect_response_in: unknown request");
- return false;
-}
-
-#endif
-
-typedef bool (*lookup_connect_out_response_t)(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl, bool* done);
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect
-static bool lookup_connect_response_out_generic(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl, bool* done)
-{
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
- case USB_REQ_SET_CONFIGURATION:
- *done = true;
- return true;
- default:
- break;
- }
- break;
- }
-
- debug("lookup_connect_response_out: unknown request");
- return false;
-}
-#endif
-
-#if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k)
-#define ATH9K_FIRMWARE_DOWNLOAD 0x30
-#define ATH9K_FIRMWARE_DOWNLOAD_COMP 0x31
-
-static bool lookup_connect_response_out_ath9k(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl, bool* done)
-{
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
- case USB_REQ_SET_CONFIGURATION:
- return true;
- default:
- break;
- }
- break;
- case USB_TYPE_VENDOR:
- switch (ctrl->bRequest) {
- case ATH9K_FIRMWARE_DOWNLOAD:
- return true;
- case ATH9K_FIRMWARE_DOWNLOAD_COMP:
- *done = true;
- return true;
- default:
- break;
- }
- break;
- }
-
- debug("lookup_connect_response_out_ath9k: unknown request");
- return false;
-}
-
-#endif
-
-#if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_control_io)
-
-struct vusb_descriptor {
- uint8 req_type;
- uint8 desc_type;
- uint32 len;
- char data[0];
-} __attribute__((packed));
-
-struct vusb_descriptors {
- uint32 len;
- struct vusb_descriptor* generic;
- struct vusb_descriptor* descs[0];
-} __attribute__((packed));
-
-struct vusb_response {
- uint8 type;
- uint8 req;
- uint32 len;
- char data[0];
-} __attribute__((packed));
-
-struct vusb_responses {
- uint32 len;
- struct vusb_response* generic;
- struct vusb_response* resps[0];
-} __attribute__((packed));
-
-static bool lookup_control_response(const struct vusb_descriptors* descs, const struct vusb_responses* resps,
- struct usb_ctrlrequest* ctrl, char** response_data, uint32* response_length)
-{
- int descs_num = 0;
- int resps_num = 0;
-
- if (descs)
- descs_num = (descs->len - offsetof(struct vusb_descriptors, descs)) / sizeof(descs->descs[0]);
- if (resps)
- resps_num = (resps->len - offsetof(struct vusb_responses, resps)) / sizeof(resps->resps[0]);
-
- uint8 req = ctrl->bRequest;
- uint8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
- uint8 desc_type = ctrl->wValue >> 8;
-
- if (req == USB_REQ_GET_DESCRIPTOR) {
- int i;
-
- for (i = 0; i < descs_num; i++) {
- struct vusb_descriptor* desc = descs->descs[i];
- if (!desc)
- continue;
- if (desc->req_type == req_type && desc->desc_type == desc_type) {
- *response_length = desc->len;
- if (*response_length != 0)
- *response_data = &desc->data[0];
- else
- *response_data = NULL;
- return true;
- }
- }
-
- if (descs && descs->generic) {
- *response_data = &descs->generic->data[0];
- *response_length = descs->generic->len;
- return true;
- }
- } else {
- int i;
-
- for (i = 0; i < resps_num; i++) {
- struct vusb_response* resp = resps->resps[i];
- if (!resp)
- continue;
- if (resp->type == req_type && resp->req == req) {
- *response_length = resp->len;
- if (*response_length != 0)
- *response_data = &resp->data[0];
- else
- *response_data = NULL;
- return true;
- }
- }
-
- if (resps && resps->generic) {
- *response_data = &resps->generic->data[0];
- *response_length = resps->generic->len;
- return true;
- }
- }
-
- return false;
-}
-
-#endif
-
-
-static int vhci_open(void)
-{
- char path[1024];
-
- snprintf(path, sizeof(path), "/dev/vhci%llu", procid);
-
- return open(path, O_RDWR);
-}
-
-static int vhci_setport(int fd, u_int port)
-{
- struct vhci_ioc_set_port args;
-
- args.port = port;
- return ioctl(fd, VHCI_IOC_SET_PORT, &args);
-}
-
-static int vhci_usb_attach(int fd)
-{
- return ioctl(fd, VHCI_IOC_USB_ATTACH, NULL);
-}
-
-static int vhci_usb_recv(int fd, void* buf, size_t size)
-{
- uint8* ptr = (uint8*)buf;
-
- while (1) {
- ssize_t done = read(fd, ptr, size);
- if (done < 0)
- return -1;
- if ((size_t)done == size)
- return 0;
- size -= done;
- ptr += done;
- }
-}
-
-static int vhci_usb_send(int fd, void* buf, size_t size)
-{
- uint8* ptr = (uint8*)buf;
-
- while (1) {
- ssize_t done = write(fd, ptr, size);
- if (done <= 0)
- return -1;
- if ((size_t)done == size)
- return 0;
- size -= done;
- ptr += done;
- }
-}
-
-static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len,
- const char* dev, const struct vusb_connect_descriptors* descs,
- lookup_connect_out_response_t lookup_connect_response_out)
-{
- struct usb_device_index* index = add_usb_index(fd, dev, dev_len);
- if (!index) {
- debug("syz_usb_connect: add_usb_index failed\n");
- return -1;
- }
- debug("syz_usb_connect: add_usb_index success\n");
-
-#if USB_DEBUG
- analyze_usb_device(index);
-#endif
-
- if (vhci_setport(fd, 1))
- fail("syz_usb_connect: vhci_setport failed with");
-
- if (vhci_usb_attach(fd)) {
- debug("syz_usb_connect: vhci_usb_attach failed with %d\n", errno);
- return -1;
- }
- debug("syz_usb_connect: vhci_usb_attach success\n");
-
- bool done = false;
- while (!done) {
- vhci_request_t req;
-
- if (vhci_usb_recv(fd, &req, sizeof(req))) {
- debug("syz_usb_connect: vhci_usb_recv failed with %d\n", errno);
- return -1;
- }
- if (req.type != VHCI_REQ_CTRL) {
- debug("syz_usb_connect: received non-control transfer\n");
- return -1;
- }
-
- debug("syz_usb_connect: bReqType: 0x%x (%s), bReq: 0x%x, wVal: 0x%x, wIdx: 0x%x, wLen: %d\n",
- req.u.ctrl.bmRequestType, (req.u.ctrl.bmRequestType & UE_DIR_IN) ? "IN" : "OUT",
- req.u.ctrl.bRequest, UGETW(req.u.ctrl.wValue), UGETW(req.u.ctrl.wIndex), UGETW(req.u.ctrl.wLength));
-
-#if USB_DEBUG
- analyze_control_request(fd, &req.u.ctrl);
-#endif
-
- char* response_data = NULL;
- uint32 response_length = 0;
- struct usb_qualifier_descriptor qual;
- char data[4096];
-
- if (req.u.ctrl.bmRequestType & UE_DIR_IN) {
- if (!lookup_connect_response_in(fd, descs, (const struct usb_ctrlrequest*)&req.u.ctrl, &qual, &response_data, &response_length)) {
- debug("syz_usb_connect: unknown control IN request\n");
- return -1;
- }
- } else {
- if (!lookup_connect_response_out(fd, descs, (const struct usb_ctrlrequest*)&req.u.ctrl, &done)) {
- debug("syz_usb_connect: unknown control OUT request\n");
- return -1;
- }
- response_data = NULL;
- response_length = UGETW(req.u.ctrl.wLength);
- }
-
- if ((req.u.ctrl.bmRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
- req.u.ctrl.bRequest == USB_REQ_SET_CONFIGURATION) {
- }
-
- if (response_length > sizeof(data))
- response_length = 0;
- if ((uint32)UGETW(req.u.ctrl.wLength) < response_length)
- response_length = UGETW(req.u.ctrl.wLength);
-
- if (response_data)
- memcpy(data, response_data, response_length);
- else
- memset(data, 0, response_length);
-
- int rv = 0;
- if (req.u.ctrl.bmRequestType & UE_DIR_IN) {
- debug("syz_usb_connect: writing %d bytes\n", response_length);
- if (response_length > 0) {
- vhci_response_t res;
- res.size = response_length;
- rv = vhci_usb_send(fd, &res, sizeof(res));
- if (rv == 0)
- rv = vhci_usb_send(fd, data, response_length);
- }
- } else {
- rv = vhci_usb_recv(fd, data, response_length);
- debug("syz_usb_connect: read %d bytes\n", response_length);
- debug_dump_data(&data[0], response_length);
- }
- if (rv < 0) {
- debug("syz_usb_connect: usb_raw_ep0_read/write failed with %d\n", rv);
- return -1;
- }
- }
-
- sleep_ms(200);
- debug("syz_usb_connect: configured\n");
- return fd;
-}
-
-static volatile long syz_usb_connect(volatile long a0, volatile long a1,
- volatile long a2, volatile long a3)
-{
- uint64 speed = a0;
- uint64 dev_len = a1;
- const char* dev = (const char*)a2;
- const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a3;
-
- debug("syz_usb_connect: dev: %p\n", dev);
- if (!dev) {
- debug("syz_usb_connect: dev is null\n");
- return -1;
- }
-
- debug("syz_usb_connect: device data:\n");
- debug_dump_data(dev, dev_len);
-
- int fd = vhci_open();
- if (fd < 0)
- fail("syz_usb_connect: vhci_open failed");
- long res = syz_usb_connect_impl(fd, speed, dev_len, dev, descs, &lookup_connect_response_out_generic);
- close(fd);
- return res;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_disconnect
-static volatile long syz_usb_disconnect(volatile long a0)
-{
- int fd = a0;
-
- int rv = close(fd);
-
- sleep_ms(200);
-
- return rv;
-}
-#endif
-
-#endif
-#if SYZ_EXECUTOR || SYZ_USB
-#include <dirent.h>
-static void setup_usb(void)
-{
- DIR* dir = opendir("/dev");
- if (dir == NULL)
- fail("failed to open /dev");
-
- struct dirent* ent = NULL;
- while ((ent = readdir(dir)) != NULL) {
- if (ent->d_type != DT_CHR)
- continue;
- if (strncmp(ent->d_name, "vhci", 4))
- continue;
- char path[1024];
- snprintf(path, sizeof(path), "/dev/%s", ent->d_name);
- if (chmod(path, 0666))
- failmsg("failed to chmod vhci", "path=%s", path);
- }
-
- closedir(dir);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_FAULT
-#include <fcntl.h>
-#include <sys/fault.h>
-#include <sys/stat.h>
-static void setup_fault(void)
-{
- if (chmod("/dev/fault", 0666))
- fail("failed to chmod /dev/fault");
-}
-static int inject_fault(int nth)
-{
- struct fault_ioc_enable en;
- int fd;
-
- fd = open("/dev/fault", O_RDWR);
- if (fd == -1)
- fail("failed to open /dev/fault");
-
- en.scope = FAULT_SCOPE_LWP;
- en.mode = 0;
- en.nth = nth + 1;
- if (ioctl(fd, FAULT_IOC_ENABLE, &en) != 0)
- failmsg("FAULT_IOC_ENABLE failed", "nth=%d", nth);
-
- return fd;
-}
-#endif
-#if SYZ_EXECUTOR
-static int fault_injected(int fd)
-{
- struct fault_ioc_getinfo info;
- struct fault_ioc_disable dis;
- int res;
-
- info.scope = FAULT_SCOPE_LWP;
- if (ioctl(fd, FAULT_IOC_GETINFO, &info) != 0)
- fail("FAULT_IOC_GETINFO failed");
- res = (info.nfaults > 0);
-
- dis.scope = FAULT_SCOPE_LWP;
- if (ioctl(fd, FAULT_IOC_DISABLE, &dis) != 0)
- fail("FAULT_IOC_DISABLE failed");
-
- close(fd);
-
- return res;
-}
-#endif
-
-#endif
-
-#if GOOS_darwin
-#define __syscall syscall
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
-
-#include <fcntl.h>
-#if !GOOS_darwin
-#include <net/if_tun.h>
-#endif
-#include <sys/types.h>
-
-static int tunfd = -1;
-
-#if GOOS_netbsd
-#define MAX_TUN 64
-#elif GOOS_freebsd
-#define MAX_TUN 256
-#else
-#define MAX_TUN 4
-#endif
-#define TUN_IFACE "tap%d"
-#define MAX_TUN_IFACE_SIZE sizeof("tap2147483647")
-#define TUN_DEVICE "/dev/tap%d"
-#define MAX_TUN_DEVICE_SIZE sizeof("/dev/tap2147483647")
-
-#define LOCAL_MAC "aa:aa:aa:aa:aa:aa"
-#define REMOTE_MAC "aa:aa:aa:aa:aa:bb"
-#define LOCAL_IPV4 "172.20.%d.170"
-#define MAX_LOCAL_IPV4_SIZE sizeof("172.20.255.170")
-#define REMOTE_IPV4 "172.20.%d.187"
-#define MAX_REMOTE_IPV4_SIZE sizeof("172.20.255.187")
-#define LOCAL_IPV6 "fe80::%02xaa"
-#define MAX_LOCAL_IPV6_SIZE sizeof("fe80::ffaa")
-#define REMOTE_IPV6 "fe80::%02xbb"
-#define MAX_REMOTE_IPV6_SIZE sizeof("fe80::ffbb")
-
-static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
-{
- int rv = vsnprintf(str, size, format, args);
- if (rv < 0)
- fail("vsnprintf failed");
- if ((size_t)rv >= size)
- failmsg("vsnprintf: string doesn't fit into buffer", "string='%s'", 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
-#define PATH_PREFIX "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin "
-#define PATH_PREFIX_LEN (sizeof(PATH_PREFIX) - 1)
-
-static void execute_command(bool panic, const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- char command[PATH_PREFIX_LEN + COMMAND_MAX_LEN];
- memcpy(command, PATH_PREFIX, PATH_PREFIX_LEN);
- vsnprintf_check(command + PATH_PREFIX_LEN, COMMAND_MAX_LEN, format, args);
- va_end(args);
- int rv = system(command);
- if (rv) {
- if (panic)
- failmsg("command failed", "command=%s: %d", &command[0], rv);
- debug("command '%s': %d\n", &command[0], rv);
- }
-}
-
-static void initialize_tun(int tun_id)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_injection)
- return;
-#endif
-
- if (tun_id < 0 || tun_id >= MAX_TUN)
- failmsg("tun_id out of range", "tun_id=%d", tun_id);
-
- char tun_device[MAX_TUN_DEVICE_SIZE];
- snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id);
-
- char tun_iface[MAX_TUN_IFACE_SIZE];
- snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id);
-
-#if GOOS_netbsd
- execute_command(0, "ifconfig %s destroy", tun_iface);
- execute_command(0, "ifconfig %s create", tun_iface);
-#else
- execute_command(0, "ifconfig %s destroy", tun_iface);
-#endif
-
- tunfd = open(tun_device, O_RDWR | O_NONBLOCK);
-#if GOOS_freebsd
- if ((tunfd < 0) && (errno == ENOENT)) {
- execute_command(0, "kldload -q if_tap");
- tunfd = open(tun_device, O_RDWR | O_NONBLOCK);
- }
-#endif
- if (tunfd == -1) {
-#if SYZ_EXECUTOR
- failmsg("tun: can't open device", "device=%s", tun_device);
-#else
- printf("tun: can't open %s: errno=%d\n", tun_device, errno);
- return;
-#endif
- }
- const int kTunFd = 200;
- if (dup2(tunfd, kTunFd) < 0)
- fail("dup2(tunfd, kTunFd) failed");
- close(tunfd);
- tunfd = kTunFd;
-
- char local_mac[sizeof(LOCAL_MAC)];
- snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC);
-#if GOOS_netbsd
- execute_command(1, "ifconfig %s link %s", tun_iface, local_mac);
-#else
- execute_command(1, "ifconfig %s ether %s", tun_iface, local_mac);
-#endif
- char local_ipv4[MAX_LOCAL_IPV4_SIZE];
- snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, tun_id);
- execute_command(1, "ifconfig %s inet %s netmask 255.255.255.0", tun_iface, local_ipv4);
- char remote_mac[sizeof(REMOTE_MAC)];
- char remote_ipv4[MAX_REMOTE_IPV4_SIZE];
- snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC);
- snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, tun_id);
- execute_command(0, "arp -s %s %s", remote_ipv4, remote_mac);
- char local_ipv6[MAX_LOCAL_IPV6_SIZE];
- snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, tun_id);
- execute_command(1, "ifconfig %s inet6 %s", tun_iface, local_ipv6);
- char remote_ipv6[MAX_REMOTE_IPV6_SIZE];
- snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, tun_id);
- execute_command(0, "ndp -s %s%%%s %s", remote_ipv6, tun_iface, remote_mac);
-}
-
-#endif
-
-#if !GOOS_darwin && SYZ_EXECUTOR || __NR_syz_emit_ethernet && SYZ_NET_INJECTION
-#include <stdbool.h>
-#include <sys/uio.h>
-
-static long syz_emit_ethernet(volatile long a0, volatile long a1)
-{
- if (tunfd < 0)
- return (uintptr_t)-1;
-
- size_t length = a0;
- const char* data = (char*)a1;
- debug_dump_data(data, length);
-
- return write(tunfd, data, length);
-}
-#endif
-
-#if !GOOS_darwin && SYZ_EXECUTOR || SYZ_NET_INJECTION && (__NR_syz_extract_tcp_res || SYZ_REPEAT)
-#include <errno.h>
-
-static int read_tun(char* data, int size)
-{
- if (tunfd < 0)
- return -1;
-
- int rv = read(tunfd, data, size);
- if (rv < 0) {
- if (errno == EAGAIN)
- return -1;
- fail("tun: read failed");
- }
- return rv;
-}
-#endif
-
-#if !GOOS_darwin && SYZ_EXECUTOR || __NR_syz_extract_tcp_res && SYZ_NET_INJECTION
-
-struct tcp_resources {
- uint32 seq;
- uint32 ack;
-};
-
-#if GOOS_freebsd || GOOS_darwin
-#include <net/ethernet.h>
-#else
-#include <net/ethertypes.h>
-#endif
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/if_ether.h>
-
-static long syz_extract_tcp_res(volatile long a0, volatile long a1, volatile long a2)
-{
-
- if (tunfd < 0)
- return (uintptr_t)-1;
- char data[1000];
- int rv = read_tun(&data[0], sizeof(data));
- if (rv == -1)
- return (uintptr_t)-1;
- size_t length = rv;
- debug_dump_data(data, length);
-
- if (length < sizeof(struct ether_header))
- return (uintptr_t)-1;
- struct ether_header* ethhdr = (struct ether_header*)&data[0];
-
- struct tcphdr* tcphdr = 0;
- if (ethhdr->ether_type == htons(ETHERTYPE_IP)) {
- if (length < sizeof(struct ether_header) + sizeof(struct ip))
- return (uintptr_t)-1;
- struct ip* iphdr = (struct ip*)&data[sizeof(struct ether_header)];
- if (iphdr->ip_p != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ether_header) + iphdr->ip_hl * 4 + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + iphdr->ip_hl * 4];
- } else {
- if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr))
- return (uintptr_t)-1;
- struct ip6_hdr* ipv6hdr = (struct ip6_hdr*)&data[sizeof(struct ether_header)];
- if (ipv6hdr->ip6_nxt != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + sizeof(struct ip6_hdr)];
- }
-
- struct tcp_resources* res = (struct tcp_resources*)a0;
- res->seq = htonl(ntohl(tcphdr->th_seq) + (uint32)a1);
- res->ack = htonl(ntohl(tcphdr->th_ack) + (uint32)a2);
-
- debug("extracted seq: %08x\n", res->seq);
- debug("extracted ack: %08x\n", res->ack);
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NONE
-
-#include <sys/resource.h>
-#include <unistd.h>
-
-static void sandbox_common()
-{
-#if !SYZ_THREADED
-#if SYZ_EXECUTOR
- if (!flag_threaded)
-#endif
- if (setsid() == -1)
- fail("setsid failed");
-#endif
- struct rlimit rlim;
-#ifdef GOOS_freebsd
- rlim.rlim_cur = rlim.rlim_max = 128 << 20;
- setrlimit(RLIMIT_AS, &rlim);
-#endif
- 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);
- rlim.rlim_cur = rlim.rlim_max = 256;
- setrlimit(RLIMIT_NOFILE, &rlim);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-
-static void loop();
-
-static int do_sandbox_none(void)
-{
- sandbox_common();
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun(procid);
-#endif
- loop();
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID
-
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-static void loop();
-
-static int wait_for_loop(int pid)
-{
- if (pid < 0)
- fail("sandbox fork failed");
- debug("spawned loop pid %d\n", pid);
- int status = 0;
- while (waitpid(-1, &status, WUNTRACED) != pid) {
- }
- return WEXITSTATUS(status);
-}
-
-#define SYZ_HAVE_SANDBOX_SETUID 1
-static int do_sandbox_setuid(void)
-{
- int pid = fork();
- if (pid != 0)
- return wait_for_loop(pid);
-
- sandbox_common();
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun(procid);
-#endif
-
- char pwbuf[1024];
- struct passwd *pw, pwres;
- if (getpwnam_r("nobody", &pwres, pwbuf, sizeof(pwbuf), &pw) != 0 || !pw)
- fail("getpwnam_r(\"nobody\") failed");
-
- if (setgroups(0, NULL))
- fail("failed to setgroups");
- if (setgid(pw->pw_gid))
- fail("failed to setgid");
- if (setuid(pw->pw_uid))
- fail("failed to setuid");
-
- loop();
- doexit(1);
-}
-#endif
-
-#elif GOOS_openbsd
-
-#include <unistd.h>
-
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/syscall.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <sys/event.h>
-#include <sys/ioctl.h>
-#include <sys/ktrace.h>
-#include <sys/mman.h>
-#include <sys/msg.h>
-#include <sys/sem.h>
-#include <sys/shm.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/sysctl.h>
-#include <sys/syslog.h>
-
-#define CAST
-
-#if (SYZ_EXECUTOR || __NR_syz_open_pts)
-#include <termios.h>
-#include <util.h>
-
-static uintptr_t syz_open_pts(void)
-{
- int master, slave;
-
- if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
- return -1;
- if (dup2(master, master + 100) != -1)
- close(master);
- return slave;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
-
-#include <net/if_tun.h>
-#include <sys/types.h>
-
-static int tunfd = -1;
-
-#define MAX_TUN 8
-#define TUN_IFACE "tap%d"
-#define MAX_TUN_IFACE_SIZE sizeof("tap2147483647")
-#define TUN_DEVICE "/dev/tap%d"
-#define MAX_TUN_DEVICE_SIZE sizeof("/dev/tap2147483647")
-
-#define LOCAL_MAC "aa:aa:aa:aa:aa:aa"
-#define REMOTE_MAC "aa:aa:aa:aa:aa:bb"
-#define LOCAL_IPV4 "172.20.%d.170"
-#define MAX_LOCAL_IPV4_SIZE sizeof("172.20.255.170")
-#define REMOTE_IPV4 "172.20.%d.187"
-#define MAX_REMOTE_IPV4_SIZE sizeof("172.20.255.187")
-#define LOCAL_IPV6 "fe80::%02xaa"
-#define MAX_LOCAL_IPV6_SIZE sizeof("fe80::ffaa")
-#define REMOTE_IPV6 "fe80::%02xbb"
-#define MAX_REMOTE_IPV6_SIZE sizeof("fe80::ffbb")
-
-static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
-{
- int rv = vsnprintf(str, size, format, args);
- if (rv < 0)
- fail("vsnprintf failed");
- if ((size_t)rv >= size)
- failmsg("vsnprintf: string doesn't fit into buffer", "string='%s'", 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
-#define PATH_PREFIX "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin "
-#define PATH_PREFIX_LEN (sizeof(PATH_PREFIX) - 1)
-
-static void execute_command(bool panic, const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- char command[PATH_PREFIX_LEN + COMMAND_MAX_LEN];
- memcpy(command, PATH_PREFIX, PATH_PREFIX_LEN);
- vsnprintf_check(command + PATH_PREFIX_LEN, COMMAND_MAX_LEN, format, args);
- va_end(args);
- int rv = system(command);
- if (rv) {
- if (panic)
- failmsg("command failed", "command=%s: %d", &command[0], rv);
- debug("command '%s': %d\n", &command[0], rv);
- }
-}
-
-static void initialize_tun(int tun_id)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_injection)
- return;
-#endif
-
- if (tun_id < 0 || tun_id >= MAX_TUN)
- failmsg("tun_id out of range", "tun_id=%d", tun_id);
-
- char tun_device[MAX_TUN_DEVICE_SIZE];
- snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id);
-
- char tun_iface[MAX_TUN_IFACE_SIZE];
- snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id);
-
- execute_command(0, "ifconfig %s destroy", tun_iface);
-
- tunfd = open(tun_device, O_RDWR | O_NONBLOCK);
- if (tunfd == -1) {
-#if SYZ_EXECUTOR
- failmsg("tun: can't open device", "device=%s", tun_device);
-#else
- printf("tun: can't open %s: errno=%d\n", tun_device, errno);
- return;
-#endif
- }
- const int kTunFd = 200;
- if (dup2(tunfd, kTunFd) < 0)
- fail("dup2(tunfd, kTunFd) failed");
- close(tunfd);
- tunfd = kTunFd;
-
- char local_mac[sizeof(LOCAL_MAC)];
- snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC);
- execute_command(1, "ifconfig %s lladdr %s", tun_iface, local_mac);
- char local_ipv4[MAX_LOCAL_IPV4_SIZE];
- snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, tun_id);
- execute_command(1, "ifconfig %s inet %s netmask 255.255.255.0", tun_iface, local_ipv4);
- char remote_mac[sizeof(REMOTE_MAC)];
- char remote_ipv4[MAX_REMOTE_IPV4_SIZE];
- snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC);
- snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, tun_id);
- execute_command(0, "arp -s %s %s", remote_ipv4, remote_mac);
- char local_ipv6[MAX_LOCAL_IPV6_SIZE];
- snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, tun_id);
- execute_command(1, "ifconfig %s inet6 %s", tun_iface, local_ipv6);
- char remote_ipv6[MAX_REMOTE_IPV6_SIZE];
- snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, tun_id);
- execute_command(0, "ndp -s %s%%%s %s", remote_ipv6, tun_iface, remote_mac);
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_emit_ethernet && SYZ_NET_INJECTION
-#include <sys/uio.h>
-
-static long syz_emit_ethernet(volatile long a0, volatile long a1)
-{
- if (tunfd < 0)
- return (uintptr_t)-1;
-
- size_t length = a0;
- const char* data = (char*)a1;
- debug_dump_data(data, length);
-
- return write(tunfd, data, length);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION && (__NR_syz_extract_tcp_res || SYZ_REPEAT)
-#include <errno.h>
-
-static int read_tun(char* data, int size)
-{
- if (tunfd < 0)
- return -1;
-
- int rv = read(tunfd, data, size);
- if (rv < 0) {
- if (errno == EAGAIN)
- return -1;
- fail("tun: read failed");
- }
- return rv;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_extract_tcp_res && SYZ_NET_INJECTION
-
-struct tcp_resources {
- uint32 seq;
- uint32 ack;
-};
-
-#include <net/ethertypes.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/if_ether.h>
-
-static long syz_extract_tcp_res(volatile long a0, volatile long a1, volatile long a2)
-{
-
- if (tunfd < 0)
- return (uintptr_t)-1;
- char data[1000];
- int rv = read_tun(&data[0], sizeof(data));
- if (rv == -1)
- return (uintptr_t)-1;
- size_t length = rv;
- debug_dump_data(data, length);
-
- if (length < sizeof(struct ether_header))
- return (uintptr_t)-1;
- struct ether_header* ethhdr = (struct ether_header*)&data[0];
-
- struct tcphdr* tcphdr = 0;
- if (ethhdr->ether_type == htons(ETHERTYPE_IP)) {
- if (length < sizeof(struct ether_header) + sizeof(struct ip))
- return (uintptr_t)-1;
- struct ip* iphdr = (struct ip*)&data[sizeof(struct ether_header)];
- if (iphdr->ip_p != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ether_header) + iphdr->ip_hl * 4 + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + iphdr->ip_hl * 4];
- } else {
- if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr))
- return (uintptr_t)-1;
- struct ip6_hdr* ipv6hdr = (struct ip6_hdr*)&data[sizeof(struct ether_header)];
- if (ipv6hdr->ip6_nxt != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + sizeof(struct ip6_hdr)];
- }
-
- struct tcp_resources* res = (struct tcp_resources*)a0;
- res->seq = htonl(ntohl(tcphdr->th_seq) + (uint32)a1);
- res->ack = htonl(ntohl(tcphdr->th_ack) + (uint32)a2);
-
- debug("extracted seq: %08x\n", res->seq);
- debug("extracted ack: %08x\n", res->ack);
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NONE
-
-#include <sys/resource.h>
-
-static void sandbox_common()
-{
-#if !SYZ_THREADED
-#if SYZ_EXECUTOR
- if (!flag_threaded)
-#endif
- if (setsid() == -1)
- fail("setsid failed");
-#endif
- struct rlimit 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);
- rlim.rlim_cur = rlim.rlim_max = 256;
- setrlimit(RLIMIT_NOFILE, &rlim);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-
-static void loop();
-
-static int do_sandbox_none(void)
-{
- sandbox_common();
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun(procid);
-#endif
- loop();
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID
-
-#include <sys/wait.h>
-
-static void loop();
-
-static int wait_for_loop(int pid)
-{
- if (pid < 0)
- fail("sandbox fork failed");
- debug("spawned loop pid %d\n", pid);
- int status = 0;
- while (waitpid(-1, &status, WUNTRACED) != pid) {
- }
- return WEXITSTATUS(status);
-}
-
-#define SYZ_HAVE_SANDBOX_SETUID 1
-static int do_sandbox_setuid(void)
-{
- int pid = fork();
- if (pid != 0)
- return wait_for_loop(pid);
-
- sandbox_common();
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun(procid);
-#endif
-
- char pwbuf[1024];
- struct passwd *pw, pwres;
- if (getpwnam_r("nobody", &pwres, pwbuf, sizeof(pwbuf), &pw) != 0 || !pw)
- fail("getpwnam_r(\"nobody\") failed");
-
- if (setgroups(0, NULL))
- fail("failed to setgroups");
- if (setgid(pw->pw_gid))
- fail("failed to setgid");
- if (setuid(pw->pw_uid))
- fail("failed to setuid");
-
- loop();
- doexit(1);
-}
-#endif
-
-#elif GOOS_fuchsia
-
-#include <fcntl.h>
-#include <lib/fdio/directory.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <time.h>
-#include <unistd.h>
-#include <utime.h>
-#include <zircon/process.h>
-#include <zircon/status.h>
-#include <zircon/syscalls.h>
-
-#if SYZ_EXECUTOR || __NR_get_root_resource
-#include <lib/ddk/driver.h>
-#endif
-
-#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
-#include <pthread.h>
-#include <setjmp.h>
-#include <zircon/syscalls/debug.h>
-#include <zircon/syscalls/exception.h>
-#include <zircon/syscalls/object.h>
-
-static __thread int skip_segv;
-static __thread jmp_buf segv_env;
-
-static void segv_handler(void)
-{
- if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED)) {
- debug("recover: skipping\n");
- longjmp(segv_env, 1);
- }
- debug("recover: exiting\n");
- doexit(SIGSEGV);
-}
-
-static zx_status_t update_exception_thread_regs(zx_handle_t exception)
-{
- zx_handle_t thread;
- zx_status_t status = zx_exception_get_thread(exception, &thread);
- if (status != ZX_OK) {
- debug("zx_exception_get_thread failed: %s (%d)\n", zx_status_get_string(status), status);
- return status;
- }
-
- zx_thread_state_general_regs_t regs;
- status = zx_thread_read_state(thread, ZX_THREAD_STATE_GENERAL_REGS,
- &regs, sizeof(regs));
- if (status != ZX_OK) {
- debug("zx_thread_read_state failed: %d %s (%d)\n",
- (int)sizeof(regs), zx_status_get_string(status), status);
- } else {
-#if GOARCH_amd64
- regs.rip = (uint64)(void*)&segv_handler;
-#elif GOARCH_arm64
- regs.pc = (uint64)(void*)&segv_handler;
-#else
-#error "unsupported arch"
-#endif
- status = zx_thread_write_state(thread, ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs));
- if (status != ZX_OK) {
- debug("zx_thread_write_state failed: %s (%d)\n", zx_status_get_string(status), status);
- }
- }
-
- zx_handle_close(thread);
- return status;
-}
-
-static void* ex_handler(void* arg)
-{
- zx_handle_t exception_channel = (zx_handle_t)(long)arg;
- for (int i = 0; i < 10000; i++) {
- zx_status_t status = zx_object_wait_one(exception_channel, ZX_CHANNEL_READABLE, ZX_TIME_INFINITE, NULL);
- if (status != ZX_OK) {
- debug("zx_object_wait_one failed: %s (%d)\n", zx_status_get_string(status), status);
- continue;
- }
-
- zx_exception_info_t info;
- zx_handle_t exception;
- status = zx_channel_read(exception_channel, 0, &info, &exception, sizeof(info), 1, NULL, NULL);
- if (status != ZX_OK) {
- debug("zx_channel_read failed: %s (%d)\n", zx_status_get_string(status), status);
- continue;
- }
-
- debug("got exception: type=%d tid=%llu\n", info.type, (unsigned long long)(info.tid));
- status = update_exception_thread_regs(exception);
- if (status != ZX_OK) {
- debug("failed to update exception thread registers: %s (%d)\n", zx_status_get_string(status), status);
- }
-
- uint32 state = ZX_EXCEPTION_STATE_HANDLED;
- status = zx_object_set_property(exception, ZX_PROP_EXCEPTION_STATE, &state, sizeof(state));
- if (status != ZX_OK) {
- debug("zx_object_set_property(ZX_PROP_EXCEPTION_STATE) failed: %s (%d)\n", zx_status_get_string(status), status);
- }
- zx_handle_close(exception);
- }
- doexit(1);
- return 0;
-}
-
-static void install_segv_handler(void)
-{
- zx_status_t status;
- zx_handle_t exception_channel;
- if ((status = zx_task_create_exception_channel(zx_process_self(), 0, &exception_channel)) != ZX_OK)
- failmsg("zx_task_create_exception_channel failed",
- "status=%s (%d)", zx_status_get_string(status), status);
- pthread_t th;
- if (pthread_create(&th, 0, ex_handler, (void*)(long)exception_channel))
- fail("pthread_create failed");
-}
-
-#define NONFAILING(...) \
- ({ \
- int ok = 1; \
- __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- if (sigsetjmp(segv_env, 0) == 0) { \
- __VA_ARGS__; \
- } else \
- ok = 0; \
- __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- ok; \
- })
-#endif
-
-#if SYZ_EXECUTOR || SYZ_THREADED
-#include <unistd.h>
-typedef struct {
- int state;
-} event_t;
-
-static void event_init(event_t* ev)
-{
- ev->state = 0;
-}
-
-static void event_reset(event_t* ev)
-{
- ev->state = 0;
-}
-
-static void event_set(event_t* ev)
-{
- if (ev->state)
- exitf("event already set");
- __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
-}
-
-static void event_wait(event_t* ev)
-{
- while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
- usleep(200);
-}
-
-static int event_isset(event_t* ev)
-{
- return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
-}
-
-static int event_timedwait(event_t* ev, uint64 timeout_ms)
-{
- uint64 start = current_time_ms();
- for (;;) {
- if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED))
- return 1;
- if (current_time_ms() - start > timeout_ms)
- return 0;
- usleep(200);
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_mmap
-long syz_mmap(size_t addr, size_t size)
-{
- zx_handle_t root = zx_vmar_root_self();
- zx_info_vmar_t info;
- zx_status_t status = zx_object_get_info(root, ZX_INFO_VMAR, &info, sizeof(info), 0, 0);
- if (status != ZX_OK) {
- debug("zx_object_get_info(ZX_INFO_VMAR) failed: %s (%d)", zx_status_get_string(status), status);
- return status;
- }
- zx_handle_t vmo;
- status = zx_vmo_create(size, 0, &vmo);
- if (status != ZX_OK) {
- debug("zx_vmo_create failed: %s (%d)\n", zx_status_get_string(status), status);
- return status;
- }
-
- uintptr_t mapped_addr;
- status = zx_vmar_map(root, ZX_VM_FLAG_SPECIFIC_OVERWRITE | ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE,
- addr - info.base, vmo, 0, size,
- &mapped_addr);
-
- zx_status_t close_vmo_status = zx_handle_close(vmo);
- if (close_vmo_status != ZX_OK) {
- debug("zx_handle_close(vmo) failed with: %s (%d)\n", zx_status_get_string(close_vmo_status), close_vmo_status);
- }
- return status;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_process_self
-static long syz_process_self(void)
-{
- return zx_process_self();
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_thread_self
-static long syz_thread_self(void)
-{
- return zx_thread_self();
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_vmar_root_self
-static long syz_vmar_root_self(void)
-{
- return zx_vmar_root_self();
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_job_default
-static long syz_job_default(void)
-{
- return zx_job_default();
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_future_time
-static long syz_future_time(volatile long when)
-{
- zx_time_t delta_ms = 10000;
- switch (when) {
- case 0:
- delta_ms = 5;
- break;
- case 1:
- delta_ms = 30;
- break;
- }
- zx_time_t now = 0;
- zx_clock_read(ZX_CLOCK_MONOTONIC, &now);
- return now + delta_ms * 1000 * 1000;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-static void loop();
-static int do_sandbox_none(void)
-{
- loop();
- return 0;
-}
-#endif
-#define CAST(f) ({void* p = (void*)f; p; })
-
-#elif GOOS_linux
-
-#include <stdlib.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#if SYZ_EXECUTOR
-const int kExtraCoverSize = 256 << 10;
-struct cover_t;
-static void cover_reset(cover_t* cov);
-#endif
-
-#if SYZ_EXECUTOR || SYZ_THREADED
-#include <linux/futex.h>
-#include <pthread.h>
-
-typedef struct {
- int state;
-} event_t;
-
-static void event_init(event_t* ev)
-{
- ev->state = 0;
-}
-
-static void event_reset(event_t* ev)
-{
- ev->state = 0;
-}
-
-static void event_set(event_t* ev)
-{
- if (ev->state)
- exitf("event already set");
- __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
- syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
-}
-
-static void event_wait(event_t* ev)
-{
- while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
- syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
-}
-
-static int event_isset(event_t* ev)
-{
- return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
-}
-
-static int event_timedwait(event_t* ev, uint64 timeout)
-{
- uint64 start = current_time_ms();
- uint64 now = start;
- for (;;) {
- uint64 remain = timeout - (now - start);
- struct timespec ts;
- ts.tv_sec = remain / 1000;
- ts.tv_nsec = (remain % 1000) * 1000 * 1000;
- syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
- if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
- return 1;
- now = current_time_ms();
- if (now - start > timeout)
- return 0;
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_REPEAT || SYZ_NET_INJECTION || SYZ_FAULT || SYZ_SANDBOX_NONE || \
- SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID || \
- SYZ_FAULT || SYZ_LEAK || SYZ_BINFMT_MISC || SYZ_SYSCTL || \
- ((__NR_syz_usb_connect || __NR_syz_usb_connect_ath9k) && USB_DEBUG) || \
- __NR_syz_usbip_server_init
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-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) {
- int err = errno;
- close(fd);
- debug("write(%s) failed: %d\n", file, err);
- errno = err;
- return false;
- }
- close(fd);
- return true;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || SYZ_802154 || \
- __NR_syz_genetlink_get_family_id || __NR_syz_80211_inject_frame || __NR_syz_80211_join_ibss || SYZ_NIC_VF
-#include <arpa/inet.h>
-#include <errno.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <linux/genetlink.h>
-#include <linux/if_addr.h>
-#include <linux/if_link.h>
-#include <linux/in6.h>
-#include <linux/neighbour.h>
-#include <linux/net.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/veth.h>
-
-struct nlmsg {
- char* pos;
- int nesting;
- struct nlattr* nested[8];
- char buf[4096];
-};
-
-static void netlink_init(struct nlmsg* nlmsg, int typ, int flags,
- const void* data, int size)
-{
- memset(nlmsg, 0, sizeof(*nlmsg));
- struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
- hdr->nlmsg_type = typ;
- hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
- memcpy(hdr + 1, data, size);
- nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size);
-}
-
-static void netlink_attr(struct nlmsg* nlmsg, int typ,
- const void* data, int size)
-{
- struct nlattr* attr = (struct nlattr*)nlmsg->pos;
- attr->nla_len = sizeof(*attr) + size;
- attr->nla_type = typ;
- if (size > 0)
- memcpy(attr + 1, data, size);
- nlmsg->pos += NLMSG_ALIGN(attr->nla_len);
-}
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_802154
-static void netlink_nest(struct nlmsg* nlmsg, int typ)
-{
- struct nlattr* attr = (struct nlattr*)nlmsg->pos;
- attr->nla_type = typ;
- nlmsg->pos += sizeof(*attr);
- nlmsg->nested[nlmsg->nesting++] = attr;
-}
-
-static void netlink_done(struct nlmsg* nlmsg)
-{
- struct nlattr* attr = nlmsg->nested[--nlmsg->nesting];
- attr->nla_len = nlmsg->pos - (char*)attr;
-}
-
-#if SYZ_EXECUTOR || SYZ_NIC_VF
-#include <ifaddrs.h>
-#include <linux/ethtool.h>
-#include <linux/sockios.h>
-#include <sys/ioctl.h>
-
-struct vf_intf {
- char pass_thru_intf[IFNAMSIZ];
- int ppid;
-};
-
-static struct vf_intf vf_intf;
-
-static void find_vf_interface(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_nic_vf)
- return;
-#endif
- struct ifaddrs* addresses = NULL;
- int pid = getpid();
- int ret = 0;
-
- memset(&vf_intf, 0, sizeof(struct vf_intf));
-
- debug("Checking for VF pass-thru interface.\n");
- if (getifaddrs(&addresses) == -1) {
- debug("%s: getifaddrs() failed.\n", __func__);
- return;
- }
-
- int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (fd < 0) {
- debug("%s: socket() failed.\n", __func__);
- return;
- }
- struct ifreq ifr;
- struct ethtool_drvinfo drvinfo;
- struct ifaddrs* address = addresses;
-
- while (address) {
- debug("ifa_name: %s\n", address->ifa_name);
- memset(&ifr, 0, sizeof(struct ifreq));
- strcpy(ifr.ifr_name, address->ifa_name);
- memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
- drvinfo.cmd = ETHTOOL_GDRVINFO;
- ifr.ifr_data = (caddr_t)&drvinfo;
- ret = ioctl(fd, SIOCETHTOOL, &ifr);
-
- if (ret < 0) {
- debug("%s: ioctl() failed.\n", __func__);
- } else if (strlen(drvinfo.bus_info)) {
- debug("bus_info: %s, strlen(drvinfo.bus_info)=%zu\n",
- drvinfo.bus_info, strlen(drvinfo.bus_info));
- if (strcmp(drvinfo.bus_info, "0000:00:11.0") == 0) {
- if (strlen(address->ifa_name) < IFNAMSIZ) {
- strncpy(vf_intf.pass_thru_intf,
- address->ifa_name, IFNAMSIZ);
- vf_intf.ppid = pid;
- } else {
- debug("%s: %d strlen(%s) >= IFNAMSIZ.\n",
- __func__, pid, address->ifa_name);
- }
- break;
- }
- }
- address = address->ifa_next;
- }
- freeifaddrs(addresses);
- if (!vf_intf.ppid) {
- memset(&vf_intf, 0, sizeof(struct vf_intf));
- debug("%s: %d could not find VF pass-thru interface.\n", __func__, pid);
- return;
- }
- debug("%s: %d found VF pass-thru interface %s\n",
- __func__, pid, vf_intf.pass_thru_intf);
-}
-#endif
-
-#endif
-
-static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
- uint16 reply_type, int* reply_len, bool dofail)
-{
-#if SYZ_EXECUTOR
- if (in_execute_one && dofail) {
- failmsg("invalid netlink_send_ext arguments", "dofail is true during syscall execution");
- }
-#endif
- if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting)
- fail("nlmsg overflow/bad nesting");
- struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
- hdr->nlmsg_len = nlmsg->pos - nlmsg->buf;
- struct sockaddr_nl addr;
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
- ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr));
- if (n != (ssize_t)hdr->nlmsg_len) {
- if (dofail)
- failmsg("netlink_send_ext: short netlink write", "wrote=%zd, want=%d", n, hdr->nlmsg_len);
- debug("netlink_send_ext: short netlink write: %zd/%d errno=%d\n", n, hdr->nlmsg_len, errno);
- return -1;
- }
- n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
- if (reply_len)
- *reply_len = 0;
- if (n < 0) {
- if (dofail)
- fail("netlink_send_ext: netlink read failed");
- debug("netlink_send_ext: netlink read failed: errno=%d\n", errno);
- return -1;
- }
- if (n < (ssize_t)sizeof(struct nlmsghdr)) {
- errno = EINVAL;
- if (dofail)
- failmsg("netlink_send_ext: short netlink read", "read=%zd", n);
- debug("netlink_send_ext: short netlink read: %zd\n", n);
- return -1;
- }
- if (hdr->nlmsg_type == NLMSG_DONE)
- return 0;
- if (reply_len && hdr->nlmsg_type == reply_type) {
- *reply_len = n;
- return 0;
- }
- if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) {
- errno = EINVAL;
- if (dofail)
- failmsg("netlink_send_ext: short netlink read", "read=%zd", n);
- debug("netlink_send_ext: short netlink read: %zd\n", n);
- return -1;
- }
- if (hdr->nlmsg_type != NLMSG_ERROR) {
- errno = EINVAL;
- if (dofail)
- failmsg("netlink_send_ext: bad netlink ack type", "type=%d", hdr->nlmsg_type);
- debug("netlink_send_ext: short netlink ack: %d\n", hdr->nlmsg_type);
- return -1;
- }
- errno = -((struct nlmsgerr*)(hdr + 1))->error;
- return -errno;
-}
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || SYZ_802154
-static int netlink_send(struct nlmsg* nlmsg, int sock)
-{
- return netlink_send_ext(nlmsg, sock, 0, NULL, true);
-}
-#endif
-
-static int netlink_query_family_id(struct nlmsg* nlmsg, int sock, const char* family_name, bool dofail)
-{
- struct genlmsghdr genlhdr;
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = CTRL_CMD_GETFAMILY;
- netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, strnlen(family_name, GENL_NAMSIZ - 1) + 1);
- int n = 0;
- int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail);
- if (err < 0) {
- debug("netlink: failed to get family id for %.*s: %s\n", GENL_NAMSIZ, family_name, strerror(errno));
- return -1;
- }
- uint16 id = 0;
- struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
- for (; (char*)attr < nlmsg->buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
- if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
- id = *(uint16*)(attr + 1);
- break;
- }
- }
- if (!id) {
- debug("netlink: failed to parse family id for %.*s\n", GENL_NAMSIZ, family_name);
- errno = EINVAL;
- return -1;
- }
- recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
-
- return id;
-}
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_DEVLINK_PCI
-static int netlink_next_msg(struct nlmsg* nlmsg, unsigned int offset,
- unsigned int total_len)
-{
- struct nlmsghdr* hdr = (struct nlmsghdr*)(nlmsg->buf + offset);
-
- if (offset == total_len || offset + hdr->nlmsg_len > total_len)
- return -1;
- return hdr->nlmsg_len;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_802154
-static void netlink_add_device_impl(struct nlmsg* nlmsg, const char* type,
- const char* name, bool up)
-{
- struct ifinfomsg hdr;
- memset(&hdr, 0, sizeof(hdr));
- if (up)
- hdr.ifi_flags = hdr.ifi_change = IFF_UP;
- netlink_init(nlmsg, RTM_NEWLINK, NLM_F_EXCL | NLM_F_CREATE, &hdr, sizeof(hdr));
- if (name)
- netlink_attr(nlmsg, IFLA_IFNAME, name, strlen(name));
- netlink_nest(nlmsg, IFLA_LINKINFO);
- netlink_attr(nlmsg, IFLA_INFO_KIND, type, strlen(type));
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
-static void netlink_add_device(struct nlmsg* nlmsg, int sock, const char* type,
- const char* name)
-{
- netlink_add_device_impl(nlmsg, type, name, false);
- netlink_done(nlmsg);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: adding device %s type %s: %s\n", name, type, strerror(errno));
- }
-}
-
-static void netlink_add_veth(struct nlmsg* nlmsg, int sock, const char* name,
- const char* peer)
-{
- netlink_add_device_impl(nlmsg, "veth", name, false);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- netlink_nest(nlmsg, VETH_INFO_PEER);
- nlmsg->pos += sizeof(struct ifinfomsg);
- netlink_attr(nlmsg, IFLA_IFNAME, peer, strlen(peer));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: adding device %s type veth peer %s: %s\n", name, peer, strerror(errno));
- }
-}
-
-static void netlink_add_xfrm(struct nlmsg* nlmsg, int sock, const char* name)
-{
- netlink_add_device_impl(nlmsg, "xfrm", name, true);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- int if_id = 1;
- netlink_attr(nlmsg, 2, &if_id, sizeof(if_id));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: adding device %s type xfrm if_id %d: %s\n", name, if_id, strerror(errno));
- }
-}
-
-static void netlink_add_hsr(struct nlmsg* nlmsg, int sock, const char* name,
- const char* slave1, const char* slave2)
-{
- netlink_add_device_impl(nlmsg, "hsr", name, false);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- int ifindex1 = if_nametoindex(slave1);
- netlink_attr(nlmsg, IFLA_HSR_SLAVE1, &ifindex1, sizeof(ifindex1));
- int ifindex2 = if_nametoindex(slave2);
- netlink_attr(nlmsg, IFLA_HSR_SLAVE2, &ifindex2, sizeof(ifindex2));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: adding device %s type hsr slave1 %s slave2 %s: %s\n", name, slave1, slave2, strerror(errno));
- }
-}
-
-static void netlink_add_linked(struct nlmsg* nlmsg, int sock, const char* type, const char* name, const char* link)
-{
- netlink_add_device_impl(nlmsg, type, name, false);
- netlink_done(nlmsg);
- int ifindex = if_nametoindex(link);
- netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: adding device %s type %s link %s: %s\n", name, type, link, strerror(errno));
- }
-}
-
-static void netlink_add_vlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16 id, uint16 proto)
-{
- netlink_add_device_impl(nlmsg, "vlan", name, false);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- netlink_attr(nlmsg, IFLA_VLAN_ID, &id, sizeof(id));
- netlink_attr(nlmsg, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int ifindex = if_nametoindex(link);
- netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: add %s type vlan link %s id %d: %s\n", name, link, id, strerror(errno));
- }
-}
-
-static void netlink_add_macvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link)
-{
- netlink_add_device_impl(nlmsg, "macvlan", name, false);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- uint32 mode = MACVLAN_MODE_BRIDGE;
- netlink_attr(nlmsg, IFLA_MACVLAN_MODE, &mode, sizeof(mode));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int ifindex = if_nametoindex(link);
- netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: add %s type macvlan link %s mode %d: %s\n", name, link, mode, strerror(errno));
- }
-}
-
-static void netlink_add_geneve(struct nlmsg* nlmsg, int sock, const char* name, uint32 vni, struct in_addr* addr4, struct in6_addr* addr6)
-{
- netlink_add_device_impl(nlmsg, "geneve", name, false);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- netlink_attr(nlmsg, IFLA_GENEVE_ID, &vni, sizeof(vni));
- if (addr4)
- netlink_attr(nlmsg, IFLA_GENEVE_REMOTE, addr4, sizeof(*addr4));
- if (addr6)
- netlink_attr(nlmsg, IFLA_GENEVE_REMOTE6, addr6, sizeof(*addr6));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: add %s type geneve vni %u: %s\n", name, vni, strerror(errno));
- }
-}
-
-#define IFLA_IPVLAN_FLAGS 2
-#define IPVLAN_MODE_L3S 2
-#undef IPVLAN_F_VEPA
-#define IPVLAN_F_VEPA 2
-
-static void netlink_add_ipvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16 mode, uint16 flags)
-{
- netlink_add_device_impl(nlmsg, "ipvlan", name, false);
- netlink_nest(nlmsg, IFLA_INFO_DATA);
- netlink_attr(nlmsg, IFLA_IPVLAN_MODE, &mode, sizeof(mode));
- netlink_attr(nlmsg, IFLA_IPVLAN_FLAGS, &flags, sizeof(flags));
- netlink_done(nlmsg);
- netlink_done(nlmsg);
- int ifindex = if_nametoindex(link);
- netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: add %s type ipvlan link %s mode %d: %s\n", name, link, mode, strerror(errno));
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_802154
-static void netlink_device_change(struct nlmsg* nlmsg, int sock, const char* name, bool up,
- const char* master, const void* mac, int macsize,
- const char* new_name)
-{
- struct ifinfomsg hdr;
- memset(&hdr, 0, sizeof(hdr));
- if (up)
- hdr.ifi_flags = hdr.ifi_change = IFF_UP;
- hdr.ifi_index = if_nametoindex(name);
- netlink_init(nlmsg, RTM_NEWLINK, 0, &hdr, sizeof(hdr));
- if (new_name)
- netlink_attr(nlmsg, IFLA_IFNAME, new_name, strlen(new_name));
- if (master) {
- int ifindex = if_nametoindex(master);
- netlink_attr(nlmsg, IFLA_MASTER, &ifindex, sizeof(ifindex));
- }
- if (macsize)
- netlink_attr(nlmsg, IFLA_ADDRESS, mac, macsize);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: device %s up master %s: %s\n", name, master ? master : "NULL", strerror(errno));
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION
-static int netlink_add_addr(struct nlmsg* nlmsg, int sock, const char* dev,
- const void* addr, int addrsize)
-{
- struct ifaddrmsg hdr;
- memset(&hdr, 0, sizeof(hdr));
- hdr.ifa_family = addrsize == 4 ? AF_INET : AF_INET6;
- hdr.ifa_prefixlen = addrsize == 4 ? 24 : 120;
- hdr.ifa_scope = RT_SCOPE_UNIVERSE;
- hdr.ifa_index = if_nametoindex(dev);
- netlink_init(nlmsg, RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, &hdr, sizeof(hdr));
- netlink_attr(nlmsg, IFA_LOCAL, addr, addrsize);
- netlink_attr(nlmsg, IFA_ADDRESS, addr, addrsize);
- return netlink_send(nlmsg, sock);
-}
-
-static void netlink_add_addr4(struct nlmsg* nlmsg, int sock,
- const char* dev, const char* addr)
-{
- struct in_addr in_addr;
- inet_pton(AF_INET, addr, &in_addr);
- int err = netlink_add_addr(nlmsg, sock, dev, &in_addr, sizeof(in_addr));
- if (err < 0) {
- debug("netlink: add addr %s dev %s: %s\n", addr, dev, strerror(errno));
- }
-}
-
-static void netlink_add_addr6(struct nlmsg* nlmsg, int sock,
- const char* dev, const char* addr)
-{
- struct in6_addr in6_addr;
- inet_pton(AF_INET6, addr, &in6_addr);
- int err = netlink_add_addr(nlmsg, sock, dev, &in6_addr, sizeof(in6_addr));
- if (err < 0) {
- debug("netlink: add addr %s dev %s: %s\n", addr, dev, strerror(errno));
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
-static void netlink_add_neigh(struct nlmsg* nlmsg, int sock, const char* name,
- const void* addr, int addrsize, const void* mac, int macsize)
-{
- struct ndmsg hdr;
- memset(&hdr, 0, sizeof(hdr));
- hdr.ndm_family = addrsize == 4 ? AF_INET : AF_INET6;
- hdr.ndm_ifindex = if_nametoindex(name);
- hdr.ndm_state = NUD_PERMANENT;
- netlink_init(nlmsg, RTM_NEWNEIGH, NLM_F_EXCL | NLM_F_CREATE, &hdr, sizeof(hdr));
- netlink_attr(nlmsg, NDA_DST, addr, addrsize);
- netlink_attr(nlmsg, NDA_LLADDR, mac, macsize);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("netlink: add neigh %s addr %d lladdr %d: %s\n", name, addrsize, macsize, strerror(errno));
- }
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || SYZ_802154
-static struct nlmsg nlmsg;
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-
-#include <linux/if_ether.h>
-#include <linux/if_tun.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-
-static int tunfd = -1;
-
-#define TUN_IFACE "syz_tun"
-#define LOCAL_MAC 0xaaaaaaaaaaaa
-#define REMOTE_MAC 0xaaaaaaaaaabb
-#define LOCAL_IPV4 "172.20.20.170"
-#define REMOTE_IPV4 "172.20.20.187"
-#define LOCAL_IPV6 "fe80::aa"
-#define REMOTE_IPV6 "fe80::bb"
-
-#ifndef IFF_NAPI
-#define IFF_NAPI 0x0010
-#endif
-#if ENABLE_NAPI_FRAGS
-static int tun_frags_enabled;
-#ifndef IFF_NAPI_FRAGS
-#define IFF_NAPI_FRAGS 0x0020
-#endif
-#endif
-
-static void initialize_tun(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_injection)
- return;
-#endif
- tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
- if (tunfd == -1) {
-#if SYZ_EXECUTOR
- fail("tun: can't open /dev/net/tun");
-#else
- printf("tun: can't open /dev/net/tun: please enable CONFIG_TUN=y\n");
- printf("otherwise fuzzing or reproducing might not work as intended\n");
- return;
-#endif
- }
- const int kTunFd = 200;
- if (dup2(tunfd, kTunFd) < 0)
- fail("dup2(tunfd, kTunFd) failed");
- close(tunfd);
- tunfd = kTunFd;
-
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, TUN_IFACE, IFNAMSIZ);
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
-#if ENABLE_NAPI_FRAGS
- ifr.ifr_flags |= IFF_NAPI | IFF_NAPI_FRAGS;
-#endif
- if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0) {
-#if ENABLE_NAPI_FRAGS
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0)
-#endif
- fail("tun: ioctl(TUNSETIFF) failed");
- }
-#if ENABLE_NAPI_FRAGS
- if (ioctl(tunfd, TUNGETIFF, (void*)&ifr) < 0)
- fail("tun: ioctl(TUNGETIFF) failed");
- tun_frags_enabled = (ifr.ifr_flags & IFF_NAPI_FRAGS) != 0;
- debug("tun_frags_enabled=%d\n", tun_frags_enabled);
-#endif
- char sysctl[64];
- sprintf(sysctl, "/proc/sys/net/ipv6/conf/%s/accept_dad", TUN_IFACE);
- write_file(sysctl, "0");
- sprintf(sysctl, "/proc/sys/net/ipv6/conf/%s/router_solicitations", TUN_IFACE);
- write_file(sysctl, "0");
-
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (sock == -1)
- fail("socket(AF_NETLINK) failed");
-
- netlink_add_addr4(&nlmsg, sock, TUN_IFACE, LOCAL_IPV4);
- netlink_add_addr6(&nlmsg, sock, TUN_IFACE, LOCAL_IPV6);
- uint64 macaddr = REMOTE_MAC;
- struct in_addr in_addr;
- inet_pton(AF_INET, REMOTE_IPV4, &in_addr);
- netlink_add_neigh(&nlmsg, sock, TUN_IFACE, &in_addr, sizeof(in_addr), &macaddr, ETH_ALEN);
- struct in6_addr in6_addr;
- inet_pton(AF_INET6, REMOTE_IPV6, &in6_addr);
- netlink_add_neigh(&nlmsg, sock, TUN_IFACE, &in6_addr, sizeof(in6_addr), &macaddr, ETH_ALEN);
- macaddr = LOCAL_MAC;
- netlink_device_change(&nlmsg, sock, TUN_IFACE, true, 0, &macaddr, ETH_ALEN, NULL);
- close(sock);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_init_net_socket || SYZ_DEVLINK_PCI || __NR_syz_socket_connect_nvme_tcp
-const int kInitNetNsFd = 201;
-#endif
-
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI || SYZ_NET_DEVICES
-
-#include <linux/genetlink.h>
-#include <stdbool.h>
-
-#define DEVLINK_FAMILY_NAME "devlink"
-
-#define DEVLINK_CMD_PORT_GET 5
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
-#define DEVLINK_CMD_RELOAD 37
-#endif
-#define DEVLINK_ATTR_BUS_NAME 1
-#define DEVLINK_ATTR_DEV_NAME 2
-#define DEVLINK_ATTR_NETDEV_NAME 7
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
-#define DEVLINK_ATTR_NETNS_FD 138
-#endif
-
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
-static void netlink_devlink_netns_move(const char* bus_name, const char* dev_name, int netns_fd)
-{
- struct genlmsghdr genlhdr;
- int sock;
- int id, err;
-
- sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock == -1)
- fail("socket(AF_NETLINK) failed");
-
- id = netlink_query_family_id(&nlmsg, sock, DEVLINK_FAMILY_NAME, true);
- if (id == -1)
- goto error;
-
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = DEVLINK_CMD_RELOAD;
- netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(&nlmsg, DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1);
- netlink_attr(&nlmsg, DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1);
- netlink_attr(&nlmsg, DEVLINK_ATTR_NETNS_FD, &netns_fd, sizeof(netns_fd));
- err = netlink_send(&nlmsg, sock);
- if (err < 0) {
- debug("netlink: failed to move devlink instance %s/%s into network namespace: %s\n",
- bus_name, dev_name, strerror(errno));
- }
-error:
- close(sock);
-}
-#endif
-
-static struct nlmsg nlmsg2;
-
-static void initialize_devlink_ports(const char* bus_name, const char* dev_name,
- const char* netdev_prefix)
-{
- struct genlmsghdr genlhdr;
- int len, total_len, id, err, offset;
- uint16 netdev_index;
-
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock == -1)
- fail("socket(AF_NETLINK) failed");
-
- int rtsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (rtsock == -1)
- fail("socket(AF_NETLINK) failed");
-
- id = netlink_query_family_id(&nlmsg, sock, DEVLINK_FAMILY_NAME, true);
- if (id == -1)
- goto error;
-
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = DEVLINK_CMD_PORT_GET;
- netlink_init(&nlmsg, id, NLM_F_DUMP, &genlhdr, sizeof(genlhdr));
- netlink_attr(&nlmsg, DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1);
- netlink_attr(&nlmsg, DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1);
-
- err = netlink_send_ext(&nlmsg, sock, id, &total_len, true);
- if (err < 0) {
- debug("netlink: failed to get port get reply: %s\n", strerror(errno));
- goto error;
- }
-
- offset = 0;
- netdev_index = 0;
- while ((len = netlink_next_msg(&nlmsg, offset, total_len)) != -1) {
- struct nlattr* attr = (struct nlattr*)(nlmsg.buf + offset + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
- for (; (char*)attr < nlmsg.buf + offset + len; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
- if (attr->nla_type == DEVLINK_ATTR_NETDEV_NAME) {
- char* port_name;
- char netdev_name[IFNAMSIZ];
- port_name = (char*)(attr + 1);
- snprintf(netdev_name, sizeof(netdev_name), "%s%d", netdev_prefix, netdev_index);
- netlink_device_change(&nlmsg2, rtsock, port_name, true, 0, 0, 0, netdev_name);
- break;
- }
- }
- offset += len;
- netdev_index++;
- }
-error:
- close(rtsock);
- close(sock);
-}
-
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
-#include <fcntl.h>
-#include <sched.h>
-
-static void initialize_devlink_pci(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_devlink_pci)
- return;
-#endif
- int netns = open("/proc/self/ns/net", O_RDONLY);
- if (netns == -1)
- fail("open(/proc/self/ns/net) failed");
- int ret = setns(kInitNetNsFd, 0);
- if (ret == -1)
- fail("set_ns(init_netns_fd) failed");
- netlink_devlink_netns_move("pci", "0000:00:10.0", netns);
- ret = setns(netns, 0);
- if (ret == -1)
- fail("set_ns(this_netns_fd) failed");
- close(netns);
-
- initialize_devlink_ports("pci", "0000:00:10.0", "netpci");
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_WIFI || __NR_syz_80211_inject_frame || __NR_syz_80211_join_ibss
-
-#define WIFI_INITIAL_DEVICE_COUNT 2
-#define WIFI_MAC_BASE \
- { \
- 0x08, 0x02, 0x11, 0x00, 0x00, 0x00 \
- }
-#define WIFI_IBSS_BSSID \
- { \
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50 \
- }
-#define WIFI_IBSS_SSID \
- { \
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 \
- }
-#define WIFI_DEFAULT_FREQUENCY 2412
-#define WIFI_DEFAULT_SIGNAL 0
-#define WIFI_DEFAULT_RX_RATE 1
-#define HWSIM_CMD_REGISTER 1
-#define HWSIM_CMD_FRAME 2
-#define HWSIM_CMD_NEW_RADIO 4
-#define HWSIM_ATTR_SUPPORT_P2P_DEVICE 14
-#define HWSIM_ATTR_PERM_ADDR 22
-
-#endif
-
-#if SYZ_EXECUTOR || SYZ_WIFI || __NR_syz_80211_join_ibss
-#include <linux/genetlink.h>
-#include <linux/if_ether.h>
-#include <linux/nl80211.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-#include <stdbool.h>
-#include <sys/ioctl.h>
-#define IF_OPER_UP 6
-struct join_ibss_props {
- int wiphy_freq;
- bool wiphy_freq_fixed;
- uint8* mac;
- uint8* ssid;
- int ssid_len;
-};
-
-static int set_interface_state(const char* interface_name, int on)
-{
- struct ifreq ifr;
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- debug("set_interface_state: failed to open socket, errno %d\n", errno);
- return -1;
- }
-
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, interface_name);
- int ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
- if (ret < 0) {
- debug("set_interface_state: failed to execute SIOCGIFFLAGS, ret %d\n", ret);
- close(sock);
- return -1;
- }
-
- if (on)
- ifr.ifr_flags |= IFF_UP;
- else
- ifr.ifr_flags &= ~IFF_UP;
-
- ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
- close(sock);
- if (ret < 0) {
- debug("set_interface_state: failed to execute SIOCSIFFLAGS, ret %d\n", ret);
- return -1;
- }
- return 0;
-}
-
-static int nl80211_set_interface(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32 ifindex,
- uint32 iftype, bool dofail)
-{
- struct genlmsghdr genlhdr;
-
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = NL80211_CMD_SET_INTERFACE;
- netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
- netlink_attr(nlmsg, NL80211_ATTR_IFTYPE, &iftype, sizeof(iftype));
- int err = netlink_send_ext(nlmsg, sock, 0, NULL, dofail);
- if (err < 0) {
- debug("nl80211_set_interface failed: %s\n", strerror(errno));
- }
- return err;
-}
-
-static int nl80211_join_ibss(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32 ifindex,
- struct join_ibss_props* props, bool dofail)
-{
- struct genlmsghdr genlhdr;
-
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = NL80211_CMD_JOIN_IBSS;
- netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
- netlink_attr(nlmsg, NL80211_ATTR_SSID, props->ssid, props->ssid_len);
- netlink_attr(nlmsg, NL80211_ATTR_WIPHY_FREQ, &(props->wiphy_freq), sizeof(props->wiphy_freq));
- if (props->mac)
- netlink_attr(nlmsg, NL80211_ATTR_MAC, props->mac, ETH_ALEN);
- if (props->wiphy_freq_fixed)
- netlink_attr(nlmsg, NL80211_ATTR_FREQ_FIXED, NULL, 0);
- int err = netlink_send_ext(nlmsg, sock, 0, NULL, dofail);
- if (err < 0) {
- debug("nl80211_join_ibss failed: %s\n", strerror(errno));
- }
- return err;
-}
-
-static int get_ifla_operstate(struct nlmsg* nlmsg, int ifindex, bool dofail)
-{
- struct ifinfomsg info;
- memset(&info, 0, sizeof(info));
- info.ifi_family = AF_UNSPEC;
- info.ifi_index = ifindex;
-
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (sock == -1) {
- debug("get_ifla_operstate: socket failed: %d\n", errno);
- return -1;
- }
-
- netlink_init(nlmsg, RTM_GETLINK, 0, &info, sizeof(info));
- int n;
- int err = netlink_send_ext(nlmsg, sock, RTM_NEWLINK, &n, dofail);
- close(sock);
-
- if (err) {
- debug("get_ifla_operstate: failed to query: %s\n", strerror(errno));
- return -1;
- }
-
- struct rtattr* attr = IFLA_RTA(NLMSG_DATA(nlmsg->buf));
- for (; RTA_OK(attr, n); attr = RTA_NEXT(attr, n)) {
- if (attr->rta_type == IFLA_OPERSTATE)
- return *((int32_t*)RTA_DATA(attr));
- }
-
- return -1;
-}
-
-static int await_ifla_operstate(struct nlmsg* nlmsg, char* interface, int operstate, bool dofail)
-{
- int ifindex = if_nametoindex(interface);
- while (true) {
- usleep(1000);
- int ret = get_ifla_operstate(nlmsg, ifindex, dofail);
- if (ret < 0)
- return ret;
- if (ret == operstate)
- return 0;
- }
- return 0;
-}
-
-static int nl80211_setup_ibss_interface(struct nlmsg* nlmsg, int sock, int nl80211_family_id, char* interface,
- struct join_ibss_props* ibss_props, bool dofail)
-{
- int ifindex = if_nametoindex(interface);
- if (ifindex == 0) {
- debug("nl80211_setup_ibss_interface: if_nametoindex failed for %.32s, ret 0\n", interface);
- return -1;
- }
-
- int ret = nl80211_set_interface(nlmsg, sock, nl80211_family_id, ifindex, NL80211_IFTYPE_ADHOC, dofail);
- if (ret < 0) {
- debug("nl80211_setup_ibss_interface: nl80211_set_interface failed for %.32s, ret %d\n", interface, ret);
- return -1;
- }
-
- ret = set_interface_state(interface, 1);
- if (ret < 0) {
- debug("nl80211_setup_ibss_interface: set_interface_state failed for %.32s, ret %d\n", interface, ret);
- return -1;
- }
-
- ret = nl80211_join_ibss(nlmsg, sock, nl80211_family_id, ifindex, ibss_props, dofail);
- if (ret < 0) {
- debug("nl80211_setup_ibss_interface: nl80211_join_ibss failed for %.32s, ret %d\n", interface, ret);
- return -1;
- }
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_WIFI
-#include <fcntl.h>
-#include <linux/rfkill.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static int hwsim80211_create_device(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8 mac_addr[ETH_ALEN])
-{
- struct genlmsghdr genlhdr;
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = HWSIM_CMD_NEW_RADIO;
- netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(nlmsg, HWSIM_ATTR_SUPPORT_P2P_DEVICE, NULL, 0);
- netlink_attr(nlmsg, HWSIM_ATTR_PERM_ADDR, mac_addr, ETH_ALEN);
- int err = netlink_send(nlmsg, sock);
- if (err < 0) {
- debug("hwsim80211_create_device failed: %s\n", strerror(errno));
- }
- return err;
-}
-
-static void initialize_wifi_devices(void)
-{
-
-#if SYZ_EXECUTOR
- if (!flag_wifi)
- return;
-#endif
- int rfkill = open("/dev/rfkill", O_RDWR);
- if (rfkill == -1)
- fail("open(/dev/rfkill) failed");
- struct rfkill_event event = {0};
- event.type = RFKILL_TYPE_ALL;
- event.op = RFKILL_OP_CHANGE_ALL;
- if (write(rfkill, &event, sizeof(event)) != (ssize_t)(sizeof(event)))
- fail("write(/dev/rfkill) failed");
- close(rfkill);
-
- uint8 mac_addr[6] = WIFI_MAC_BASE;
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock < 0)
- fail("initialize_wifi_devices: failed to create socket");
- int hwsim_family_id = netlink_query_family_id(&nlmsg, sock, "MAC80211_HWSIM", true);
- int nl80211_family_id = netlink_query_family_id(&nlmsg, sock, "nl80211", true);
- uint8 ssid[] = WIFI_IBSS_SSID;
- uint8 bssid[] = WIFI_IBSS_BSSID;
- struct join_ibss_props ibss_props = {
- .wiphy_freq = WIFI_DEFAULT_FREQUENCY, .wiphy_freq_fixed = true, .mac = bssid, .ssid = ssid, .ssid_len = sizeof(ssid)};
-
- for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) {
- mac_addr[5] = device_id;
- int ret = hwsim80211_create_device(&nlmsg, sock, hwsim_family_id, mac_addr);
- if (ret < 0)
- failmsg("initialize_wifi_devices: failed to create device", "device=%d", device_id);
- char interface[6] = "wlan0";
- interface[4] += device_id;
-
- if (nl80211_setup_ibss_interface(&nlmsg, sock, nl80211_family_id, interface, &ibss_props, true) < 0)
- failmsg("initialize_wifi_devices: failed set up IBSS network", "device=%d", device_id);
- }
- for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) {
- char interface[6] = "wlan0";
- interface[4] += device_id;
- int ret = await_ifla_operstate(&nlmsg, interface, IF_OPER_UP, true);
- if (ret < 0)
- failmsg("initialize_wifi_devices: get_ifla_operstate failed",
- "device=%d, ret=%d", device_id, ret);
- }
-
- close(sock);
-}
-#endif
-
-#if SYZ_EXECUTOR || (SYZ_NET_DEVICES && SYZ_NIC_VF) || SYZ_SWAP
-static int runcmdline(char* cmdline)
-{
- debug("%s\n", cmdline);
- int ret = system(cmdline);
- if (ret) {
- debug("FAIL: %s\n", cmdline);
- }
- return ret;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-
-#include <linux/if_ether.h>
-#include <linux/if_tun.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#define DEV_IPV4 "172.20.20.%d"
-#define DEV_IPV6 "fe80::%02x"
-#define DEV_MAC 0x00aaaaaaaaaa
-
-static void netdevsim_add(unsigned int addr, unsigned int port_count)
-{
- write_file("/sys/bus/netdevsim/del_device", "%u", addr);
- if (write_file("/sys/bus/netdevsim/new_device", "%u %u", addr, port_count)) {
- char buf[32];
- snprintf(buf, sizeof(buf), "netdevsim%d", addr);
- initialize_devlink_ports("netdevsim", buf, "netdevsim");
- }
-}
-
-#define WG_GENL_NAME "wireguard"
-enum wg_cmd {
- WG_CMD_GET_DEVICE,
- WG_CMD_SET_DEVICE,
-};
-enum wgdevice_attribute {
- WGDEVICE_A_UNSPEC,
- WGDEVICE_A_IFINDEX,
- WGDEVICE_A_IFNAME,
- WGDEVICE_A_PRIVATE_KEY,
- WGDEVICE_A_PUBLIC_KEY,
- WGDEVICE_A_FLAGS,
- WGDEVICE_A_LISTEN_PORT,
- WGDEVICE_A_FWMARK,
- WGDEVICE_A_PEERS,
-};
-enum wgpeer_attribute {
- WGPEER_A_UNSPEC,
- WGPEER_A_PUBLIC_KEY,
- WGPEER_A_PRESHARED_KEY,
- WGPEER_A_FLAGS,
- WGPEER_A_ENDPOINT,
- WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
- WGPEER_A_LAST_HANDSHAKE_TIME,
- WGPEER_A_RX_BYTES,
- WGPEER_A_TX_BYTES,
- WGPEER_A_ALLOWEDIPS,
- WGPEER_A_PROTOCOL_VERSION,
-};
-enum wgallowedip_attribute {
- WGALLOWEDIP_A_UNSPEC,
- WGALLOWEDIP_A_FAMILY,
- WGALLOWEDIP_A_IPADDR,
- WGALLOWEDIP_A_CIDR_MASK,
-};
-
-static void netlink_wireguard_setup(void)
-{
- const char ifname_a[] = "wg0";
- const char ifname_b[] = "wg1";
- const char ifname_c[] = "wg2";
- const char private_a[] = "\xa0\x5c\xa8\x4f\x6c\x9c\x8e\x38\x53\xe2\xfd\x7a\x70\xae\x0f\xb2\x0f\xa1\x52\x60\x0c\xb0\x08\x45\x17\x4f\x08\x07\x6f\x8d\x78\x43";
- const char private_b[] = "\xb0\x80\x73\xe8\xd4\x4e\x91\xe3\xda\x92\x2c\x22\x43\x82\x44\xbb\x88\x5c\x69\xe2\x69\xc8\xe9\xd8\x35\xb1\x14\x29\x3a\x4d\xdc\x6e";
- const char private_c[] = "\xa0\xcb\x87\x9a\x47\xf5\xbc\x64\x4c\x0e\x69\x3f\xa6\xd0\x31\xc7\x4a\x15\x53\xb6\xe9\x01\xb9\xff\x2f\x51\x8c\x78\x04\x2f\xb5\x42";
- const char public_a[] = "\x97\x5c\x9d\x81\xc9\x83\xc8\x20\x9e\xe7\x81\x25\x4b\x89\x9f\x8e\xd9\x25\xae\x9f\x09\x23\xc2\x3c\x62\xf5\x3c\x57\xcd\xbf\x69\x1c";
- const char public_b[] = "\xd1\x73\x28\x99\xf6\x11\xcd\x89\x94\x03\x4d\x7f\x41\x3d\xc9\x57\x63\x0e\x54\x93\xc2\x85\xac\xa4\x00\x65\xcb\x63\x11\xbe\x69\x6b";
- const char public_c[] = "\xf4\x4d\xa3\x67\xa8\x8e\xe6\x56\x4f\x02\x02\x11\x45\x67\x27\x08\x2f\x5c\xeb\xee\x8b\x1b\xf5\xeb\x73\x37\x34\x1b\x45\x9b\x39\x22";
- const uint16 listen_a = 20001;
- const uint16 listen_b = 20002;
- const uint16 listen_c = 20003;
- const uint16 af_inet = AF_INET;
- const uint16 af_inet6 = AF_INET6;
- const struct sockaddr_in endpoint_b_v4 = {
- .sin_family = AF_INET,
- .sin_port = htons(listen_b),
- .sin_addr = {htonl(INADDR_LOOPBACK)}};
- const struct sockaddr_in endpoint_c_v4 = {
- .sin_family = AF_INET,
- .sin_port = htons(listen_c),
- .sin_addr = {htonl(INADDR_LOOPBACK)}};
- struct sockaddr_in6 endpoint_a_v6 = {
- .sin6_family = AF_INET6,
- .sin6_port = htons(listen_a)};
- endpoint_a_v6.sin6_addr = in6addr_loopback;
- struct sockaddr_in6 endpoint_c_v6 = {
- .sin6_family = AF_INET6,
- .sin6_port = htons(listen_c)};
- endpoint_c_v6.sin6_addr = in6addr_loopback;
- const struct in_addr first_half_v4 = {0};
- const struct in_addr second_half_v4 = {(uint32)htonl(128 << 24)};
- const struct in6_addr first_half_v6 = {{{0}}};
- const struct in6_addr second_half_v6 = {{{0x80}}};
- const uint8 half_cidr = 1;
- const uint16 persistent_keepalives[] = {1, 3, 7, 9, 14, 19};
-
- struct genlmsghdr genlhdr = {
- .cmd = WG_CMD_SET_DEVICE,
- .version = 1};
- int sock;
- int id, err;
-
- sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock == -1) {
- debug("socket(AF_NETLINK) failed: %s\n", strerror(errno));
- return;
- }
-
- id = netlink_query_family_id(&nlmsg, sock, WG_GENL_NAME, true);
- if (id == -1)
- goto error;
-
- netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_a, strlen(ifname_a) + 1);
- netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_a, 32);
- netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_a, 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32);
- netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4));
- netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[0], 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32);
- netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v6, sizeof(endpoint_c_v6));
- netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[1], 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- err = netlink_send(&nlmsg, sock);
- if (err < 0) {
- debug("netlink: failed to setup wireguard instance: %s\n", strerror(errno));
- }
-
- netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_b, strlen(ifname_b) + 1);
- netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_b, 32);
- netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_b, 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32);
- netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6));
- netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[2], 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32);
- netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v4, sizeof(endpoint_c_v4));
- netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[3], 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- err = netlink_send(&nlmsg, sock);
- if (err < 0) {
- debug("netlink: failed to setup wireguard instance: %s\n", strerror(errno));
- }
-
- netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_c, strlen(ifname_c) + 1);
- netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_c, 32);
- netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_c, 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32);
- netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6));
- netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[4], 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32);
- netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4));
- netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[5], 2);
- netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_nest(&nlmsg, NLA_F_NESTED | 0);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
- netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
- netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- netlink_done(&nlmsg);
- err = netlink_send(&nlmsg, sock);
- if (err < 0) {
- debug("netlink: failed to setup wireguard instance: %s\n", strerror(errno));
- }
-
-error:
- close(sock);
-}
-
-#if SYZ_EXECUTOR || SYZ_NIC_VF
-
-static void netlink_nicvf_setup(void)
-{
- char cmdline[256];
-
-#if SYZ_EXECUTOR
- if (!flag_nic_vf)
- return;
-#endif
- if (!vf_intf.ppid)
- return;
-
- debug("ppid = %d, vf_intf.pass_thru_intf: %s\n",
- vf_intf.ppid, vf_intf.pass_thru_intf);
-
- sprintf(cmdline, "nsenter -t 1 -n ip link set %s netns %d",
- vf_intf.pass_thru_intf, getpid());
- if (runcmdline(cmdline))
- failmsg("failed to run command", "%s", cmdline);
- sprintf(cmdline, "ip a s %s", vf_intf.pass_thru_intf);
- if (runcmdline(cmdline))
- failmsg("failed to run command", "%s", cmdline);
- sprintf(cmdline, "ip link set %s down", vf_intf.pass_thru_intf);
- if (runcmdline(cmdline))
- failmsg("failed to run command", "%s", cmdline);
- sprintf(cmdline, "ip link set %s name nicvf0", vf_intf.pass_thru_intf);
- if (runcmdline(cmdline))
- failmsg("failed to run command", "%s", cmdline);
- debug("nicvf0 VF pass-through setup complete.\n");
-}
-#endif
-static void initialize_netdevices(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_devices)
- return;
-#endif
- char netdevsim[16];
- sprintf(netdevsim, "netdevsim%d", (int)procid);
- struct {
- const char* type;
- const char* dev;
- } devtypes[] = {
- {"ip6gretap", "ip6gretap0"},
- {"bridge", "bridge0"},
- {"vcan", "vcan0"},
- {"bond", "bond0"},
- {"team", "team0"},
- {"dummy", "dummy0"},
-#if SYZ_EXECUTOR || SYZ_NIC_VF
- {"nicvf", "nicvf0"},
-#endif
- {"nlmon", "nlmon0"},
- {"caif", "caif0"},
- {"batadv", "batadv0"},
- {"vxcan", "vxcan1"},
- {"veth", 0},
- {"wireguard", "wg0"},
- {"wireguard", "wg1"},
- {"wireguard", "wg2"},
- };
- const char* devmasters[] = {"bridge", "bond", "team", "batadv"};
- struct {
- const char* name;
- int macsize;
- bool noipv6;
- } devices[] = {
- {"lo", ETH_ALEN},
- {"sit0", 0},
- {"bridge0", ETH_ALEN},
- {"vcan0", 0, true},
- {"tunl0", 0},
- {"gre0", 0},
- {"gretap0", ETH_ALEN},
- {"ip_vti0", 0},
- {"ip6_vti0", 0},
- {"ip6tnl0", 0},
- {"ip6gre0", 0},
- {"ip6gretap0", ETH_ALEN},
- {"erspan0", ETH_ALEN},
- {"bond0", ETH_ALEN},
- {"veth0", ETH_ALEN},
- {"veth1", ETH_ALEN},
- {"team0", ETH_ALEN},
- {"veth0_to_bridge", ETH_ALEN},
- {"veth1_to_bridge", ETH_ALEN},
- {"veth0_to_bond", ETH_ALEN},
- {"veth1_to_bond", ETH_ALEN},
- {"veth0_to_team", ETH_ALEN},
- {"veth1_to_team", ETH_ALEN},
- {"veth0_to_hsr", ETH_ALEN},
- {"veth1_to_hsr", ETH_ALEN},
- {"hsr0", 0},
- {"dummy0", ETH_ALEN},
-#if SYZ_EXECUTOR || SYZ_NIC_VF
- {"nicvf0", 0, true},
-#endif
- {"nlmon0", 0},
- {"vxcan0", 0, true},
- {"vxcan1", 0, true},
- {"caif0", ETH_ALEN},
- {"batadv0", ETH_ALEN},
- {netdevsim, ETH_ALEN},
- {"xfrm0", ETH_ALEN},
- {"veth0_virt_wifi", ETH_ALEN},
- {"veth1_virt_wifi", ETH_ALEN},
- {"virt_wifi0", ETH_ALEN},
- {"veth0_vlan", ETH_ALEN},
- {"veth1_vlan", ETH_ALEN},
- {"vlan0", ETH_ALEN},
- {"vlan1", ETH_ALEN},
- {"macvlan0", ETH_ALEN},
- {"macvlan1", ETH_ALEN},
- {"ipvlan0", ETH_ALEN},
- {"ipvlan1", ETH_ALEN},
- {"veth0_macvtap", ETH_ALEN},
- {"veth1_macvtap", ETH_ALEN},
- {"macvtap0", ETH_ALEN},
- {"macsec0", ETH_ALEN},
- {"veth0_to_batadv", ETH_ALEN},
- {"veth1_to_batadv", ETH_ALEN},
- {"batadv_slave_0", ETH_ALEN},
- {"batadv_slave_1", ETH_ALEN},
- {"geneve0", ETH_ALEN},
- {"geneve1", ETH_ALEN},
- {"wg0", 0},
- {"wg1", 0},
- {"wg2", 0},
- };
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (sock == -1)
- fail("socket(AF_NETLINK) failed");
- unsigned i;
- for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++)
- netlink_add_device(&nlmsg, sock, devtypes[i].type, devtypes[i].dev);
- for (i = 0; i < sizeof(devmasters) / (sizeof(devmasters[0])); i++) {
- char master[32], slave0[32], veth0[32], slave1[32], veth1[32];
- sprintf(slave0, "%s_slave_0", devmasters[i]);
- sprintf(veth0, "veth0_to_%s", devmasters[i]);
- netlink_add_veth(&nlmsg, sock, slave0, veth0);
- sprintf(slave1, "%s_slave_1", devmasters[i]);
- sprintf(veth1, "veth1_to_%s", devmasters[i]);
- netlink_add_veth(&nlmsg, sock, slave1, veth1);
- sprintf(master, "%s0", devmasters[i]);
- netlink_device_change(&nlmsg, sock, slave0, false, master, 0, 0, NULL);
- netlink_device_change(&nlmsg, sock, slave1, false, master, 0, 0, NULL);
- }
- netlink_add_xfrm(&nlmsg, sock, "xfrm0");
- netlink_device_change(&nlmsg, sock, "bridge_slave_0", true, 0, 0, 0, NULL);
- netlink_device_change(&nlmsg, sock, "bridge_slave_1", true, 0, 0, 0, NULL);
- netlink_add_veth(&nlmsg, sock, "hsr_slave_0", "veth0_to_hsr");
- netlink_add_veth(&nlmsg, sock, "hsr_slave_1", "veth1_to_hsr");
- netlink_add_hsr(&nlmsg, sock, "hsr0", "hsr_slave_0", "hsr_slave_1");
- netlink_device_change(&nlmsg, sock, "hsr_slave_0", true, 0, 0, 0, NULL);
- netlink_device_change(&nlmsg, sock, "hsr_slave_1", true, 0, 0, 0, NULL);
-
- netlink_add_veth(&nlmsg, sock, "veth0_virt_wifi", "veth1_virt_wifi");
- netlink_add_linked(&nlmsg, sock, "virt_wifi", "virt_wifi0", "veth1_virt_wifi");
-
- netlink_add_veth(&nlmsg, sock, "veth0_vlan", "veth1_vlan");
- netlink_add_vlan(&nlmsg, sock, "vlan0", "veth0_vlan", 0, htons(ETH_P_8021Q));
- netlink_add_vlan(&nlmsg, sock, "vlan1", "veth0_vlan", 1, htons(ETH_P_8021AD));
- netlink_add_macvlan(&nlmsg, sock, "macvlan0", "veth1_vlan");
- netlink_add_macvlan(&nlmsg, sock, "macvlan1", "veth1_vlan");
- netlink_add_ipvlan(&nlmsg, sock, "ipvlan0", "veth0_vlan", IPVLAN_MODE_L2, 0);
- netlink_add_ipvlan(&nlmsg, sock, "ipvlan1", "veth0_vlan", IPVLAN_MODE_L3S, IPVLAN_F_VEPA);
-
- netlink_add_veth(&nlmsg, sock, "veth0_macvtap", "veth1_macvtap");
- netlink_add_linked(&nlmsg, sock, "macvtap", "macvtap0", "veth0_macvtap");
- netlink_add_linked(&nlmsg, sock, "macsec", "macsec0", "veth1_macvtap");
-
- char addr[32];
- sprintf(addr, DEV_IPV4, 14 + 10);
- struct in_addr geneve_addr4;
- if (inet_pton(AF_INET, addr, &geneve_addr4) <= 0)
- fail("geneve0 inet_pton failed");
- struct in6_addr geneve_addr6;
- if (inet_pton(AF_INET6, "fc00::01", &geneve_addr6) <= 0)
- fail("geneve1 inet_pton failed");
- netlink_add_geneve(&nlmsg, sock, "geneve0", 0, &geneve_addr4, 0);
- netlink_add_geneve(&nlmsg, sock, "geneve1", 1, 0, &geneve_addr6);
-
- netdevsim_add((int)procid, 4);
-
- netlink_wireguard_setup();
-
-#if SYZ_EXECUTOR || SYZ_NIC_VF
- netlink_nicvf_setup();
-#endif
-
- for (i = 0; i < sizeof(devices) / (sizeof(devices[0])); i++) {
- char addr[32];
- sprintf(addr, DEV_IPV4, i + 10);
- netlink_add_addr4(&nlmsg, sock, devices[i].name, addr);
- if (!devices[i].noipv6) {
- sprintf(addr, DEV_IPV6, i + 10);
- netlink_add_addr6(&nlmsg, sock, devices[i].name, addr);
- }
- uint64 macaddr = DEV_MAC + ((i + 10ull) << 40);
- netlink_device_change(&nlmsg, sock, devices[i].name, true, 0, &macaddr, devices[i].macsize, NULL);
- }
- close(sock);
-}
-static void initialize_netdevices_init(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_devices)
- return;
-#endif
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (sock == -1)
- fail("socket(AF_NETLINK) failed");
- struct {
- const char* type;
- int macsize;
- bool noipv6;
- bool noup;
- } devtypes[] = {
- {"nr", 7, true},
- {"rose", 5, true, true},
- };
- unsigned i;
- for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) {
- char dev[32], addr[32];
- sprintf(dev, "%s%d", devtypes[i].type, (int)procid);
- sprintf(addr, "172.30.%d.%d", i, (int)procid + 1);
- netlink_add_addr4(&nlmsg, sock, dev, addr);
- if (!devtypes[i].noipv6) {
- sprintf(addr, "fe88::%02x:%02x", i, (int)procid + 1);
- netlink_add_addr6(&nlmsg, sock, dev, addr);
- }
- int macsize = devtypes[i].macsize;
- uint64 macaddr = 0xbbbbbb + ((unsigned long long)i << (8 * (macsize - 2))) +
- (procid << (8 * (macsize - 1)));
- netlink_device_change(&nlmsg, sock, dev, !devtypes[i].noup, 0, &macaddr, macsize, NULL);
- }
- close(sock);
-
-#if SYZ_EXECUTOR || SYZ_NIC_VF
- find_vf_interface();
-#endif
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION && (__NR_syz_extract_tcp_res || SYZ_REPEAT)
-#include <errno.h>
-
-static int read_tun(char* data, int size)
-{
- if (tunfd < 0)
- return -1;
-
- int rv = read(tunfd, data, size);
- if (rv < 0) {
- if (errno == EAGAIN || errno == EBADF || errno == EBADFD)
- return -1;
- fail("tun read failed");
- }
- return rv;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_emit_ethernet && SYZ_NET_INJECTION
-#include <stdbool.h>
-#include <sys/uio.h>
-
-#if ENABLE_NAPI_FRAGS
-#define MAX_FRAGS 4
-struct vnet_fragmentation {
- uint32 full;
- uint32 count;
- uint32 frags[MAX_FRAGS];
-};
-#endif
-
-static long syz_emit_ethernet(volatile long a0, volatile long a1, volatile long a2)
-{
- if (tunfd < 0)
- return (uintptr_t)-1;
-
- uint32 length = a0;
- char* data = (char*)a1;
- debug_dump_data(data, length);
-
-#if ENABLE_NAPI_FRAGS
- struct vnet_fragmentation* frags = (struct vnet_fragmentation*)a2;
- struct iovec vecs[MAX_FRAGS + 1];
- uint32 nfrags = 0;
- if (!tun_frags_enabled || frags == NULL) {
- vecs[nfrags].iov_base = data;
- vecs[nfrags].iov_len = length;
- nfrags++;
- } else {
- bool full = frags->full;
- uint32 count = frags->count;
- if (count > MAX_FRAGS)
- count = MAX_FRAGS;
- uint32 i;
- for (i = 0; i < count && length != 0; i++) {
- uint32 size = frags->frags[i];
- if (size > length)
- size = length;
- vecs[nfrags].iov_base = data;
- vecs[nfrags].iov_len = size;
- nfrags++;
- data += size;
- length -= size;
- }
- if (length != 0 && (full || nfrags == 0)) {
- vecs[nfrags].iov_base = data;
- vecs[nfrags].iov_len = length;
- nfrags++;
- }
- }
- return writev(tunfd, vecs, nfrags);
-#else
- return write(tunfd, data, length);
-#endif
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_io_uring_submit || __NR_syz_io_uring_complete || __NR_syz_io_uring_setup
-
-#define SIZEOF_IO_URING_SQE 64
-#define SIZEOF_IO_URING_CQE 16
-#define SQ_HEAD_OFFSET 0
-#define SQ_TAIL_OFFSET 64
-#define SQ_RING_MASK_OFFSET 256
-#define SQ_RING_ENTRIES_OFFSET 264
-#define SQ_FLAGS_OFFSET 276
-#define SQ_DROPPED_OFFSET 272
-#define CQ_HEAD_OFFSET 128
-#define CQ_TAIL_OFFSET 192
-#define CQ_RING_MASK_OFFSET 260
-#define CQ_RING_ENTRIES_OFFSET 268
-#define CQ_RING_OVERFLOW_OFFSET 284
-#define CQ_FLAGS_OFFSET 280
-#define CQ_CQES_OFFSET 320
-
-#if SYZ_EXECUTOR || __NR_syz_io_uring_complete
-struct io_uring_cqe {
- uint64 user_data;
- uint32 res;
- uint32 flags;
-};
-
-static long syz_io_uring_complete(volatile long a0)
-{
- char* ring_ptr = (char*)a0;
- uint32 cq_ring_mask = *(uint32*)(ring_ptr + CQ_RING_MASK_OFFSET);
- uint32* cq_head_ptr = (uint32*)(ring_ptr + CQ_HEAD_OFFSET);
- uint32 cq_head = *cq_head_ptr & cq_ring_mask;
- uint32 cq_head_next = *cq_head_ptr + 1;
- char* cqe_src = ring_ptr + CQ_CQES_OFFSET + cq_head * SIZEOF_IO_URING_CQE;
- struct io_uring_cqe cqe;
- memcpy(&cqe, cqe_src, sizeof(cqe));
- __atomic_store_n(cq_head_ptr, cq_head_next, __ATOMIC_RELEASE);
- return (cqe.user_data == 0x12345 || cqe.user_data == 0x23456) ? (long)cqe.res : (long)-1;
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_io_uring_setup
-
-struct io_sqring_offsets {
- uint32 head;
- uint32 tail;
- uint32 ring_mask;
- uint32 ring_entries;
- uint32 flags;
- uint32 dropped;
- uint32 array;
- uint32 resv1;
- uint64 resv2;
-};
-
-struct io_cqring_offsets {
- uint32 head;
- uint32 tail;
- uint32 ring_mask;
- uint32 ring_entries;
- uint32 overflow;
- uint32 cqes;
- uint64 resv[2];
-};
-
-struct io_uring_params {
- uint32 sq_entries;
- uint32 cq_entries;
- uint32 flags;
- uint32 sq_thread_cpu;
- uint32 sq_thread_idle;
- uint32 features;
- uint32 resv[4];
- struct io_sqring_offsets sq_off;
- struct io_cqring_offsets cq_off;
-};
-
-#define IORING_OFF_SQ_RING 0
-#define IORING_OFF_SQES 0x10000000ULL
-#define IORING_SETUP_SQE128 (1U << 10)
-#define IORING_SETUP_CQE32 (1U << 11)
-
-#include <sys/mman.h>
-#include <unistd.h>
-static long syz_io_uring_setup(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
-{
- uint32 entries = (uint32)a0;
- struct io_uring_params* setup_params = (struct io_uring_params*)a1;
- void** ring_ptr_out = (void**)a2;
- void** sqes_ptr_out = (void**)a3;
- setup_params->flags &= ~(IORING_SETUP_CQE32 | IORING_SETUP_SQE128);
- uint32 fd_io_uring = syscall(__NR_io_uring_setup, entries, setup_params);
- uint32 sq_ring_sz = setup_params->sq_off.array + setup_params->sq_entries * sizeof(uint32);
- uint32 cq_ring_sz = setup_params->cq_off.cqes + setup_params->cq_entries * SIZEOF_IO_URING_CQE;
- uint32 ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz;
- *ring_ptr_out = mmap(0, ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd_io_uring, IORING_OFF_SQ_RING);
-
- uint32 sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE;
- *sqes_ptr_out = mmap(0, sqes_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd_io_uring, IORING_OFF_SQES);
-
- uint32* array = (uint32*)((uintptr_t)*ring_ptr_out + setup_params->sq_off.array);
- for (uint32 index = 0; index < entries; index++)
- array[index] = index;
-
- return fd_io_uring;
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_io_uring_submit
-
-static long syz_io_uring_submit(volatile long a0, volatile long a1, volatile long a2)
-{
- char* ring_ptr = (char*)a0;
- char* sqes_ptr = (char*)a1;
-
- char* sqe = (char*)a2;
-
- uint32 sq_ring_mask = *(uint32*)(ring_ptr + SQ_RING_MASK_OFFSET);
- uint32* sq_tail_ptr = (uint32*)(ring_ptr + SQ_TAIL_OFFSET);
- uint32 sq_tail = *sq_tail_ptr & sq_ring_mask;
- char* sqe_dest = sqes_ptr + sq_tail * SIZEOF_IO_URING_SQE;
- memcpy(sqe_dest, sqe, SIZEOF_IO_URING_SQE);
- uint32 sq_tail_next = *sq_tail_ptr + 1;
- __atomic_store_n(sq_tail_ptr, sq_tail_next, __ATOMIC_RELEASE);
- return 0;
-}
-
-#endif
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usbip_server_init
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/usb/ch9.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#define VHCI_HC_PORTS 8
-#define VHCI_PORTS (VHCI_HC_PORTS * 2)
-
-static long syz_usbip_server_init(volatile long a0)
-{
- static int port_alloc[2];
-
- int speed = (int)a0;
- bool usb3 = (speed == USB_SPEED_SUPER);
-
- int socket_pair[2];
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair)) {
- debug("syz_usbip_server_init: socketpair failed (%d)\n", errno);
- return -1;
- }
-
- int client_fd = socket_pair[0];
- int server_fd = socket_pair[1];
-
- int available_port_num = __atomic_fetch_add(&port_alloc[usb3], 1, __ATOMIC_RELAXED);
- if (available_port_num > VHCI_HC_PORTS) {
- debug("syz_usbip_server_init : no more available port for : %d\n", available_port_num);
- return -1;
- }
- int port_num = procid * VHCI_PORTS + usb3 * VHCI_HC_PORTS + available_port_num;
- char buffer[100];
- sprintf(buffer, "%d %d %s %d", port_num, client_fd, "0", speed);
-
- write_file("/sys/devices/platform/vhci_hcd.0/attach", buffer);
- return server_fd;
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_btf_id_by_name
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#define BTF_MAGIC 0xeB9F
-
-struct btf_header {
- __u16 magic;
- __u8 version;
- __u8 flags;
- __u32 hdr_len;
- __u32 type_off;
- __u32 type_len;
- __u32 str_off;
- __u32 str_len;
-};
-
-#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
-#define BTF_INFO_VLEN(info) ((info)&0xffff)
-
-#define BTF_KIND_INT 1
-#define BTF_KIND_ARRAY 3
-#define BTF_KIND_STRUCT 4
-#define BTF_KIND_UNION 5
-#define BTF_KIND_ENUM 6
-#define BTF_KIND_FUNC_PROTO 13
-#define BTF_KIND_VAR 14
-#define BTF_KIND_DATASEC 15
-
-struct btf_type {
- __u32 name_off;
- __u32 info;
- union {
- __u32 size;
- __u32 type;
- };
-};
-
-struct btf_enum {
- __u32 name_off;
- __s32 val;
-};
-
-struct btf_array {
- __u32 type;
- __u32 index_type;
- __u32 nelems;
-};
-
-struct btf_member {
- __u32 name_off;
- __u32 type;
- __u32 offset;
-};
-
-struct btf_param {
- __u32 name_off;
- __u32 type;
-};
-
-struct btf_var {
- __u32 linkage;
-};
-
-struct btf_var_secinfo {
- __u32 type;
- __u32 offset;
- __u32 size;
-};
-#define VMLINUX_MAX_SUPPORT_SIZE (10 * 1024 * 1024)
-static char* read_btf_vmlinux()
-{
- static bool is_read = false;
- static char buf[VMLINUX_MAX_SUPPORT_SIZE];
- if (is_read)
- return buf;
-
- int fd = open("/sys/kernel/btf/vmlinux", O_RDONLY);
- if (fd < 0)
- return NULL;
-
- unsigned long bytes_read = 0;
- for (;;) {
- ssize_t ret = read(fd, buf + bytes_read,
- VMLINUX_MAX_SUPPORT_SIZE - bytes_read);
-
- if (ret < 0 || bytes_read + ret == VMLINUX_MAX_SUPPORT_SIZE)
- return NULL;
-
- if (ret == 0)
- break;
-
- bytes_read += ret;
- }
-
- is_read = true;
- return buf;
-}
-static long syz_btf_id_by_name(volatile long a0)
-{
- char* target = (char*)a0;
-
- char* vmlinux = read_btf_vmlinux();
- if (vmlinux == NULL)
- return -1;
-
- struct btf_header* btf_header = (struct btf_header*)vmlinux;
- if (btf_header->magic != BTF_MAGIC)
- return -1;
- char* btf_type_sec = vmlinux + btf_header->hdr_len + btf_header->type_off;
- char* btf_str_sec = vmlinux + btf_header->hdr_len + btf_header->str_off;
- unsigned int bytes_parsed = 0;
- long idx = 1;
- while (bytes_parsed < btf_header->type_len) {
- struct btf_type* btf_type = (struct btf_type*)(btf_type_sec + bytes_parsed);
- uint32 kind = BTF_INFO_KIND(btf_type->info);
- uint32 vlen = BTF_INFO_VLEN(btf_type->info);
- char* name = btf_str_sec + btf_type->name_off;
-
- if (strcmp(name, target) == 0)
- return idx;
- size_t skip;
- switch (kind) {
- case BTF_KIND_INT:
- skip = sizeof(uint32);
- break;
- case BTF_KIND_ENUM:
- skip = sizeof(struct btf_enum) * vlen;
- break;
- case BTF_KIND_ARRAY:
- skip = sizeof(struct btf_array);
- break;
- case BTF_KIND_STRUCT:
- case BTF_KIND_UNION:
- skip = sizeof(struct btf_member) * vlen;
- break;
- case BTF_KIND_FUNC_PROTO:
- skip = sizeof(struct btf_param) * vlen;
- break;
- case BTF_KIND_VAR:
- skip = sizeof(struct btf_var);
- break;
- case BTF_KIND_DATASEC:
- skip = sizeof(struct btf_var_secinfo) * vlen;
- break;
- default:
- skip = 0;
- }
-
- bytes_parsed += sizeof(struct btf_type) + skip;
- idx++;
- }
-
- return -1;
-}
-
-#endif
-#if SYZ_EXECUTOR || __NR_syz_memcpy_off
-static long syz_memcpy_off(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4)
-{
- char* dest = (char*)a0;
- uint32 dest_off = (uint32)a1;
- char* src = (char*)a2;
- uint32 src_off = (uint32)a3;
- size_t n = (size_t)a4;
-
- return (long)memcpy(dest + dest_off, src + src_off, n);
-}
-#endif
-
-#if (SYZ_EXECUTOR || SYZ_REPEAT && SYZ_NET_INJECTION) && SYZ_EXECUTOR_USES_FORK_SERVER
-static void flush_tun()
-{
-#if SYZ_EXECUTOR
- if (!flag_net_injection)
- return;
-#endif
- char data[1000];
- while (read_tun(&data[0], sizeof(data)) != -1) {
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_extract_tcp_res && SYZ_NET_INJECTION
-#ifndef __ANDROID__
-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 {
- uint32 seq;
- uint32 ack;
-};
-
-static long syz_extract_tcp_res(volatile long a0, volatile long a1, volatile long a2)
-{
-
- if (tunfd < 0)
- return (uintptr_t)-1;
- char data[1000];
- int rv = read_tun(&data[0], sizeof(data));
- if (rv == -1)
- return (uintptr_t)-1;
- size_t length = rv;
- debug_dump_data(data, length);
-
- if (length < sizeof(struct ethhdr))
- return (uintptr_t)-1;
- struct ethhdr* ethhdr = (struct ethhdr*)&data[0];
-
- struct tcphdr* tcphdr = 0;
- if (ethhdr->h_proto == htons(ETH_P_IP)) {
- if (length < sizeof(struct ethhdr) + sizeof(struct iphdr))
- return (uintptr_t)-1;
- struct iphdr* iphdr = (struct iphdr*)&data[sizeof(struct ethhdr)];
- if (iphdr->protocol != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ethhdr) + iphdr->ihl * 4 + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + iphdr->ihl * 4];
- } else {
- if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr))
- return (uintptr_t)-1;
- struct ipv6hdr* ipv6hdr = (struct ipv6hdr*)&data[sizeof(struct ethhdr)];
- if (ipv6hdr->nexthdr != IPPROTO_TCP)
- return (uintptr_t)-1;
- if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
- return (uintptr_t)-1;
- tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + sizeof(struct ipv6hdr)];
- }
-
- struct tcp_resources* res = (struct tcp_resources*)a0;
- res->seq = htonl((ntohl(tcphdr->seq) + (uint32)a1));
- res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32)a2));
-
- debug("extracted seq: %08x\n", res->seq);
- debug("extracted ack: %08x\n", res->ack);
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_CLOSE_FDS || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-#define MAX_FDS 30
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \
- __NR_syz_usb_ep_write || __NR_syz_usb_ep_read || __NR_syz_usb_control_io || \
- __NR_syz_usb_disconnect
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/usb/ch9.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#define USB_MAX_IFACE_NUM 4
-#define USB_MAX_EP_NUM 32
-#define USB_MAX_FDS 6
-
-struct usb_endpoint_index {
- struct usb_endpoint_descriptor desc;
- int handle;
-};
-
-struct usb_iface_index {
- struct usb_interface_descriptor* iface;
- uint8 bInterfaceNumber;
- uint8 bAlternateSetting;
- uint8 bInterfaceClass;
- struct usb_endpoint_index eps[USB_MAX_EP_NUM];
- int eps_num;
-};
-
-struct usb_device_index {
- struct usb_device_descriptor* dev;
- struct usb_config_descriptor* config;
- uint8 bDeviceClass;
- uint8 bMaxPower;
- int config_length;
- struct usb_iface_index ifaces[USB_MAX_IFACE_NUM];
- int ifaces_num;
- int iface_cur;
-};
-
-struct usb_info {
- int fd;
- struct usb_device_index index;
-};
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \
- __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write
-static struct usb_info usb_devices[USB_MAX_FDS];
-
-static struct usb_device_index* lookup_usb_index(int fd)
-{
- for (int i = 0; i < USB_MAX_FDS; i++) {
- if (__atomic_load_n(&usb_devices[i].fd, __ATOMIC_ACQUIRE) == fd)
- return &usb_devices[i].index;
- }
- return NULL;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-static int usb_devices_num;
-
-static bool parse_usb_descriptor(const char* buffer, size_t length, struct usb_device_index* index)
-{
- if (length < sizeof(*index->dev) + sizeof(*index->config))
- return false;
-
- memset(index, 0, sizeof(*index));
-
- index->dev = (struct usb_device_descriptor*)buffer;
- index->config = (struct usb_config_descriptor*)(buffer + sizeof(*index->dev));
- index->bDeviceClass = index->dev->bDeviceClass;
- index->bMaxPower = index->config->bMaxPower;
- index->config_length = length - sizeof(*index->dev);
- index->iface_cur = -1;
- size_t offset = 0;
-
- while (true) {
- if (offset + 1 >= length)
- break;
- uint8 desc_length = buffer[offset];
- uint8 desc_type = buffer[offset + 1];
- if (desc_length <= 2)
- break;
- if (offset + desc_length > length)
- break;
- if (desc_type == USB_DT_INTERFACE && index->ifaces_num < USB_MAX_IFACE_NUM) {
- struct usb_interface_descriptor* iface = (struct usb_interface_descriptor*)(buffer + offset);
- debug("parse_usb_descriptor: found interface #%u (%d, %d) at %p\n",
- index->ifaces_num, iface->bInterfaceNumber, iface->bAlternateSetting, iface);
- index->ifaces[index->ifaces_num].iface = iface;
- index->ifaces[index->ifaces_num].bInterfaceNumber = iface->bInterfaceNumber;
- index->ifaces[index->ifaces_num].bAlternateSetting = iface->bAlternateSetting;
- index->ifaces[index->ifaces_num].bInterfaceClass = iface->bInterfaceClass;
- index->ifaces_num++;
- }
- if (desc_type == USB_DT_ENDPOINT && index->ifaces_num > 0) {
- struct usb_iface_index* iface = &index->ifaces[index->ifaces_num - 1];
- debug("parse_usb_descriptor: found endpoint #%u at %p\n", iface->eps_num, buffer + offset);
- if (iface->eps_num < USB_MAX_EP_NUM) {
- memcpy(&iface->eps[iface->eps_num].desc, buffer + offset, sizeof(iface->eps[iface->eps_num].desc));
- iface->eps_num++;
- }
- }
- offset += desc_length;
- }
-
- return true;
-}
-
-static struct usb_device_index* add_usb_index(int fd, const char* dev, size_t dev_len)
-{
- int i = __atomic_fetch_add(&usb_devices_num, 1, __ATOMIC_RELAXED);
- if (i >= USB_MAX_FDS)
- return NULL;
-
- if (!parse_usb_descriptor(dev, dev_len, &usb_devices[i].index))
- return NULL;
-
- __atomic_store_n(&usb_devices[i].fd, fd, __ATOMIC_RELEASE);
- return &usb_devices[i].index;
-}
-
-#endif
-
-#if USB_DEBUG
-
-#include <linux/hid.h>
-#include <linux/usb/audio.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/ch11.h>
-#include <linux/usb/ch9.h>
-#define USBLP_REQ_GET_ID 0x00
-#define USBLP_REQ_GET_STATUS 0x01
-#define USBLP_REQ_RESET 0x02
-
-const char* usb_class_to_string(unsigned value)
-{
- switch (value) {
- case USB_CLASS_PER_INTERFACE:
- return "USB_CLASS_PER_INTERFACE";
- case USB_CLASS_AUDIO:
- return "USB_CLASS_AUDIO";
- case USB_CLASS_COMM:
- return "USB_CLASS_COMM";
- case USB_CLASS_HID:
- return "USB_CLASS_HID";
- case USB_CLASS_PHYSICAL:
- return "USB_CLASS_PHYSICAL";
- case USB_CLASS_STILL_IMAGE:
- return "USB_CLASS_STILL_IMAGE";
- case USB_CLASS_PRINTER:
- return "USB_CLASS_PRINTER";
- case USB_CLASS_MASS_STORAGE:
- return "USB_CLASS_MASS_STORAGE";
- case USB_CLASS_HUB:
- return "USB_CLASS_HUB";
- case USB_CLASS_CDC_DATA:
- return "USB_CLASS_CDC_DATA";
- case USB_CLASS_CSCID:
- return "USB_CLASS_CSCID";
- case USB_CLASS_CONTENT_SEC:
- return "USB_CLASS_CONTENT_SEC";
- case USB_CLASS_VIDEO:
- return "USB_CLASS_VIDEO";
- case USB_CLASS_WIRELESS_CONTROLLER:
- return "USB_CLASS_WIRELESS_CONTROLLER";
- case USB_CLASS_MISC:
- return "USB_CLASS_MISC";
- case USB_CLASS_APP_SPEC:
- return "USB_CLASS_APP_SPEC";
- case USB_CLASS_VENDOR_SPEC:
- return "USB_CLASS_VENDOR_SPEC";
- }
- return "unknown";
-}
-static void analyze_usb_device(struct usb_device_index* index)
-{
- debug("analyze_usb_device: idVendor = %04x\n", (unsigned)index->dev->idVendor);
- debug("analyze_usb_device: idProduct = %04x\n", (unsigned)index->dev->idProduct);
-
- debug("analyze_usb_device: bDeviceClass = %x (%s)\n", (unsigned)index->dev->bDeviceClass,
- usb_class_to_string(index->dev->bDeviceClass));
- debug("analyze_usb_device: bDeviceSubClass = %x\n", (unsigned)index->dev->bDeviceSubClass);
- debug("analyze_usb_device: bDeviceProtocol = %x\n", (unsigned)index->dev->bDeviceProtocol);
-
- for (int i = 0; i < index->ifaces_num; i++) {
- struct usb_interface_descriptor* iface = index->ifaces[i].iface;
- debug("analyze_usb_device: interface #%d:\n", i);
- debug("analyze_usb_device: bInterfaceClass = %x (%s)\n", (unsigned)iface->bInterfaceClass,
- usb_class_to_string(iface->bInterfaceClass));
- debug("analyze_usb_device: bInterfaceSubClass = %x\n", (unsigned)iface->bInterfaceSubClass);
- debug("analyze_usb_device: bInterfaceProtocol = %x\n", (unsigned)iface->bInterfaceProtocol);
- }
-}
-
-static bool analyze_control_request_standard(struct usb_device_index* index, struct usb_ctrlrequest* ctrl)
-{
- uint8 bDeviceClass = index->bDeviceClass;
- uint8 bInterfaceClass = index->ifaces[index->iface_cur].bInterfaceClass;
- if (bDeviceClass == USB_CLASS_HID || bInterfaceClass == USB_CLASS_HID) {
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- debug("analyze_control_request: req = USB_REQ_GET_DESCRIPTOR\n");
- switch (ctrl->wValue >> 8) {
- case HID_DT_HID:
- debug("analyze_control_request: desc = HID_DT_HID\n");
- return true;
- case HID_DT_REPORT:
- debug("analyze_control_request: desc = HID_DT_REPORT\n");
- return true;
- case HID_DT_PHYSICAL:
- debug("analyze_control_request: desc = HID_DT_PHYSICAL\n");
- return false;
- }
- }
- }
-
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- debug("analyze_control_request: req = USB_REQ_GET_DESCRIPTOR\n");
- switch (ctrl->wValue >> 8) {
- case USB_DT_DEVICE:
- debug("analyze_control_request: desc = USB_DT_DEVICE\n");
- return true;
- case USB_DT_CONFIG:
- debug("analyze_control_request: desc = USB_DT_CONFIG, index = %d\n", (int)(ctrl->wValue & 0xff));
- return true;
- case USB_DT_STRING:
- debug("analyze_control_request: desc = USB_DT_STRING\n");
- return true;
- case USB_DT_INTERFACE:
- debug("analyze_control_request: desc = USB_DT_INTERFACE\n");
- break;
- case USB_DT_ENDPOINT:
- debug("analyze_control_request: desc = USB_DT_ENDPOINT\n");
- break;
- case USB_DT_DEVICE_QUALIFIER:
- debug("analyze_control_request: desc = USB_DT_DEVICE_QUALIFIER\n");
- return true;
- case USB_DT_OTHER_SPEED_CONFIG:
- debug("analyze_control_request: desc = USB_DT_OTHER_SPEED_CONFIG\n");
- break;
- case USB_DT_INTERFACE_POWER:
- debug("analyze_control_request: desc = USB_DT_INTERFACE_POWER\n");
- break;
- case USB_DT_OTG:
- debug("analyze_control_request: desc = USB_DT_OTG\n");
- break;
- case USB_DT_DEBUG:
- debug("analyze_control_request: desc = USB_DT_DEBUG\n");
- break;
- case USB_DT_INTERFACE_ASSOCIATION:
- debug("analyze_control_request: desc = USB_DT_INTERFACE_ASSOCIATION\n");
- break;
- case USB_DT_SECURITY:
- debug("analyze_control_request: desc = USB_DT_SECURITY\n");
- break;
- case USB_DT_KEY:
- debug("analyze_control_request: desc = USB_DT_KEY\n");
- break;
- case USB_DT_ENCRYPTION_TYPE:
- debug("analyze_control_request: desc = USB_DT_ENCRYPTION_TYPE\n");
- break;
- case USB_DT_BOS:
- debug("analyze_control_request: desc = USB_DT_BOS\n");
- return true;
- case USB_DT_DEVICE_CAPABILITY:
- debug("analyze_control_request: desc = USB_DT_DEVICE_CAPABILITY\n");
- break;
- case USB_DT_WIRELESS_ENDPOINT_COMP:
- debug("analyze_control_request: desc = USB_DT_WIRELESS_ENDPOINT_COMP\n");
- break;
- case USB_DT_WIRE_ADAPTER:
- debug("analyze_control_request: desc = USB_DT_WIRE_ADAPTER\n");
- break;
- case USB_DT_RPIPE:
- debug("analyze_control_request: desc = USB_DT_RPIPE\n");
- break;
- case USB_DT_CS_RADIO_CONTROL:
- debug("analyze_control_request: desc = USB_DT_CS_RADIO_CONTROL\n");
- break;
- case USB_DT_PIPE_USAGE:
- debug("analyze_control_request: desc = USB_DT_PIPE_USAGE\n");
- break;
- case USB_DT_SS_ENDPOINT_COMP:
- debug("analyze_control_request: desc = USB_DT_SS_ENDPOINT_COMP\n");
- break;
- case USB_DT_SSP_ISOC_ENDPOINT_COMP:
- debug("analyze_control_request: desc = USB_DT_SSP_ISOC_ENDPOINT_COMP\n");
- break;
- default:
- debug("analyze_control_request: desc = unknown = 0x%x\n", (int)(ctrl->wValue >> 8));
- break;
- }
- break;
- case USB_REQ_GET_STATUS:
- debug("analyze_control_request: req = USB_REQ_GET_STATUS\n");
- break;
- case USB_REQ_CLEAR_FEATURE:
- debug("analyze_control_request: req = USB_REQ_CLEAR_FEATURE\n");
- break;
- case USB_REQ_SET_FEATURE:
- debug("analyze_control_request: req = USB_REQ_SET_FEATURE\n");
- break;
- case USB_REQ_GET_CONFIGURATION:
- debug("analyze_control_request: req = USB_REQ_GET_CONFIGURATION\n");
- return true;
- case USB_REQ_SET_CONFIGURATION:
- debug("analyze_control_request: req = USB_REQ_SET_CONFIGURATION\n");
- break;
- case USB_REQ_GET_INTERFACE:
- debug("analyze_control_request: req = USB_REQ_GET_INTERFACE\n");
- return true;
- case USB_REQ_SET_INTERFACE:
- debug("analyze_control_request: req = USB_REQ_SET_INTERFACE\n");
- break;
- default:
- debug("analyze_control_request: req = unknown = 0x%x\n", (int)ctrl->bRequest);
- break;
- }
-
- return false;
-}
-
-static bool analyze_control_request_class(struct usb_device_index* index, struct usb_ctrlrequest* ctrl)
-{
- uint8 bDeviceClass = index->bDeviceClass;
- uint8 bInterfaceClass = index->ifaces[index->iface_cur].bInterfaceClass;
-
- if (bDeviceClass == USB_CLASS_HID || bInterfaceClass == USB_CLASS_HID) {
- switch (ctrl->bRequest) {
- case HID_REQ_GET_REPORT:
- debug("analyze_control_request: req = HID_REQ_GET_REPORT\n");
- return true;
- case HID_REQ_GET_IDLE:
- debug("analyze_control_request: req = HID_REQ_GET_IDLE\n");
- break;
- case HID_REQ_GET_PROTOCOL:
- debug("analyze_control_request: req = HID_REQ_GET_PROTOCOL\n");
- return true;
- case HID_REQ_SET_REPORT:
- debug("analyze_control_request: req = HID_REQ_SET_REPORT\n");
- break;
- case HID_REQ_SET_IDLE:
- debug("analyze_control_request: req = HID_REQ_SET_IDLE\n");
- break;
- case HID_REQ_SET_PROTOCOL:
- debug("analyze_control_request: req = HID_REQ_SET_PROTOCOL\n");
- break;
- }
- }
-
- if (bDeviceClass == USB_CLASS_AUDIO || bInterfaceClass == USB_CLASS_AUDIO) {
- switch (ctrl->bRequest) {
- case UAC_SET_CUR:
- debug("analyze_control_request: req = UAC_SET_CUR\n");
- break;
- case UAC_GET_CUR:
- debug("analyze_control_request: req = UAC_GET_CUR\n");
- return true;
- case UAC_SET_MIN:
- debug("analyze_control_request: req = UAC_SET_MIN\n");
- break;
- case UAC_GET_MIN:
- debug("analyze_control_request: req = UAC_GET_MIN\n");
- return true;
- case UAC_SET_MAX:
- debug("analyze_control_request: req = UAC_SET_MAX\n");
- break;
- case UAC_GET_MAX:
- debug("analyze_control_request: req = UAC_GET_MAX\n");
- return true;
- case UAC_SET_RES:
- debug("analyze_control_request: req = UAC_SET_RES\n");
- break;
- case UAC_GET_RES:
- debug("analyze_control_request: req = UAC_GET_RES\n");
- return true;
- case UAC_SET_MEM:
- debug("analyze_control_request: req = UAC_SET_MEM\n");
- break;
- case UAC_GET_MEM:
- debug("analyze_control_request: req = UAC_GET_MEM\n");
- return true;
- }
- }
-
- if (bDeviceClass == USB_CLASS_PRINTER || bInterfaceClass == USB_CLASS_PRINTER) {
- switch (ctrl->bRequest) {
- case USBLP_REQ_GET_ID:
- debug("analyze_control_request: req = USBLP_REQ_GET_ID\n");
- return true;
- case USBLP_REQ_GET_STATUS:
- debug("analyze_control_request: req = USBLP_REQ_GET_STATUS\n");
- return true;
- case USBLP_REQ_RESET:
- debug("analyze_control_request: req = USBLP_REQ_RESET\n");
- break;
- }
- }
-
- if (bDeviceClass == USB_CLASS_HUB || bInterfaceClass == USB_CLASS_HUB) {
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- switch (ctrl->wValue >> 8) {
- case USB_DT_HUB:
- debug("analyze_control_request: desc = USB_DT_HUB\n");
- return true;
- case USB_DT_SS_HUB:
- debug("analyze_control_request: desc = USB_DT_SS_HUB\n");
- return true;
- }
- case USB_REQ_GET_STATUS:
- debug("analyze_control_request: req = USB_REQ_GET_STATUS\n");
- return true;
- case HUB_SET_DEPTH:
- debug("analyze_control_request: req = HUB_SET_DEPTH\n");
- break;
- }
- }
-
- if (bInterfaceClass == USB_CLASS_COMM) {
- switch (ctrl->bRequest) {
- case USB_CDC_SEND_ENCAPSULATED_COMMAND:
- debug("analyze_control_request: req = USB_CDC_SEND_ENCAPSULATED_COMMAND\n");
- break;
- case USB_CDC_GET_ENCAPSULATED_RESPONSE:
- debug("analyze_control_request: req = USB_CDC_GET_ENCAPSULATED_RESPONSE\n");
- break;
- case USB_CDC_REQ_SET_LINE_CODING:
- debug("analyze_control_request: req = USB_CDC_REQ_SET_LINE_CODING\n");
- break;
- case USB_CDC_REQ_GET_LINE_CODING:
- debug("analyze_control_request: req = USB_CDC_REQ_GET_LINE_CODING\n");
- break;
- case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
- debug("analyze_control_request: req = USB_CDC_REQ_SET_CONTROL_LINE_STATE\n");
- break;
- case USB_CDC_REQ_SEND_BREAK:
- debug("analyze_control_request: req = USB_CDC_REQ_SEND_BREAK\n");
- break;
- case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
- debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_MULTICAST_FILTERS\n");
- break;
- case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
- debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER\n");
- break;
- case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
- debug("analyze_control_request: req = USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER\n");
- break;
- case USB_CDC_SET_ETHERNET_PACKET_FILTER:
- debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_PACKET_FILTER\n");
- break;
- case USB_CDC_GET_ETHERNET_STATISTIC:
- debug("analyze_control_request: req = USB_CDC_GET_ETHERNET_STATISTIC\n");
- break;
- case USB_CDC_GET_NTB_PARAMETERS:
- debug("analyze_control_request: req = USB_CDC_GET_NTB_PARAMETERS\n");
- return true;
- case USB_CDC_GET_NET_ADDRESS:
- debug("analyze_control_request: req = USB_CDC_GET_NET_ADDRESS\n");
- break;
- case USB_CDC_SET_NET_ADDRESS:
- debug("analyze_control_request: req = USB_CDC_SET_NET_ADDRESS\n");
- break;
- case USB_CDC_GET_NTB_FORMAT:
- debug("analyze_control_request: req = USB_CDC_GET_NTB_FORMAT\n");
- return true;
- case USB_CDC_SET_NTB_FORMAT:
- debug("analyze_control_request: req = USB_CDC_SET_NTB_FORMAT\n");
- break;
- case USB_CDC_GET_NTB_INPUT_SIZE:
- debug("analyze_control_request: req = USB_CDC_GET_NTB_INPUT_SIZE\n");
- return true;
- case USB_CDC_SET_NTB_INPUT_SIZE:
- debug("analyze_control_request: req = USB_CDC_SET_NTB_INPUT_SIZE\n");
- break;
- case USB_CDC_GET_MAX_DATAGRAM_SIZE:
- debug("analyze_control_request: req = USB_CDC_GET_MAX_DATAGRAM_SIZE\n");
- return true;
- case USB_CDC_SET_MAX_DATAGRAM_SIZE:
- debug("analyze_control_request: req = USB_CDC_SET_MAX_DATAGRAM_SIZE\n");
- break;
- case USB_CDC_GET_CRC_MODE:
- debug("analyze_control_request: req = USB_CDC_GET_CRC_MODE\n");
- return true;
- case USB_CDC_SET_CRC_MODE:
- debug("analyze_control_request: req = USB_CDC_SET_CRC_MODE\n");
- break;
- }
- }
-
- return false;
-}
-
-static bool analyze_control_request_vendor(struct usb_device_index* index, struct usb_ctrlrequest* ctrl)
-{
- return true;
-}
-static void analyze_control_request(int fd, struct usb_ctrlrequest* ctrl)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
-
- if (!index)
- return;
-
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- debug("analyze_control_request: type = USB_TYPE_STANDARD\n");
- if (analyze_control_request_standard(index, ctrl))
- return;
- break;
- case USB_TYPE_CLASS:
- debug("analyze_control_request: type = USB_TYPE_CLASS\n");
- if (analyze_control_request_class(index, ctrl))
- return;
- break;
- case USB_TYPE_VENDOR:
- debug("analyze_control_request: type = USB_TYPE_VENDOR\n");
- if (analyze_control_request_vendor(index, ctrl))
- return;
- break;
- }
-
- if (ctrl->bRequestType & USB_DIR_IN) {
- char message[128];
- debug("analyze_control_request: unknown control request\n");
- snprintf(&message[0], sizeof(message), "BUG: unknown control request (0x%x, 0x%x, 0x%x, 0x%x, %d)",
- ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, ctrl->wLength);
- write_file("/dev/kmsg", &message[0]);
- }
-}
-
-#endif
-
-struct vusb_connect_string_descriptor {
- uint32 len;
- char* str;
-} __attribute__((packed));
-
-struct vusb_connect_descriptors {
- uint32 qual_len;
- char* qual;
- uint32 bos_len;
- char* bos;
- uint32 strs_len;
- struct vusb_connect_string_descriptor strs[0];
-} __attribute__((packed));
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-
-static const char default_string[] = {
- 8, USB_DT_STRING,
- 's', 0, 'y', 0, 'z', 0
-};
-
-static const char default_lang_id[] = {
- 4, USB_DT_STRING,
- 0x09, 0x04
-};
-
-static bool lookup_connect_response_in(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl,
- struct usb_qualifier_descriptor* qual,
- char** response_data, uint32* response_length)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
- uint8 str_idx;
-
- if (!index)
- return false;
-
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- switch (ctrl->wValue >> 8) {
- case USB_DT_DEVICE:
- *response_data = (char*)index->dev;
- *response_length = sizeof(*index->dev);
- return true;
- case USB_DT_CONFIG:
- *response_data = (char*)index->config;
- *response_length = index->config_length;
- return true;
- case USB_DT_STRING:
- str_idx = (uint8)ctrl->wValue;
- if (descs && str_idx < descs->strs_len) {
- *response_data = descs->strs[str_idx].str;
- *response_length = descs->strs[str_idx].len;
- return true;
- }
- if (str_idx == 0) {
- *response_data = (char*)&default_lang_id[0];
- *response_length = default_lang_id[0];
- return true;
- }
- *response_data = (char*)&default_string[0];
- *response_length = default_string[0];
- return true;
- case USB_DT_BOS:
- *response_data = descs->bos;
- *response_length = descs->bos_len;
- return true;
- case USB_DT_DEVICE_QUALIFIER:
- if (!descs->qual) {
- qual->bLength = sizeof(*qual);
- qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
- qual->bcdUSB = index->dev->bcdUSB;
- qual->bDeviceClass = index->dev->bDeviceClass;
- qual->bDeviceSubClass = index->dev->bDeviceSubClass;
- qual->bDeviceProtocol = index->dev->bDeviceProtocol;
- qual->bMaxPacketSize0 = index->dev->bMaxPacketSize0;
- qual->bNumConfigurations = index->dev->bNumConfigurations;
- qual->bRESERVED = 0;
- *response_data = (char*)qual;
- *response_length = sizeof(*qual);
- return true;
- }
- *response_data = descs->qual;
- *response_length = descs->qual_len;
- return true;
- default:
- break;
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- debug("lookup_connect_response_in: unknown request");
- return false;
-}
-
-#endif
-
-typedef bool (*lookup_connect_out_response_t)(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl, bool* done);
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect
-static bool lookup_connect_response_out_generic(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl, bool* done)
-{
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
- case USB_REQ_SET_CONFIGURATION:
- *done = true;
- return true;
- default:
- break;
- }
- break;
- }
-
- debug("lookup_connect_response_out: unknown request");
- return false;
-}
-#endif
-
-#if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k)
-#define ATH9K_FIRMWARE_DOWNLOAD 0x30
-#define ATH9K_FIRMWARE_DOWNLOAD_COMP 0x31
-
-static bool lookup_connect_response_out_ath9k(int fd, const struct vusb_connect_descriptors* descs,
- const struct usb_ctrlrequest* ctrl, bool* done)
-{
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- switch (ctrl->bRequest) {
- case USB_REQ_SET_CONFIGURATION:
- return true;
- default:
- break;
- }
- break;
- case USB_TYPE_VENDOR:
- switch (ctrl->bRequest) {
- case ATH9K_FIRMWARE_DOWNLOAD:
- return true;
- case ATH9K_FIRMWARE_DOWNLOAD_COMP:
- *done = true;
- return true;
- default:
- break;
- }
- break;
- }
-
- debug("lookup_connect_response_out_ath9k: unknown request");
- return false;
-}
-
-#endif
-
-#if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_control_io)
-
-struct vusb_descriptor {
- uint8 req_type;
- uint8 desc_type;
- uint32 len;
- char data[0];
-} __attribute__((packed));
-
-struct vusb_descriptors {
- uint32 len;
- struct vusb_descriptor* generic;
- struct vusb_descriptor* descs[0];
-} __attribute__((packed));
-
-struct vusb_response {
- uint8 type;
- uint8 req;
- uint32 len;
- char data[0];
-} __attribute__((packed));
-
-struct vusb_responses {
- uint32 len;
- struct vusb_response* generic;
- struct vusb_response* resps[0];
-} __attribute__((packed));
-
-static bool lookup_control_response(const struct vusb_descriptors* descs, const struct vusb_responses* resps,
- struct usb_ctrlrequest* ctrl, char** response_data, uint32* response_length)
-{
- int descs_num = 0;
- int resps_num = 0;
-
- if (descs)
- descs_num = (descs->len - offsetof(struct vusb_descriptors, descs)) / sizeof(descs->descs[0]);
- if (resps)
- resps_num = (resps->len - offsetof(struct vusb_responses, resps)) / sizeof(resps->resps[0]);
-
- uint8 req = ctrl->bRequest;
- uint8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
- uint8 desc_type = ctrl->wValue >> 8;
-
- if (req == USB_REQ_GET_DESCRIPTOR) {
- int i;
-
- for (i = 0; i < descs_num; i++) {
- struct vusb_descriptor* desc = descs->descs[i];
- if (!desc)
- continue;
- if (desc->req_type == req_type && desc->desc_type == desc_type) {
- *response_length = desc->len;
- if (*response_length != 0)
- *response_data = &desc->data[0];
- else
- *response_data = NULL;
- return true;
- }
- }
-
- if (descs && descs->generic) {
- *response_data = &descs->generic->data[0];
- *response_length = descs->generic->len;
- return true;
- }
- } else {
- int i;
-
- for (i = 0; i < resps_num; i++) {
- struct vusb_response* resp = resps->resps[i];
- if (!resp)
- continue;
- if (resp->type == req_type && resp->req == req) {
- *response_length = resp->len;
- if (*response_length != 0)
- *response_data = &resp->data[0];
- else
- *response_data = NULL;
- return true;
- }
- }
-
- if (resps && resps->generic) {
- *response_data = &resps->generic->data[0];
- *response_length = resps->generic->len;
- return true;
- }
- }
-
- return false;
-}
-
-#endif
-
-
-#define UDC_NAME_LENGTH_MAX 128
-
-struct usb_raw_init {
- __u8 driver_name[UDC_NAME_LENGTH_MAX];
- __u8 device_name[UDC_NAME_LENGTH_MAX];
- __u8 speed;
-};
-
-enum usb_raw_event_type {
- USB_RAW_EVENT_INVALID = 0,
- USB_RAW_EVENT_CONNECT = 1,
- USB_RAW_EVENT_CONTROL = 2,
-};
-
-struct usb_raw_event {
- __u32 type;
- __u32 length;
- __u8 data[0];
-};
-
-struct usb_raw_ep_io {
- __u16 ep;
- __u16 flags;
- __u32 length;
- __u8 data[0];
-};
-
-#define USB_RAW_EPS_NUM_MAX 30
-#define USB_RAW_EP_NAME_MAX 16
-#define USB_RAW_EP_ADDR_ANY 0xff
-
-struct usb_raw_ep_caps {
- __u32 type_control : 1;
- __u32 type_iso : 1;
- __u32 type_bulk : 1;
- __u32 type_int : 1;
- __u32 dir_in : 1;
- __u32 dir_out : 1;
-};
-
-struct usb_raw_ep_limits {
- __u16 maxpacket_limit;
- __u16 max_streams;
- __u32 reserved;
-};
-
-struct usb_raw_ep_info {
- __u8 name[USB_RAW_EP_NAME_MAX];
- __u32 addr;
- struct usb_raw_ep_caps caps;
- struct usb_raw_ep_limits limits;
-};
-
-struct usb_raw_eps_info {
- struct usb_raw_ep_info eps[USB_RAW_EPS_NUM_MAX];
-};
-
-#define USB_RAW_IOCTL_INIT _IOW('U', 0, struct usb_raw_init)
-#define USB_RAW_IOCTL_RUN _IO('U', 1)
-#define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event)
-#define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io)
-#define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io)
-#define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor)
-#define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32)
-#define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io)
-#define USB_RAW_IOCTL_EP_READ _IOWR('U', 8, struct usb_raw_ep_io)
-#define USB_RAW_IOCTL_CONFIGURE _IO('U', 9)
-#define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32)
-#define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info)
-#define USB_RAW_IOCTL_EP0_STALL _IO('U', 12)
-#define USB_RAW_IOCTL_EP_SET_HALT _IOW('U', 13, __u32)
-#define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32)
-#define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32)
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-static int usb_raw_open()
-{
- return open("/dev/raw-gadget", O_RDWR);
-}
-
-static int usb_raw_init(int fd, uint32 speed, const char* driver, const char* device)
-{
- struct usb_raw_init arg;
- strncpy((char*)&arg.driver_name[0], driver, sizeof(arg.driver_name));
- strncpy((char*)&arg.device_name[0], device, sizeof(arg.device_name));
- arg.speed = speed;
- return ioctl(fd, USB_RAW_IOCTL_INIT, &arg);
-}
-
-static int usb_raw_run(int fd)
-{
- return ioctl(fd, USB_RAW_IOCTL_RUN, 0);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_ep_write
-static int usb_raw_ep_write(int fd, struct usb_raw_ep_io* io)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP_WRITE, io);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_ep_read
-static int usb_raw_ep_read(int fd, struct usb_raw_ep_io* io)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP_READ, io);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-
-static int usb_raw_configure(int fd)
-{
- return ioctl(fd, USB_RAW_IOCTL_CONFIGURE, 0);
-}
-
-static int usb_raw_vbus_draw(int fd, uint32 power)
-{
- return ioctl(fd, USB_RAW_IOCTL_VBUS_DRAW, power);
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io
-static int usb_raw_ep0_write(int fd, struct usb_raw_ep_io* io)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP0_WRITE, io);
-}
-
-static int usb_raw_ep0_read(int fd, struct usb_raw_ep_io* io)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP0_READ, io);
-}
-
-static int usb_raw_event_fetch(int fd, struct usb_raw_event* event)
-{
- return ioctl(fd, USB_RAW_IOCTL_EVENT_FETCH, event);
-}
-
-static int usb_raw_ep_enable(int fd, struct usb_endpoint_descriptor* desc)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP_ENABLE, desc);
-}
-
-static int usb_raw_ep_disable(int fd, int ep)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP_DISABLE, ep);
-}
-
-static int usb_raw_ep0_stall(int fd)
-{
- return ioctl(fd, USB_RAW_IOCTL_EP0_STALL, 0);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_control_io
-static int lookup_interface(int fd, uint8 bInterfaceNumber, uint8 bAlternateSetting)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
- if (!index)
- return -1;
-
- for (int i = 0; i < index->ifaces_num; i++) {
- if (index->ifaces[i].bInterfaceNumber == bInterfaceNumber &&
- index->ifaces[i].bAlternateSetting == bAlternateSetting)
- return i;
- }
- return -1;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_ep_write || __NR_syz_usb_ep_read
-static int lookup_endpoint(int fd, uint8 bEndpointAddress)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
- if (!index)
- return -1;
- if (index->iface_cur < 0)
- return -1;
-
- for (int ep = 0; ep < index->ifaces[index->iface_cur].eps_num; ep++)
- if (index->ifaces[index->iface_cur].eps[ep].desc.bEndpointAddress == bEndpointAddress)
- return index->ifaces[index->iface_cur].eps[ep].handle;
- return -1;
-}
-#endif
-
-#define USB_MAX_PACKET_SIZE 4096
-
-struct usb_raw_control_event {
- struct usb_raw_event inner;
- struct usb_ctrlrequest ctrl;
- char data[USB_MAX_PACKET_SIZE];
-};
-
-struct usb_raw_ep_io_data {
- struct usb_raw_ep_io inner;
- char data[USB_MAX_PACKET_SIZE];
-};
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io
-static void set_interface(int fd, int n)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
- if (!index)
- return;
-
- if (index->iface_cur >= 0 && index->iface_cur < index->ifaces_num) {
- for (int ep = 0; ep < index->ifaces[index->iface_cur].eps_num; ep++) {
- int rv = usb_raw_ep_disable(fd, index->ifaces[index->iface_cur].eps[ep].handle);
- if (rv < 0) {
- debug("set_interface: failed to disable endpoint 0x%02x\n",
- index->ifaces[index->iface_cur].eps[ep].desc.bEndpointAddress);
- } else {
- debug("set_interface: endpoint 0x%02x disabled\n",
- index->ifaces[index->iface_cur].eps[ep].desc.bEndpointAddress);
- }
- }
- }
- if (n >= 0 && n < index->ifaces_num) {
- for (int ep = 0; ep < index->ifaces[n].eps_num; ep++) {
- int rv = usb_raw_ep_enable(fd, &index->ifaces[n].eps[ep].desc);
- if (rv < 0) {
- debug("set_interface: failed to enable endpoint 0x%02x\n",
- index->ifaces[n].eps[ep].desc.bEndpointAddress);
- } else {
- debug("set_interface: endpoint 0x%02x enabled as %d\n",
- index->ifaces[n].eps[ep].desc.bEndpointAddress, rv);
- index->ifaces[n].eps[ep].handle = rv;
- }
- }
- index->iface_cur = n;
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
-static int configure_device(int fd)
-{
- struct usb_device_index* index = lookup_usb_index(fd);
-
- if (!index)
- return -1;
-
- int rv = usb_raw_vbus_draw(fd, index->bMaxPower);
- if (rv < 0) {
- debug("configure_device: usb_raw_vbus_draw failed with %d\n", rv);
- return rv;
- }
- rv = usb_raw_configure(fd);
- if (rv < 0) {
- debug("configure_device: usb_raw_configure failed with %d\n", rv);
- return rv;
- }
- set_interface(fd, 0);
- return 0;
-}
-
-static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const char* dev,
- const struct vusb_connect_descriptors* descs,
- lookup_connect_out_response_t lookup_connect_response_out)
-{
- debug("syz_usb_connect: dev: %p\n", dev);
- if (!dev) {
- debug("syz_usb_connect: dev is null\n");
- return -1;
- }
-
- debug("syz_usb_connect: device data:\n");
- debug_dump_data(dev, dev_len);
-
- int fd = usb_raw_open();
- if (fd < 0) {
- debug("syz_usb_connect: usb_raw_open failed with %d\n", fd);
- return fd;
- }
- if (fd >= MAX_FDS) {
- close(fd);
- debug("syz_usb_connect: too many open fds\n");
- return -1;
- }
- debug("syz_usb_connect: usb_raw_open success\n");
-
- struct usb_device_index* index = add_usb_index(fd, dev, dev_len);
- if (!index) {
- debug("syz_usb_connect: add_usb_index failed\n");
- return -1;
- }
- debug("syz_usb_connect: add_usb_index success\n");
-
-#if USB_DEBUG
- analyze_usb_device(index);
-#endif
- char device[32];
- sprintf(&device[0], "dummy_udc.%llu", procid);
- int rv = usb_raw_init(fd, speed, "dummy_udc", &device[0]);
- if (rv < 0) {
- debug("syz_usb_connect: usb_raw_init failed with %d\n", rv);
- return rv;
- }
- debug("syz_usb_connect: usb_raw_init success\n");
-
- rv = usb_raw_run(fd);
- if (rv < 0) {
- debug("syz_usb_connect: usb_raw_run failed with %d\n", rv);
- return rv;
- }
- debug("syz_usb_connect: usb_raw_run success\n");
-
- bool done = false;
- while (!done) {
- struct usb_raw_control_event event;
- event.inner.type = 0;
- event.inner.length = sizeof(event.ctrl);
- rv = usb_raw_event_fetch(fd, (struct usb_raw_event*)&event);
- if (rv < 0) {
- debug("syz_usb_connect: usb_raw_event_fetch failed with %d\n", rv);
- return rv;
- }
- if (event.inner.type != USB_RAW_EVENT_CONTROL)
- continue;
-
- debug("syz_usb_connect: bReqType: 0x%x (%s), bReq: 0x%x, wVal: 0x%x, wIdx: 0x%x, wLen: %d\n",
- event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT",
- event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength);
-
-#if USB_DEBUG
- analyze_control_request(fd, &event.ctrl);
-#endif
-
- char* response_data = NULL;
- uint32 response_length = 0;
- struct usb_qualifier_descriptor qual;
-
- if (event.ctrl.bRequestType & USB_DIR_IN) {
- if (!lookup_connect_response_in(fd, descs, &event.ctrl, &qual, &response_data, &response_length)) {
- debug("syz_usb_connect: unknown request, stalling\n");
- usb_raw_ep0_stall(fd);
- continue;
- }
- } else {
- if (!lookup_connect_response_out(fd, descs, &event.ctrl, &done)) {
- debug("syz_usb_connect: unknown request, stalling\n");
- usb_raw_ep0_stall(fd);
- continue;
- }
- response_data = NULL;
- response_length = event.ctrl.wLength;
- }
-
- if ((event.ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
- event.ctrl.bRequest == USB_REQ_SET_CONFIGURATION) {
- rv = configure_device(fd);
- if (rv < 0) {
- debug("syz_usb_connect: configure_device failed with %d\n", rv);
- return rv;
- }
- }
-
- struct usb_raw_ep_io_data response;
- response.inner.ep = 0;
- response.inner.flags = 0;
- if (response_length > sizeof(response.data))
- response_length = 0;
- if (event.ctrl.wLength < response_length)
- response_length = event.ctrl.wLength;
- response.inner.length = response_length;
- if (response_data)
- memcpy(&response.data[0], response_data, response_length);
- else
- memset(&response.data[0], 0, response_length);
-
- if (event.ctrl.bRequestType & USB_DIR_IN) {
- debug("syz_usb_connect: writing %d bytes\n", response.inner.length);
- rv = usb_raw_ep0_write(fd, (struct usb_raw_ep_io*)&response);
- } else {
- rv = usb_raw_ep0_read(fd, (struct usb_raw_ep_io*)&response);
- debug("syz_usb_connect: read %d bytes\n", response.inner.length);
- debug_dump_data(&event.data[0], response.inner.length);
- }
- if (rv < 0) {
- debug("syz_usb_connect: usb_raw_ep0_read/write failed with %d\n", rv);
- return rv;
- }
- }
-
- sleep_ms(200);
-
- debug("syz_usb_connect: configured\n");
-
- return fd;
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect
-static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
-{
- uint64 speed = a0;
- uint64 dev_len = a1;
- const char* dev = (const char*)a2;
- const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a3;
-
- return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_generic);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k
-static volatile long syz_usb_connect_ath9k(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
-{
- uint64 speed = a0;
- uint64 dev_len = a1;
- const char* dev = (const char*)a2;
- const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a3;
-
- return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_ath9k);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_control_io
-static volatile long syz_usb_control_io(volatile long a0, volatile long a1, volatile long a2)
-{
- int fd = a0;
- const struct vusb_descriptors* descs = (const struct vusb_descriptors*)a1;
- const struct vusb_responses* resps = (const struct vusb_responses*)a2;
-
- struct usb_raw_control_event event;
- event.inner.type = 0;
- event.inner.length = USB_MAX_PACKET_SIZE;
- int rv = usb_raw_event_fetch(fd, (struct usb_raw_event*)&event);
- if (rv < 0) {
- debug("syz_usb_control_io: usb_raw_ep0_read failed with %d\n", rv);
- return rv;
- }
- if (event.inner.type != USB_RAW_EVENT_CONTROL) {
- debug("syz_usb_control_io: wrong event type: %d\n", (int)event.inner.type);
- return -1;
- }
-
- debug("syz_usb_control_io: bReqType: 0x%x (%s), bReq: 0x%x, wVal: 0x%x, wIdx: 0x%x, wLen: %d\n",
- event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT",
- event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength);
-
-#if USB_DEBUG
- analyze_control_request(fd, &event.ctrl);
-#endif
-
- char* response_data = NULL;
- uint32 response_length = 0;
-
- if ((event.ctrl.bRequestType & USB_DIR_IN) && event.ctrl.wLength) {
- if (!lookup_control_response(descs, resps, &event.ctrl, &response_data, &response_length)) {
- debug("syz_usb_connect: unknown request, stalling\n");
- usb_raw_ep0_stall(fd);
- return -1;
- }
- } else {
- if ((event.ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD ||
- event.ctrl.bRequest == USB_REQ_SET_INTERFACE) {
- int iface_num = event.ctrl.wIndex;
- int alt_set = event.ctrl.wValue;
- debug("syz_usb_control_io: setting interface (%d, %d)\n", iface_num, alt_set);
- int iface_index = lookup_interface(fd, iface_num, alt_set);
- if (iface_index < 0) {
- debug("syz_usb_control_io: interface (%d, %d) not found\n", iface_num, alt_set);
- } else {
- set_interface(fd, iface_index);
- debug("syz_usb_control_io: interface (%d, %d) set\n", iface_num, alt_set);
- }
- }
-
- response_length = event.ctrl.wLength;
- }
-
- struct usb_raw_ep_io_data response;
- response.inner.ep = 0;
- response.inner.flags = 0;
- if (response_length > sizeof(response.data))
- response_length = 0;
- if (event.ctrl.wLength < response_length)
- response_length = event.ctrl.wLength;
- if ((event.ctrl.bRequestType & USB_DIR_IN) && !event.ctrl.wLength) {
- response_length = USB_MAX_PACKET_SIZE;
- }
- response.inner.length = response_length;
- if (response_data)
- memcpy(&response.data[0], response_data, response_length);
- else
- memset(&response.data[0], 0, response_length);
-
- if ((event.ctrl.bRequestType & USB_DIR_IN) && event.ctrl.wLength) {
- debug("syz_usb_control_io: writing %d bytes\n", response.inner.length);
- debug_dump_data(&response.data[0], response.inner.length);
- rv = usb_raw_ep0_write(fd, (struct usb_raw_ep_io*)&response);
- } else {
- rv = usb_raw_ep0_read(fd, (struct usb_raw_ep_io*)&response);
- debug("syz_usb_control_io: read %d bytes\n", response.inner.length);
- debug_dump_data(&response.data[0], response.inner.length);
- }
- if (rv < 0) {
- debug("syz_usb_control_io: usb_raw_ep0_read/write failed with %d\n", rv);
- return rv;
- }
-
- sleep_ms(200);
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_ep_write
-static volatile long syz_usb_ep_write(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
-{
- int fd = a0;
- uint8 ep = a1;
- uint32 len = a2;
- char* data = (char*)a3;
-
- int ep_handle = lookup_endpoint(fd, ep);
- if (ep_handle < 0) {
- debug("syz_usb_ep_write: endpoint not found\n");
- return -1;
- }
- debug("syz_usb_ep_write: endpoint handle: %d\n", ep_handle);
-
- struct usb_raw_ep_io_data io_data;
- io_data.inner.ep = ep_handle;
- io_data.inner.flags = 0;
- if (len > sizeof(io_data.data))
- len = sizeof(io_data.data);
- io_data.inner.length = len;
- memcpy(&io_data.data[0], data, len);
-
- int rv = usb_raw_ep_write(fd, (struct usb_raw_ep_io*)&io_data);
- if (rv < 0) {
- debug("syz_usb_ep_write: usb_raw_ep_write failed with %d\n", rv);
- return rv;
- }
-
- sleep_ms(200);
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_ep_read
-static volatile long syz_usb_ep_read(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
-{
- int fd = a0;
- uint8 ep = a1;
- uint32 len = a2;
- char* data = (char*)a3;
-
- int ep_handle = lookup_endpoint(fd, ep);
- if (ep_handle < 0) {
- debug("syz_usb_ep_read: endpoint not found\n");
- return -1;
- }
- debug("syz_usb_ep_read: endpoint handle: %d\n", ep_handle);
-
- struct usb_raw_ep_io_data io_data;
- io_data.inner.ep = ep_handle;
- io_data.inner.flags = 0;
- if (len > sizeof(io_data.data))
- len = sizeof(io_data.data);
- io_data.inner.length = len;
-
- int rv = usb_raw_ep_read(fd, (struct usb_raw_ep_io*)&io_data);
- if (rv < 0) {
- debug("syz_usb_ep_read: usb_raw_ep_read failed with %d\n", rv);
- return rv;
- }
-
- memcpy(&data[0], &io_data.data[0], io_data.inner.length);
-
- debug("syz_usb_ep_read: received data:\n");
- debug_dump_data(&io_data.data[0], io_data.inner.length);
-
- sleep_ms(200);
-
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_usb_disconnect
-static volatile long syz_usb_disconnect(volatile long a0)
-{
- int fd = a0;
-
- int rv = close(fd);
-
- sleep_ms(200);
-
- return rv;
-}
-#endif
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_open_dev
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2)
-{
- if (a0 == 0xc || a0 == 0xb) {
- char buf[128];
- sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8)a1, (uint8)a2);
- return open(buf, O_RDWR, 0);
- } else {
- char buf[1024];
- char* hash;
- strncpy(buf, (char*)a0, sizeof(buf) - 1);
- buf[sizeof(buf) - 1] = 0;
- while ((hash = strchr(buf, '#'))) {
- *hash = '0' + (char)(a1 % 10);
- a1 /= 10;
- }
- return open(buf, a2, 0);
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_open_procfs
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static long syz_open_procfs(volatile long a0, volatile long a1)
-{
-
- char buf[128];
- memset(buf, 0, sizeof(buf));
- if (a0 == 0) {
- snprintf(buf, sizeof(buf), "/proc/self/%s", (char*)a1);
- } else if (a0 == -1) {
- snprintf(buf, sizeof(buf), "/proc/thread-self/%s", (char*)a1);
- } else {
- snprintf(buf, sizeof(buf), "/proc/self/task/%d/%s", (int)a0, (char*)a1);
- }
- int fd = open(buf, O_RDWR);
- if (fd == -1)
- fd = open(buf, O_RDONLY);
- return fd;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_open_pts
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static long syz_open_pts(volatile long a0, volatile long a1)
-{
- int ptyno = 0;
- if (ioctl(a0, TIOCGPTN, &ptyno))
- return -1;
- char buf[128];
- sprintf(buf, "/dev/pts/%d", ptyno);
- return open(buf, a1, 0);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_init_net_socket
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-static long syz_init_net_socket(volatile long domain, volatile long type, volatile long proto)
-{
- int netns = open("/proc/self/ns/net", O_RDONLY);
- if (netns == -1)
- return netns;
- if (setns(kInitNetNsFd, 0))
- return -1;
- int sock = syscall(__NR_socket, domain, type, proto);
- int err = errno;
- if (setns(netns, 0)) {
- exitf("setns(netns) failed");
- }
- close(netns);
- errno = err;
- return sock;
-}
-#else
-static long syz_init_net_socket(volatile long domain, volatile long type, volatile long proto)
-{
- return syscall(__NR_socket, domain, type, proto);
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_socket_connect_nvme_tcp
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-static long syz_socket_connect_nvme_tcp()
-{
- struct sockaddr_in nvme_local_address;
- int netns = open("/proc/self/ns/net", O_RDONLY);
- if (netns == -1)
- return netns;
- if (setns(kInitNetNsFd, 0))
- return -1;
- int sock = syscall(__NR_socket, AF_INET, SOCK_STREAM, 0x0);
- int err = errno;
- if (setns(netns, 0)) {
- exitf("setns(netns) failed");
- }
- close(netns);
- errno = err;
- nvme_local_address.sin_family = AF_INET;
- nvme_local_address.sin_port = htobe16(4420);
- nvme_local_address.sin_addr.s_addr = htobe32(0x7f000001);
- err = syscall(__NR_connect, sock, &nvme_local_address, sizeof(nvme_local_address));
- if (err != 0) {
- close(sock);
- return -1;
- }
- return sock;
-}
-#else
-static long syz_socket_connect_nvme_tcp()
-{
- return syscall(__NR_socket, -1, 0, 0);
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_VHCI_INJECTION
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/rfkill.h>
-#include <pthread.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#define BTPROTO_HCI 1
-#define ACL_LINK 1
-#define SCAN_PAGE 2
-
-typedef struct {
- uint8 b[6];
-} __attribute__((packed)) bdaddr_t;
-
-#define HCI_COMMAND_PKT 1
-#define HCI_EVENT_PKT 4
-#define HCI_VENDOR_PKT 0xff
-
-struct hci_command_hdr {
- uint16 opcode;
- uint8 plen;
-} __attribute__((packed));
-
-struct hci_event_hdr {
- uint8 evt;
- uint8 plen;
-} __attribute__((packed));
-
-#define HCI_EV_CONN_COMPLETE 0x03
-struct hci_ev_conn_complete {
- uint8 status;
- uint16 handle;
- bdaddr_t bdaddr;
- uint8 link_type;
- uint8 encr_mode;
-} __attribute__((packed));
-
-#define HCI_EV_CONN_REQUEST 0x04
-struct hci_ev_conn_request {
- bdaddr_t bdaddr;
- uint8 dev_class[3];
- uint8 link_type;
-} __attribute__((packed));
-
-#define HCI_EV_REMOTE_FEATURES 0x0b
-struct hci_ev_remote_features {
- uint8 status;
- uint16 handle;
- uint8 features[8];
-} __attribute__((packed));
-
-#define HCI_EV_CMD_COMPLETE 0x0e
-struct hci_ev_cmd_complete {
- uint8 ncmd;
- uint16 opcode;
-} __attribute__((packed));
-
-#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a
-
-#define HCI_OP_READ_BUFFER_SIZE 0x1005
-struct hci_rp_read_buffer_size {
- uint8 status;
- uint16 acl_mtu;
- uint8 sco_mtu;
- uint16 acl_max_pkt;
- uint16 sco_max_pkt;
-} __attribute__((packed));
-
-#define HCI_OP_READ_BD_ADDR 0x1009
-struct hci_rp_read_bd_addr {
- uint8 status;
- bdaddr_t bdaddr;
-} __attribute__((packed));
-
-#define HCI_EV_LE_META 0x3e
-struct hci_ev_le_meta {
- uint8 subevent;
-} __attribute__((packed));
-
-#define HCI_EV_LE_CONN_COMPLETE 0x01
-struct hci_ev_le_conn_complete {
- uint8 status;
- uint16 handle;
- uint8 role;
- uint8 bdaddr_type;
- bdaddr_t bdaddr;
- uint16 interval;
- uint16 latency;
- uint16 supervision_timeout;
- uint8 clk_accurancy;
-} __attribute__((packed));
-
-struct hci_dev_req {
- uint16 dev_id;
- uint32 dev_opt;
-};
-
-struct vhci_vendor_pkt_request {
- uint8 type;
- uint8 opcode;
-} __attribute__((packed));
-
-struct vhci_pkt {
- uint8 type;
- union {
- struct {
- uint8 opcode;
- uint16 id;
- } __attribute__((packed)) vendor_pkt;
- struct hci_command_hdr command_hdr;
- };
-} __attribute__((packed));
-
-#define HCIDEVUP _IOW('H', 201, int)
-#define HCISETSCAN _IOW('H', 221, int)
-
-static int vhci_fd = -1;
-
-static void rfkill_unblock_all()
-{
- int fd = open("/dev/rfkill", O_WRONLY);
- if (fd < 0)
- fail("open /dev/rfkill failed");
- struct rfkill_event event = {0};
- event.idx = 0;
- event.type = RFKILL_TYPE_ALL;
- event.op = RFKILL_OP_CHANGE_ALL;
- event.soft = 0;
- event.hard = 0;
- if (write(fd, &event, sizeof(event)) < 0)
- fail("write rfkill event failed");
- close(fd);
-}
-
-static void hci_send_event_packet(int fd, uint8 evt, void* data, size_t data_len)
-{
- struct iovec iv[3];
-
- struct hci_event_hdr hdr;
- hdr.evt = evt;
- hdr.plen = data_len;
-
- uint8 type = HCI_EVENT_PKT;
-
- iv[0].iov_base = &type;
- iv[0].iov_len = sizeof(type);
- iv[1].iov_base = &hdr;
- iv[1].iov_len = sizeof(hdr);
- iv[2].iov_base = data;
- iv[2].iov_len = data_len;
-
- if (writev(fd, iv, sizeof(iv) / sizeof(struct iovec)) < 0)
- fail("writev failed");
-}
-
-static void hci_send_event_cmd_complete(int fd, uint16 opcode, void* data, size_t data_len)
-{
- struct iovec iv[4];
-
- struct hci_event_hdr hdr;
- hdr.evt = HCI_EV_CMD_COMPLETE;
- hdr.plen = sizeof(struct hci_ev_cmd_complete) + data_len;
-
- struct hci_ev_cmd_complete evt_hdr;
- evt_hdr.ncmd = 1;
- evt_hdr.opcode = opcode;
-
- uint8 type = HCI_EVENT_PKT;
-
- iv[0].iov_base = &type;
- iv[0].iov_len = sizeof(type);
- iv[1].iov_base = &hdr;
- iv[1].iov_len = sizeof(hdr);
- iv[2].iov_base = &evt_hdr;
- iv[2].iov_len = sizeof(evt_hdr);
- iv[3].iov_base = data;
- iv[3].iov_len = data_len;
-
- if (writev(fd, iv, sizeof(iv) / sizeof(struct iovec)) < 0)
- fail("writev failed");
-}
-
-static bool process_command_pkt(int fd, char* buf, ssize_t buf_size)
-{
- struct hci_command_hdr* hdr = (struct hci_command_hdr*)buf;
- if (buf_size < (ssize_t)sizeof(struct hci_command_hdr) ||
- hdr->plen != buf_size - sizeof(struct hci_command_hdr))
- failmsg("process_command_pkt: invalid size", "suze=%zx", buf_size);
-
- switch (hdr->opcode) {
- case HCI_OP_WRITE_SCAN_ENABLE: {
- uint8 status = 0;
- hci_send_event_cmd_complete(fd, hdr->opcode, &status, sizeof(status));
- return true;
- }
- case HCI_OP_READ_BD_ADDR: {
- struct hci_rp_read_bd_addr rp = {0};
- rp.status = 0;
- memset(&rp.bdaddr, 0xaa, 6);
- hci_send_event_cmd_complete(fd, hdr->opcode, &rp, sizeof(rp));
- return false;
- }
- case HCI_OP_READ_BUFFER_SIZE: {
- struct hci_rp_read_buffer_size rp = {0};
- rp.status = 0;
- rp.acl_mtu = 1021;
- rp.sco_mtu = 96;
- rp.acl_max_pkt = 4;
- rp.sco_max_pkt = 6;
- hci_send_event_cmd_complete(fd, hdr->opcode, &rp, sizeof(rp));
- return false;
- }
- }
-
- char dummy[0xf9] = {0};
- hci_send_event_cmd_complete(fd, hdr->opcode, dummy, sizeof(dummy));
- return false;
-}
-
-static void* event_thread(void* arg)
-{
- while (1) {
- char buf[1024] = {0};
- ssize_t buf_size = read(vhci_fd, buf, sizeof(buf));
- if (buf_size < 0)
- fail("read failed");
- debug_dump_data(buf, buf_size);
- if (buf_size > 0 && buf[0] == HCI_COMMAND_PKT) {
- if (process_command_pkt(vhci_fd, buf + 1, buf_size - 1))
- break;
- }
- }
- return NULL;
-}
-#define HCI_HANDLE_1 200
-#define HCI_HANDLE_2 201
-
-#define HCI_PRIMARY 0
-#define HCI_OP_RESET 0x0c03
-
-static void initialize_vhci()
-{
-#if SYZ_EXECUTOR
- if (!flag_vhci_injection)
- return;
-#endif
-
- int hci_sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
- if (hci_sock < 0)
- fail("socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI) failed");
-
- vhci_fd = open("/dev/vhci", O_RDWR);
- if (vhci_fd == -1)
- fail("open /dev/vhci failed");
- const int kVhciFd = 202;
- if (dup2(vhci_fd, kVhciFd) < 0)
- fail("dup2(vhci_fd, kVhciFd) failed");
- close(vhci_fd);
- vhci_fd = kVhciFd;
-
- struct vhci_vendor_pkt_request vendor_pkt_req = {HCI_VENDOR_PKT, HCI_PRIMARY};
- if (write(vhci_fd, &vendor_pkt_req, sizeof(vendor_pkt_req)) != sizeof(vendor_pkt_req))
- fail("vendor_pkt_req write failed");
-
- struct vhci_pkt vhci_pkt;
- if (read(vhci_fd, &vhci_pkt, sizeof(vhci_pkt)) != sizeof(vhci_pkt))
- fail("vhci_pkt read failed");
-
- if (vhci_pkt.type == HCI_COMMAND_PKT && vhci_pkt.command_hdr.opcode == HCI_OP_RESET) {
- char response[1] = {0};
- hci_send_event_cmd_complete(vhci_fd, HCI_OP_RESET, response, sizeof(response));
-
- if (read(vhci_fd, &vhci_pkt, sizeof(vhci_pkt)) != sizeof(vhci_pkt))
- fail("vhci_pkt read failed");
- }
-
- if (vhci_pkt.type != HCI_VENDOR_PKT)
- fail("wrong response packet");
-
- int dev_id = vhci_pkt.vendor_pkt.id;
- debug("hci dev id: %x\n", dev_id);
-
- pthread_t th;
- if (pthread_create(&th, NULL, event_thread, NULL))
- fail("pthread_create failed");
- int ret = ioctl(hci_sock, HCIDEVUP, dev_id);
- if (ret) {
- if (errno == ERFKILL) {
- rfkill_unblock_all();
- ret = ioctl(hci_sock, HCIDEVUP, dev_id);
- }
-
- if (ret && errno != EALREADY)
- fail("ioctl(HCIDEVUP) failed");
- }
- struct hci_dev_req dr = {0};
- dr.dev_id = dev_id;
- dr.dev_opt = SCAN_PAGE;
- if (ioctl(hci_sock, HCISETSCAN, &dr))
- fail("ioctl(HCISETSCAN) failed");
- struct hci_ev_conn_request request;
- memset(&request, 0, sizeof(request));
- memset(&request.bdaddr, 0xaa, 6);
- *(uint8*)&request.bdaddr.b[5] = 0x10;
- request.link_type = ACL_LINK;
- hci_send_event_packet(vhci_fd, HCI_EV_CONN_REQUEST, &request, sizeof(request));
-
- struct hci_ev_conn_complete complete;
- memset(&complete, 0, sizeof(complete));
- complete.status = 0;
- complete.handle = HCI_HANDLE_1;
- memset(&complete.bdaddr, 0xaa, 6);
- *(uint8*)&complete.bdaddr.b[5] = 0x10;
- complete.link_type = ACL_LINK;
- complete.encr_mode = 0;
- hci_send_event_packet(vhci_fd, HCI_EV_CONN_COMPLETE, &complete, sizeof(complete));
-
- struct hci_ev_remote_features features;
- memset(&features, 0, sizeof(features));
- features.status = 0;
- features.handle = HCI_HANDLE_1;
- hci_send_event_packet(vhci_fd, HCI_EV_REMOTE_FEATURES, &features, sizeof(features));
- struct {
- struct hci_ev_le_meta le_meta;
- struct hci_ev_le_conn_complete le_conn;
- } le_conn;
- memset(&le_conn, 0, sizeof(le_conn));
- le_conn.le_meta.subevent = HCI_EV_LE_CONN_COMPLETE;
- memset(&le_conn.le_conn.bdaddr, 0xaa, 6);
- *(uint8*)&le_conn.le_conn.bdaddr.b[5] = 0x11;
- le_conn.le_conn.role = 1;
- le_conn.le_conn.handle = HCI_HANDLE_2;
- hci_send_event_packet(vhci_fd, HCI_EV_LE_META, &le_conn, sizeof(le_conn));
-
- pthread_join(th, NULL);
- close(hci_sock);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_emit_vhci && SYZ_VHCI_INJECTION
-static long syz_emit_vhci(volatile long a0, volatile long a1)
-{
- if (vhci_fd < 0)
- return (uintptr_t)-1;
-
- char* data = (char*)a0;
- uint32 length = a1;
-
- return write(vhci_fd, data, length);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_genetlink_get_family_id
-#include <errno.h>
-#include <sys/socket.h>
-
-static long syz_genetlink_get_family_id(volatile long name, volatile long sock_arg)
-{
- debug("syz_genetlink_get_family_id(%s, %d)\n", (char*)name, (int)sock_arg);
- int fd = sock_arg;
- if (fd < 0) {
- fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (fd == -1) {
- debug("syz_genetlink_get_family_id: socket failed: %d\n", errno);
- return -1;
- }
- }
- struct nlmsg nlmsg_tmp;
- int ret = netlink_query_family_id(&nlmsg_tmp, fd, (char*)name, false);
- if ((int)sock_arg < 0)
- close(fd);
- if (ret < 0) {
- debug("syz_genetlink_get_family_id: netlink_query_family_id failed: %d\n", ret);
- return -1;
- }
-
- return ret;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_mount_image || __NR_syz_read_part_table
-
-//% This code is derived from puff.{c,h}, found in the zlib development. The
-//% original files come with the following copyright notice:
-
-//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
-//% version 2.3, 21 Jan 2013
-//% This software is provided 'as-is', without any express or implied
-//% warranty. In no event will the author be held liable for any damages
-//% arising from the use of this software.
-//% Permission is granted to anyone to use this software for any purpose,
-//% including commercial applications, and to alter it and redistribute it
-//% freely, subject to the following restrictions:
-//% 1. The origin of this software must not be misrepresented; you must not
-//% claim that you wrote the original software. If you use this software
-//% in a product, an acknowledgment in the product documentation would be
-//% appreciated but is not required.
-//% 2. Altered source versions must be plainly marked as such, and must not be
-//% misrepresented as being the original software.
-//% 3. This notice may not be removed or altered from any source distribution.
-//% Mark Adler madler@alumni.caltech.edu
-
-//% BEGIN CODE DERIVED FROM puff.{c,h}
-
-#include <setjmp.h>
-#define MAXBITS 15
-#define MAXLCODES 286
-#define MAXDCODES 30
-#define MAXCODES (MAXLCODES + MAXDCODES)
-#define FIXLCODES 288
-
-struct puff_state {
- unsigned char* out;
- unsigned long outlen;
- unsigned long outcnt;
- const unsigned char* in;
- unsigned long inlen;
- unsigned long incnt;
- int bitbuf;
- int bitcnt;
- jmp_buf env;
-};
-static int puff_bits(struct puff_state* s, int need)
-{
- long val = s->bitbuf;
- while (s->bitcnt < need) {
- if (s->incnt == s->inlen)
- longjmp(s->env, 1);
- val |= (long)(s->in[s->incnt++]) << s->bitcnt;
- s->bitcnt += 8;
- }
- s->bitbuf = (int)(val >> need);
- s->bitcnt -= need;
- return (int)(val & ((1L << need) - 1));
-}
-static int puff_stored(struct puff_state* s)
-{
- s->bitbuf = 0;
- s->bitcnt = 0;
- if (s->incnt + 4 > s->inlen)
- return 2;
- unsigned len = s->in[s->incnt++];
- len |= s->in[s->incnt++] << 8;
- if (s->in[s->incnt++] != (~len & 0xff) ||
- s->in[s->incnt++] != ((~len >> 8) & 0xff))
- return -2;
- if (s->incnt + len > s->inlen)
- return 2;
- if (s->outcnt + len > s->outlen)
- return 1;
- for (; len--; s->outcnt++, s->incnt++) {
- if (s->in[s->incnt])
- s->out[s->outcnt] = s->in[s->incnt];
- }
- return 0;
-}
-struct puff_huffman {
- short* count;
- short* symbol;
-};
-static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
-{
- int first = 0;
- int index = 0;
- int bitbuf = s->bitbuf;
- int left = s->bitcnt;
- int code = first = index = 0;
- int len = 1;
- short* next = h->count + 1;
- while (1) {
- while (left--) {
- code |= bitbuf & 1;
- bitbuf >>= 1;
- int count = *next++;
- if (code - count < first) {
- s->bitbuf = bitbuf;
- s->bitcnt = (s->bitcnt - len) & 7;
- return h->symbol[index + (code - first)];
- }
- index += count;
- first += count;
- first <<= 1;
- code <<= 1;
- len++;
- }
- left = (MAXBITS + 1) - len;
- if (left == 0)
- break;
- if (s->incnt == s->inlen)
- longjmp(s->env, 1);
- bitbuf = s->in[s->incnt++];
- if (left > 8)
- left = 8;
- }
- return -10;
-}
-static int puff_construct(struct puff_huffman* h, const short* length, int n)
-{
- int len;
- for (len = 0; len <= MAXBITS; len++)
- h->count[len] = 0;
- int symbol;
- for (symbol = 0; symbol < n; symbol++)
- (h->count[length[symbol]])++;
- if (h->count[0] == n)
- return 0;
- int left = 1;
- for (len = 1; len <= MAXBITS; len++) {
- left <<= 1;
- left -= h->count[len];
- if (left < 0)
- return left;
- }
- short offs[MAXBITS + 1];
- offs[1] = 0;
- for (len = 1; len < MAXBITS; len++)
- offs[len + 1] = offs[len] + h->count[len];
- for (symbol = 0; symbol < n; symbol++)
- if (length[symbol] != 0)
- h->symbol[offs[length[symbol]]++] = symbol;
- return left;
-}
-static int puff_codes(struct puff_state* s,
- const struct puff_huffman* lencode,
- const struct puff_huffman* distcode)
-{
- static const short lens[29] = {
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
- static const short lext[29] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
- static const short dists[30] = {
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577};
- static const short dext[30] = {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13};
- int symbol;
- do {
- symbol = puff_decode(s, lencode);
- if (symbol < 0)
- return symbol;
- if (symbol < 256) {
- if (s->outcnt == s->outlen)
- return 1;
- if (symbol)
- s->out[s->outcnt] = symbol;
- s->outcnt++;
- } else if (symbol > 256) {
- symbol -= 257;
- if (symbol >= 29)
- return -10;
- int len = lens[symbol] + puff_bits(s, lext[symbol]);
- symbol = puff_decode(s, distcode);
- if (symbol < 0)
- return symbol;
- unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
- if (dist > s->outcnt)
- return -11;
- if (s->outcnt + len > s->outlen)
- return 1;
- while (len--) {
- if (dist <= s->outcnt && s->out[s->outcnt - dist])
- s->out[s->outcnt] = s->out[s->outcnt - dist];
- s->outcnt++;
- }
- }
- } while (symbol != 256);
- return 0;
-}
-static int puff_fixed(struct puff_state* s)
-{
- static int virgin = 1;
- static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
- static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- static struct puff_huffman lencode, distcode;
- if (virgin) {
- lencode.count = lencnt;
- lencode.symbol = lensym;
- distcode.count = distcnt;
- distcode.symbol = distsym;
- short lengths[FIXLCODES];
- int symbol;
- for (symbol = 0; symbol < 144; symbol++)
- lengths[symbol] = 8;
- for (; symbol < 256; symbol++)
- lengths[symbol] = 9;
- for (; symbol < 280; symbol++)
- lengths[symbol] = 7;
- for (; symbol < FIXLCODES; symbol++)
- lengths[symbol] = 8;
- puff_construct(&lencode, lengths, FIXLCODES);
- for (symbol = 0; symbol < MAXDCODES; symbol++)
- lengths[symbol] = 5;
- puff_construct(&distcode, lengths, MAXDCODES);
- virgin = 0;
- }
- return puff_codes(s, &lencode, &distcode);
-}
-static int puff_dynamic(struct puff_state* s)
-{
- static const short order[19] =
- {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
- int nlen = puff_bits(s, 5) + 257;
- int ndist = puff_bits(s, 5) + 1;
- int ncode = puff_bits(s, 4) + 4;
- if (nlen > MAXLCODES || ndist > MAXDCODES)
- return -3;
- short lengths[MAXCODES];
- int index;
- for (index = 0; index < ncode; index++)
- lengths[order[index]] = puff_bits(s, 3);
- for (; index < 19; index++)
- lengths[order[index]] = 0;
- short lencnt[MAXBITS + 1], lensym[MAXLCODES];
- struct puff_huffman lencode = {lencnt, lensym};
- int err = puff_construct(&lencode, lengths, 19);
- if (err != 0)
- return -4;
- index = 0;
- while (index < nlen + ndist) {
- int symbol;
- int len;
-
- symbol = puff_decode(s, &lencode);
- if (symbol < 0)
- return symbol;
- if (symbol < 16)
- lengths[index++] = symbol;
- else {
- len = 0;
- if (symbol == 16) {
- if (index == 0)
- return -5;
- len = lengths[index - 1];
- symbol = 3 + puff_bits(s, 2);
- } else if (symbol == 17)
- symbol = 3 + puff_bits(s, 3);
- else
- symbol = 11 + puff_bits(s, 7);
- if (index + symbol > nlen + ndist)
- return -6;
- while (symbol--)
- lengths[index++] = len;
- }
- }
- if (lengths[256] == 0)
- return -9;
- err = puff_construct(&lencode, lengths, nlen);
- if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
- return -7;
- short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- struct puff_huffman distcode = {distcnt, distsym};
- err = puff_construct(&distcode, lengths + nlen, ndist);
- if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
- return -8;
- return puff_codes(s, &lencode, &distcode);
-}
-static int puff(
- unsigned char* dest,
- unsigned long* destlen,
- const unsigned char* source,
- unsigned long sourcelen)
-{
- struct puff_state s = {
- .out = dest,
- .outlen = *destlen,
- .outcnt = 0,
- .in = source,
- .inlen = sourcelen,
- .incnt = 0,
- .bitbuf = 0,
- .bitcnt = 0,
- };
- int err;
- if (setjmp(s.env) != 0)
- err = 2;
- else {
- int last;
- do {
- last = puff_bits(&s, 1);
- int type = puff_bits(&s, 2);
- err = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));
- if (err != 0)
- break;
- } while (!last);
- }
-
- *destlen = s.outcnt;
- return err;
-}
-
-//% END CODE DERIVED FROM puff.{c,h}
-
-#include <errno.h>
-#include <sys/mman.h>
-#define ZLIB_HEADER_WIDTH 2
-
-static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
-{
- if (sourcelen < ZLIB_HEADER_WIDTH)
- return 0;
- source += ZLIB_HEADER_WIDTH;
- sourcelen -= ZLIB_HEADER_WIDTH;
- const unsigned long max_destlen = 132 << 20;
- void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
- if (ret == MAP_FAILED)
- return -1;
- unsigned char* dest = (unsigned char*)ret;
- unsigned long destlen = max_destlen;
- int err = puff(dest, &destlen, source, sourcelen);
- if (err) {
- munmap(dest, max_destlen);
- errno = -err;
- return -1;
- }
- if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
- munmap(dest, max_destlen);
- return -1;
- }
- return munmap(dest, max_destlen);
-}
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/loop.h>
-#include <stdbool.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-static int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* loopfd_p)
-{
- int err = 0, loopfd = -1;
- int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
- if (memfd == -1) {
- err = errno;
- goto error;
- }
- if (puff_zlib_to_file(data, size, memfd)) {
- err = errno;
- debug("setup_loop_device: could not decompress data: %d\n", errno);
- goto error_close_memfd;
- }
-
- loopfd = open(loopname, O_RDWR);
- if (loopfd == -1) {
- err = errno;
- debug("setup_loop_device: open failed: %d\n", errno);
- goto error_close_memfd;
- }
- if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
- if (errno != EBUSY) {
- err = errno;
- goto error_close_loop;
- }
- ioctl(loopfd, LOOP_CLR_FD, 0);
- usleep(1000);
- if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
- err = errno;
- goto error_close_loop;
- }
- }
-
- close(memfd);
- *loopfd_p = loopfd;
- return 0;
-
-error_close_loop:
- close(loopfd);
-error_close_memfd:
- close(memfd);
-error:
- errno = err;
- return -1;
-}
-
-#if SYZ_EXECUTOR || __NR_syz_mount_image
-
-static void reset_loop_device(const char* loopname)
-{
- int loopfd = open(loopname, O_RDWR);
- if (loopfd == -1) {
- debug("reset_loop_device: open failed: %d\n", errno);
- return;
- }
- if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
- debug("reset_loop_device: LOOP_CLR_FD failed: %d\n", errno);
- }
- close(loopfd);
-}
-
-#endif
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_read_part_table
-static long syz_read_part_table(volatile unsigned long size, volatile long image)
-{
- unsigned char* data = (unsigned char*)image;
- int err = 0, res = -1, loopfd = -1;
- char loopname[64];
-
- snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
- if (setup_loop_device(data, size, loopname, &loopfd) == -1)
- return -1;
-
- struct loop_info64 info;
- if (ioctl(loopfd, LOOP_GET_STATUS64, &info)) {
- err = errno;
- goto error_clear_loop;
- }
-#if SYZ_EXECUTOR
- cover_reset(0);
-#endif
- info.lo_flags |= LO_FLAGS_PARTSCAN;
- if (ioctl(loopfd, LOOP_SET_STATUS64, &info)) {
- err = errno;
- goto error_clear_loop;
- }
- res = 0;
- for (unsigned long i = 1, j = 0; i < 8; i++) {
- snprintf(loopname, sizeof(loopname), "/dev/loop%llup%d", procid, (int)i);
- struct stat statbuf;
- if (stat(loopname, &statbuf) == 0) {
- char linkname[64];
- snprintf(linkname, sizeof(linkname), "./file%d", (int)j++);
- if (symlink(loopname, linkname)) {
- debug("syz_read_part_table: symlink(%s, %s) failed: %d\n", loopname, linkname, errno);
- }
- }
- }
-error_clear_loop:
- if (res)
- ioctl(loopfd, LOOP_CLR_FD, 0);
- close(loopfd);
- errno = err;
- return res;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_mount_image
-#include <stddef.h>
-#include <string.h>
-#include <sys/mount.h>
-static long syz_mount_image(
- volatile long fsarg,
- volatile long dir,
- volatile long flags,
- volatile long optsarg,
- volatile long change_dir,
- volatile unsigned long size,
- volatile long image)
-{
- unsigned char* data = (unsigned char*)image;
- int res = -1, err = 0, need_loop_device = !!size;
- char* mount_opts = (char*)optsarg;
- char* target = (char*)dir;
- char* fs = (char*)fsarg;
- char* source = NULL;
- char loopname[64];
-
- if (need_loop_device) {
- int loopfd;
- memset(loopname, 0, sizeof(loopname));
- snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
- if (setup_loop_device(data, size, loopname, &loopfd) == -1)
- return -1;
- close(loopfd);
- source = loopname;
- }
-
- mkdir(target, 0777);
- char opts[256];
- memset(opts, 0, sizeof(opts));
- if (strlen(mount_opts) > (sizeof(opts) - 32)) {
- debug("ERROR: syz_mount_image parameter optsarg bigger than internal opts\n");
- }
- strncpy(opts, mount_opts, sizeof(opts) - 32);
- if (strcmp(fs, "iso9660") == 0) {
- flags |= MS_RDONLY;
- } else if (strncmp(fs, "ext", 3) == 0) {
- bool has_remount_ro = false;
- char* remount_ro_start = strstr(opts, "errors=remount-ro");
- if (remount_ro_start != NULL) {
- char after = *(remount_ro_start + strlen("errors=remount-ro"));
- char before = remount_ro_start == opts ? '\0' : *(remount_ro_start - 1);
- has_remount_ro = ((before == '\0' || before == ',') && (after == '\0' || after == ','));
- }
- if (strstr(opts, "errors=panic") || !has_remount_ro)
- strcat(opts, ",errors=continue");
- } else if (strcmp(fs, "xfs") == 0) {
- strcat(opts, ",nouuid");
- }
- debug("syz_mount_image: size=%llu loop='%s' dir='%s' fs='%s' flags=%llu opts='%s'\n", (uint64)size, loopname, target, fs, (uint64)flags, opts);
-#if SYZ_EXECUTOR
- cover_reset(0);
-#endif
- res = mount(source, target, fs, flags, opts);
- if (res == -1) {
- debug("syz_mount_image > mount error: %d\n", errno);
- err = errno;
- goto error_clear_loop;
- }
- res = open(target, O_RDONLY | O_DIRECTORY);
- if (res == -1) {
- debug("syz_mount_image > open error: %d\n", errno);
- err = errno;
- goto error_clear_loop;
- }
- if (change_dir) {
- res = chdir(target);
- if (res == -1) {
- debug("syz_mount_image > chdir error: %d\n", errno);
- err = errno;
- }
- }
-
-error_clear_loop:
- if (need_loop_device)
- reset_loop_device(loopname);
- errno = err;
- return res;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu
-#if !GOARCH_riscv64 && !GOARCH_arm
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/kvm.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-
-#if GOARCH_amd64
-
-#define ADDR_TEXT 0x0000
-#define ADDR_GDT 0x1000
-#define ADDR_LDT 0x1800
-#define ADDR_PML4 0x2000
-#define ADDR_PDP 0x3000
-#define ADDR_PD 0x4000
-#define ADDR_STACK0 0x0f80
-#define ADDR_VAR_HLT 0x2800
-#define ADDR_VAR_SYSRET 0x2808
-#define ADDR_VAR_SYSEXIT 0x2810
-#define ADDR_VAR_IDT 0x3800
-#define ADDR_VAR_TSS64 0x3a00
-#define ADDR_VAR_TSS64_CPL3 0x3c00
-#define ADDR_VAR_TSS16 0x3d00
-#define ADDR_VAR_TSS16_2 0x3e00
-#define ADDR_VAR_TSS16_CPL3 0x3f00
-#define ADDR_VAR_TSS32 0x4800
-#define ADDR_VAR_TSS32_2 0x4a00
-#define ADDR_VAR_TSS32_CPL3 0x4c00
-#define ADDR_VAR_TSS32_VM86 0x4e00
-#define ADDR_VAR_VMXON_PTR 0x5f00
-#define ADDR_VAR_VMCS_PTR 0x5f08
-#define ADDR_VAR_VMEXIT_PTR 0x5f10
-#define ADDR_VAR_VMWRITE_FLD 0x5f18
-#define ADDR_VAR_VMWRITE_VAL 0x5f20
-#define ADDR_VAR_VMXON 0x6000
-#define ADDR_VAR_VMCS 0x7000
-#define ADDR_VAR_VMEXIT_CODE 0x9000
-#define ADDR_VAR_USER_CODE 0x9100
-#define ADDR_VAR_USER_CODE2 0x9120
-
-#define SEL_LDT (1 << 3)
-#define SEL_CS16 (2 << 3)
-#define SEL_DS16 (3 << 3)
-#define SEL_CS16_CPL3 ((4 << 3) + 3)
-#define SEL_DS16_CPL3 ((5 << 3) + 3)
-#define SEL_CS32 (6 << 3)
-#define SEL_DS32 (7 << 3)
-#define SEL_CS32_CPL3 ((8 << 3) + 3)
-#define SEL_DS32_CPL3 ((9 << 3) + 3)
-#define SEL_CS64 (10 << 3)
-#define SEL_DS64 (11 << 3)
-#define SEL_CS64_CPL3 ((12 << 3) + 3)
-#define SEL_DS64_CPL3 ((13 << 3) + 3)
-#define SEL_CGATE16 (14 << 3)
-#define SEL_TGATE16 (15 << 3)
-#define SEL_CGATE32 (16 << 3)
-#define SEL_TGATE32 (17 << 3)
-#define SEL_CGATE64 (18 << 3)
-#define SEL_CGATE64_HI (19 << 3)
-#define SEL_TSS16 (20 << 3)
-#define SEL_TSS16_2 (21 << 3)
-#define SEL_TSS16_CPL3 ((22 << 3) + 3)
-#define SEL_TSS32 (23 << 3)
-#define SEL_TSS32_2 (24 << 3)
-#define SEL_TSS32_CPL3 ((25 << 3) + 3)
-#define SEL_TSS32_VM86 (26 << 3)
-#define SEL_TSS64 (27 << 3)
-#define SEL_TSS64_HI (28 << 3)
-#define SEL_TSS64_CPL3 ((29 << 3) + 3)
-#define SEL_TSS64_CPL3_HI (30 << 3)
-
-#define MSR_IA32_FEATURE_CONTROL 0x3a
-#define MSR_IA32_VMX_BASIC 0x480
-#define MSR_IA32_SMBASE 0x9e
-#define MSR_IA32_SYSENTER_CS 0x174
-#define MSR_IA32_SYSENTER_ESP 0x175
-#define MSR_IA32_SYSENTER_EIP 0x176
-#define MSR_IA32_STAR 0xC0000081
-#define MSR_IA32_LSTAR 0xC0000082
-#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B
-
-#define NEXT_INSN $0xbadc0de
-#define PREFIX_SIZE 0xba1d
-const char kvm_asm16_cpl3[] = "\x0f\x20\xc0\x66\x83\xc8\x01\x0f\x22\xc0\xb8\xa0\x00\x0f\x00\xd8\xb8\x2b\x00\x8e\xd8\x8e\xc0\x8e\xe0\x8e\xe8\xbc\x00\x01\xc7\x06\x00\x01\x1d\xba\xc7\x06\x02\x01\x23\x00\xc7\x06\x04\x01\x00\x01\xc7\x06\x06\x01\x2b\x00\xcb";
-const char kvm_asm32_paged[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0";
-const char kvm_asm32_vm86[] = "\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00";
-const char kvm_asm32_paged_vm86[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00";
-const char kvm_asm64_enable_long[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8";
-const char kvm_asm64_init_vm[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8\x48\xc7\xc1\x3a\x00\x00\x00\x0f\x32\x48\x83\xc8\x05\x0f\x30\x0f\x20\xe0\x48\x0d\x00\x20\x00\x00\x0f\x22\xe0\x48\xc7\xc1\x80\x04\x00\x00\x0f\x32\x48\xc7\xc2\x00\x60\x00\x00\x89\x02\x48\xc7\xc2\x00\x70\x00\x00\x89\x02\x48\xc7\xc0\x00\x5f\x00\x00\xf3\x0f\xc7\x30\x48\xc7\xc0\x08\x5f\x00\x00\x66\x0f\xc7\x30\x0f\xc7\x30\x48\xc7\xc1\x81\x04\x00\x00\x0f\x32\x48\x83\xc8\x00\x48\x21\xd0\x48\xc7\xc2\x00\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x82\x04\x00\x00\x0f\x32\x48\x83\xc8\x00\x48\x21\xd0\x48\xc7\xc2\x02\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x40\x00\x00\x48\xc7\xc0\x81\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x83\x04\x00\x00\x0f\x32\x48\x0d\xff\x6f\x03\x00\x48\x21\xd0\x48\xc7\xc2\x0c\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x84\x04\x00\x00\x0f\x32\x48\x0d\xff\x17\x00\x00\x48\x21\xd0\x48\xc7\xc2\x12\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x2c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x28\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x02\x0c\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc0\x58\x00\x00\x00\x48\xc7\xc2\x00\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc0\xd8\x00\x00\x00\x48\xc7\xc2\x0c\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x2c\x00\x00\x48\xc7\xc0\x00\x05\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x4c\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x0f\x20\xc0\x48\xc7\xc2\x00\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xd8\x48\xc7\xc2\x02\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xe0\x48\xc7\xc2\x04\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x48\xc7\xc2\x06\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x6c\x00\x00\x48\xc7\xc0\x00\x3a\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x6c\x00\x00\x48\xc7\xc0\x00\x10\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x6c\x00\x00\x48\xc7\xc0\x00\x38\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x6c\x00\x00\x48\x8b\x04\x25\x10\x5f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x77\x02\x00\x00\x0f\x32\x48\xc1\xe2\x20\x48\x09\xd0\x48\xc7\xc2\x00\x2c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x48\xc7\xc2\x04\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x60\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x02\x60\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x1c\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x22\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x08\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x08\x00\x00\x48\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x08\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x08\x00\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x68\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x68\x00\x00\x48\xc7\xc0\x00\x3a\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x68\x00\x00\x48\xc7\xc0\x00\x10\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x18\x68\x00\x00\x48\xc7\xc0\x00\x38\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x48\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x48\x00\x00\x48\xc7\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x48\x00\x00\x48\xc7\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x48\x00\x00\x48\xc7\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x48\x00\x00\x48\xc7\xc0\x9b\x20\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x18\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1a\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1c\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x48\x00\x00\x48\xc7\xc0\x82\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x22\x48\x00\x00\x48\xc7\xc0\x8b\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1c\x68\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x68\x00\x00\x48\xc7\xc0\x00\x91\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x68\x00\x00\x48\xc7\xc0\x02\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x28\x00\x00\x48\xc7\xc0\x00\x05\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x28\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x0f\x20\xc0\x48\xc7\xc2\x00\x68\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xd8\x48\xc7\xc2\x02\x68\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xe0\x48\xc7\xc2\x04\x68\x00\x00\x48\x89\xc0\x0f\x79\xd0\x48\xc7\xc0\x18\x5f\x00\x00\x48\x8b\x10\x48\xc7\xc0\x20\x5f\x00\x00\x48\x8b\x08\x48\x31\xc0\x0f\x78\xd0\x48\x31\xc8\x0f\x79\xd0\x0f\x01\xc2\x48\xc7\xc2\x00\x44\x00\x00\x0f\x78\xd0\xf4";
-const char kvm_asm64_vm_exit[] = "\x48\xc7\xc3\x00\x44\x00\x00\x0f\x78\xda\x48\xc7\xc3\x02\x44\x00\x00\x0f\x78\xd9\x48\xc7\xc0\x00\x64\x00\x00\x0f\x78\xc0\x48\xc7\xc3\x1e\x68\x00\x00\x0f\x78\xdb\xf4";
-const char kvm_asm64_cpl3[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8\x48\xc7\xc0\x6b\x00\x00\x00\x8e\xd8\x8e\xc0\x8e\xe0\x8e\xe8\x48\xc7\xc4\x80\x0f\x00\x00\x48\xc7\x04\x24\x1d\xba\x00\x00\x48\xc7\x44\x24\x04\x63\x00\x00\x00\x48\xc7\x44\x24\x08\x80\x0f\x00\x00\x48\xc7\x44\x24\x0c\x6b\x00\x00\x00\xcb";
-
-
-#ifndef KVM_SMI
-#define KVM_SMI _IO(KVMIO, 0xb7)
-#endif
-
-#define CR0_PE 1
-#define CR0_MP (1 << 1)
-#define CR0_EM (1 << 2)
-#define CR0_TS (1 << 3)
-#define CR0_ET (1 << 4)
-#define CR0_NE (1 << 5)
-#define CR0_WP (1 << 16)
-#define CR0_AM (1 << 18)
-#define CR0_NW (1 << 29)
-#define CR0_CD (1 << 30)
-#define CR0_PG (1 << 31)
-
-#define CR4_VME 1
-#define CR4_PVI (1 << 1)
-#define CR4_TSD (1 << 2)
-#define CR4_DE (1 << 3)
-#define CR4_PSE (1 << 4)
-#define CR4_PAE (1 << 5)
-#define CR4_MCE (1 << 6)
-#define CR4_PGE (1 << 7)
-#define CR4_PCE (1 << 8)
-#define CR4_OSFXSR (1 << 8)
-#define CR4_OSXMMEXCPT (1 << 10)
-#define CR4_UMIP (1 << 11)
-#define CR4_VMXE (1 << 13)
-#define CR4_SMXE (1 << 14)
-#define CR4_FSGSBASE (1 << 16)
-#define CR4_PCIDE (1 << 17)
-#define CR4_OSXSAVE (1 << 18)
-#define CR4_SMEP (1 << 20)
-#define CR4_SMAP (1 << 21)
-#define CR4_PKE (1 << 22)
-
-#define EFER_SCE 1
-#define EFER_LME (1 << 8)
-#define EFER_LMA (1 << 10)
-#define EFER_NXE (1 << 11)
-#define EFER_SVME (1 << 12)
-#define EFER_LMSLE (1 << 13)
-#define EFER_FFXSR (1 << 14)
-#define EFER_TCE (1 << 15)
-#define PDE32_PRESENT 1
-#define PDE32_RW (1 << 1)
-#define PDE32_USER (1 << 2)
-#define PDE32_PS (1 << 7)
-#define PDE64_PRESENT 1
-#define PDE64_RW (1 << 1)
-#define PDE64_USER (1 << 2)
-#define PDE64_ACCESSED (1 << 5)
-#define PDE64_DIRTY (1 << 6)
-#define PDE64_PS (1 << 7)
-#define PDE64_G (1 << 8)
-
-struct tss16 {
- uint16 prev;
- uint16 sp0;
- uint16 ss0;
- uint16 sp1;
- uint16 ss1;
- uint16 sp2;
- uint16 ss2;
- uint16 ip;
- uint16 flags;
- uint16 ax;
- uint16 cx;
- uint16 dx;
- uint16 bx;
- uint16 sp;
- uint16 bp;
- uint16 si;
- uint16 di;
- uint16 es;
- uint16 cs;
- uint16 ss;
- uint16 ds;
- uint16 ldt;
-} __attribute__((packed));
-
-struct tss32 {
- uint16 prev, prevh;
- uint32 sp0;
- uint16 ss0, ss0h;
- uint32 sp1;
- uint16 ss1, ss1h;
- uint32 sp2;
- uint16 ss2, ss2h;
- uint32 cr3;
- uint32 ip;
- uint32 flags;
- uint32 ax;
- uint32 cx;
- uint32 dx;
- uint32 bx;
- uint32 sp;
- uint32 bp;
- uint32 si;
- uint32 di;
- uint16 es, esh;
- uint16 cs, csh;
- uint16 ss, ssh;
- uint16 ds, dsh;
- uint16 fs, fsh;
- uint16 gs, gsh;
- uint16 ldt, ldth;
- uint16 trace;
- uint16 io_bitmap;
-} __attribute__((packed));
-
-struct tss64 {
- uint32 reserved0;
- uint64 rsp[3];
- uint64 reserved1;
- uint64 ist[7];
- uint64 reserved2;
- uint32 reserved3;
- uint32 io_bitmap;
-} __attribute__((packed));
-
-static void fill_segment_descriptor(uint64* dt, uint64* lt, struct kvm_segment* seg)
-{
- uint16 index = seg->selector >> 3;
- uint64 limit = seg->g ? seg->limit >> 12 : seg->limit;
- uint64 sd = (limit & 0xffff) | (seg->base & 0xffffff) << 16 | (uint64)seg->type << 40 | (uint64)seg->s << 44 | (uint64)seg->dpl << 45 | (uint64)seg->present << 47 | (limit & 0xf0000ULL) << 48 | (uint64)seg->avl << 52 | (uint64)seg->l << 53 | (uint64)seg->db << 54 | (uint64)seg->g << 55 | (seg->base & 0xff000000ULL) << 56;
- dt[index] = sd;
- lt[index] = sd;
-}
-
-static void fill_segment_descriptor_dword(uint64* dt, uint64* lt, struct kvm_segment* seg)
-{
- fill_segment_descriptor(dt, lt, seg);
- uint16 index = seg->selector >> 3;
- dt[index + 1] = 0;
- lt[index + 1] = 0;
-}
-
-static void setup_syscall_msrs(int cpufd, uint16 sel_cs, uint16 sel_cs_cpl3)
-{
- char buf[sizeof(struct kvm_msrs) + 5 * sizeof(struct kvm_msr_entry)];
- memset(buf, 0, sizeof(buf));
- struct kvm_msrs* msrs = (struct kvm_msrs*)buf;
- struct kvm_msr_entry* entries = msrs->entries;
- msrs->nmsrs = 5;
- entries[0].index = MSR_IA32_SYSENTER_CS;
- entries[0].data = sel_cs;
- entries[1].index = MSR_IA32_SYSENTER_ESP;
- entries[1].data = ADDR_STACK0;
- entries[2].index = MSR_IA32_SYSENTER_EIP;
- entries[2].data = ADDR_VAR_SYSEXIT;
- entries[3].index = MSR_IA32_STAR;
- entries[3].data = ((uint64)sel_cs << 32) | ((uint64)sel_cs_cpl3 << 48);
- entries[4].index = MSR_IA32_LSTAR;
- entries[4].data = ADDR_VAR_SYSRET;
- ioctl(cpufd, KVM_SET_MSRS, msrs);
-}
-
-static void setup_32bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t guest_mem)
-{
- sregs->idt.base = guest_mem + ADDR_VAR_IDT;
- sregs->idt.limit = 0x1ff;
- uint64* idt = (uint64*)(host_mem + sregs->idt.base);
- for (int i = 0; i < 32; i++) {
- struct kvm_segment gate;
- gate.selector = i << 3;
- switch (i % 6) {
- case 0:
- gate.type = 6;
- gate.base = SEL_CS16;
- break;
- case 1:
- gate.type = 7;
- gate.base = SEL_CS16;
- break;
- case 2:
- gate.type = 3;
- gate.base = SEL_TGATE16;
- break;
- case 3:
- gate.type = 14;
- gate.base = SEL_CS32;
- break;
- case 4:
- gate.type = 15;
- gate.base = SEL_CS32;
- break;
- case 5:
- gate.type = 11;
- gate.base = SEL_TGATE32;
- break;
- }
- gate.limit = guest_mem + ADDR_VAR_USER_CODE2;
- gate.present = 1;
- gate.dpl = 0;
- gate.s = 0;
- gate.g = 0;
- gate.db = 0;
- gate.l = 0;
- gate.avl = 0;
- fill_segment_descriptor(idt, idt, &gate);
- }
-}
-
-static void setup_64bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t guest_mem)
-{
- sregs->idt.base = guest_mem + ADDR_VAR_IDT;
- sregs->idt.limit = 0x1ff;
- uint64* idt = (uint64*)(host_mem + sregs->idt.base);
- for (int i = 0; i < 32; i++) {
- struct kvm_segment gate;
- gate.selector = (i * 2) << 3;
- gate.type = (i & 1) ? 14 : 15;
- gate.base = SEL_CS64;
- gate.limit = guest_mem + ADDR_VAR_USER_CODE2;
- gate.present = 1;
- gate.dpl = 0;
- gate.s = 0;
- gate.g = 0;
- gate.db = 0;
- gate.l = 0;
- gate.avl = 0;
- fill_segment_descriptor_dword(idt, idt, &gate);
- }
-}
-
-struct kvm_text {
- uintptr_t typ;
- const void* text;
- uintptr_t size;
-};
-
-struct kvm_opt {
- uint64 typ;
- uint64 val;
-};
-
-#define KVM_SETUP_PAGING (1 << 0)
-#define KVM_SETUP_PAE (1 << 1)
-#define KVM_SETUP_PROTECTED (1 << 2)
-#define KVM_SETUP_CPL3 (1 << 3)
-#define KVM_SETUP_VIRT86 (1 << 4)
-#define KVM_SETUP_SMM (1 << 5)
-#define KVM_SETUP_VM (1 << 6)
-static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7)
-{
- const int vmfd = a0;
- const int cpufd = a1;
- char* const host_mem = (char*)a2;
- const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3;
- const uintptr_t text_count = a4;
- const uintptr_t flags = a5;
- const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6;
- uintptr_t opt_count = a7;
-
- const uintptr_t page_size = 4 << 10;
- const uintptr_t ioapic_page = 10;
- const uintptr_t guest_mem_size = 24 * page_size;
- const uintptr_t guest_mem = 0;
-
- (void)text_count;
- int text_type = text_array_ptr[0].typ;
- const void* text = text_array_ptr[0].text;
- uintptr_t text_size = text_array_ptr[0].size;
-
- for (uintptr_t i = 0; i < guest_mem_size / page_size; i++) {
- struct kvm_userspace_memory_region memreg;
- memreg.slot = i;
- memreg.flags = 0;
- memreg.guest_phys_addr = guest_mem + i * page_size;
- if (i == ioapic_page)
- memreg.guest_phys_addr = 0xfec00000;
- memreg.memory_size = page_size;
- memreg.userspace_addr = (uintptr_t)host_mem + i * page_size;
- ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
- }
- struct kvm_userspace_memory_region memreg;
- memreg.slot = 1 + (1 << 16);
- memreg.flags = 0;
- memreg.guest_phys_addr = 0x30000;
- memreg.memory_size = 64 << 10;
- memreg.userspace_addr = (uintptr_t)host_mem;
- ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
-
- struct kvm_sregs sregs;
- if (ioctl(cpufd, KVM_GET_SREGS, &sregs))
- return -1;
-
- struct kvm_regs regs;
- memset(&regs, 0, sizeof(regs));
- regs.rip = guest_mem + ADDR_TEXT;
- regs.rsp = ADDR_STACK0;
-
- sregs.gdt.base = guest_mem + ADDR_GDT;
- sregs.gdt.limit = 256 * sizeof(uint64) - 1;
- uint64* gdt = (uint64*)(host_mem + sregs.gdt.base);
-
- struct kvm_segment seg_ldt;
- memset(&seg_ldt, 0, sizeof(seg_ldt));
- seg_ldt.selector = SEL_LDT;
- seg_ldt.type = 2;
- seg_ldt.base = guest_mem + ADDR_LDT;
- seg_ldt.limit = 256 * sizeof(uint64) - 1;
- seg_ldt.present = 1;
- seg_ldt.dpl = 0;
- seg_ldt.s = 0;
- seg_ldt.g = 0;
- seg_ldt.db = 1;
- seg_ldt.l = 0;
- sregs.ldt = seg_ldt;
- uint64* ldt = (uint64*)(host_mem + sregs.ldt.base);
-
- struct kvm_segment seg_cs16;
- memset(&seg_cs16, 0, sizeof(seg_cs16));
- seg_cs16.selector = SEL_CS16;
- seg_cs16.type = 11;
- seg_cs16.base = 0;
- seg_cs16.limit = 0xfffff;
- seg_cs16.present = 1;
- seg_cs16.dpl = 0;
- seg_cs16.s = 1;
- seg_cs16.g = 0;
- seg_cs16.db = 0;
- seg_cs16.l = 0;
-
- struct kvm_segment seg_ds16 = seg_cs16;
- seg_ds16.selector = SEL_DS16;
- seg_ds16.type = 3;
-
- struct kvm_segment seg_cs16_cpl3 = seg_cs16;
- seg_cs16_cpl3.selector = SEL_CS16_CPL3;
- seg_cs16_cpl3.dpl = 3;
-
- struct kvm_segment seg_ds16_cpl3 = seg_ds16;
- seg_ds16_cpl3.selector = SEL_DS16_CPL3;
- seg_ds16_cpl3.dpl = 3;
-
- struct kvm_segment seg_cs32 = seg_cs16;
- seg_cs32.selector = SEL_CS32;
- seg_cs32.db = 1;
-
- struct kvm_segment seg_ds32 = seg_ds16;
- seg_ds32.selector = SEL_DS32;
- seg_ds32.db = 1;
-
- struct kvm_segment seg_cs32_cpl3 = seg_cs32;
- seg_cs32_cpl3.selector = SEL_CS32_CPL3;
- seg_cs32_cpl3.dpl = 3;
-
- struct kvm_segment seg_ds32_cpl3 = seg_ds32;
- seg_ds32_cpl3.selector = SEL_DS32_CPL3;
- seg_ds32_cpl3.dpl = 3;
-
- struct kvm_segment seg_cs64 = seg_cs16;
- seg_cs64.selector = SEL_CS64;
- seg_cs64.l = 1;
-
- struct kvm_segment seg_ds64 = seg_ds32;
- seg_ds64.selector = SEL_DS64;
-
- struct kvm_segment seg_cs64_cpl3 = seg_cs64;
- seg_cs64_cpl3.selector = SEL_CS64_CPL3;
- seg_cs64_cpl3.dpl = 3;
-
- struct kvm_segment seg_ds64_cpl3 = seg_ds64;
- seg_ds64_cpl3.selector = SEL_DS64_CPL3;
- seg_ds64_cpl3.dpl = 3;
-
- struct kvm_segment seg_tss32;
- memset(&seg_tss32, 0, sizeof(seg_tss32));
- seg_tss32.selector = SEL_TSS32;
- seg_tss32.type = 9;
- seg_tss32.base = ADDR_VAR_TSS32;
- seg_tss32.limit = 0x1ff;
- seg_tss32.present = 1;
- seg_tss32.dpl = 0;
- seg_tss32.s = 0;
- seg_tss32.g = 0;
- seg_tss32.db = 0;
- seg_tss32.l = 0;
-
- struct kvm_segment seg_tss32_2 = seg_tss32;
- seg_tss32_2.selector = SEL_TSS32_2;
- seg_tss32_2.base = ADDR_VAR_TSS32_2;
-
- struct kvm_segment seg_tss32_cpl3 = seg_tss32;
- seg_tss32_cpl3.selector = SEL_TSS32_CPL3;
- seg_tss32_cpl3.base = ADDR_VAR_TSS32_CPL3;
-
- struct kvm_segment seg_tss32_vm86 = seg_tss32;
- seg_tss32_vm86.selector = SEL_TSS32_VM86;
- seg_tss32_vm86.base = ADDR_VAR_TSS32_VM86;
-
- struct kvm_segment seg_tss16 = seg_tss32;
- seg_tss16.selector = SEL_TSS16;
- seg_tss16.base = ADDR_VAR_TSS16;
- seg_tss16.limit = 0xff;
- seg_tss16.type = 1;
-
- struct kvm_segment seg_tss16_2 = seg_tss16;
- seg_tss16_2.selector = SEL_TSS16_2;
- seg_tss16_2.base = ADDR_VAR_TSS16_2;
- seg_tss16_2.dpl = 0;
-
- struct kvm_segment seg_tss16_cpl3 = seg_tss16;
- seg_tss16_cpl3.selector = SEL_TSS16_CPL3;
- seg_tss16_cpl3.base = ADDR_VAR_TSS16_CPL3;
- seg_tss16_cpl3.dpl = 3;
-
- struct kvm_segment seg_tss64 = seg_tss32;
- seg_tss64.selector = SEL_TSS64;
- seg_tss64.base = ADDR_VAR_TSS64;
- seg_tss64.limit = 0x1ff;
-
- struct kvm_segment seg_tss64_cpl3 = seg_tss64;
- seg_tss64_cpl3.selector = SEL_TSS64_CPL3;
- seg_tss64_cpl3.base = ADDR_VAR_TSS64_CPL3;
- seg_tss64_cpl3.dpl = 3;
-
- struct kvm_segment seg_cgate16;
- memset(&seg_cgate16, 0, sizeof(seg_cgate16));
- seg_cgate16.selector = SEL_CGATE16;
- seg_cgate16.type = 4;
- seg_cgate16.base = SEL_CS16 | (2 << 16);
- seg_cgate16.limit = ADDR_VAR_USER_CODE2;
- seg_cgate16.present = 1;
- seg_cgate16.dpl = 0;
- seg_cgate16.s = 0;
- seg_cgate16.g = 0;
- seg_cgate16.db = 0;
- seg_cgate16.l = 0;
- seg_cgate16.avl = 0;
-
- struct kvm_segment seg_tgate16 = seg_cgate16;
- seg_tgate16.selector = SEL_TGATE16;
- seg_tgate16.type = 3;
- seg_cgate16.base = SEL_TSS16_2;
- seg_tgate16.limit = 0;
-
- struct kvm_segment seg_cgate32 = seg_cgate16;
- seg_cgate32.selector = SEL_CGATE32;
- seg_cgate32.type = 12;
- seg_cgate32.base = SEL_CS32 | (2 << 16);
-
- struct kvm_segment seg_tgate32 = seg_cgate32;
- seg_tgate32.selector = SEL_TGATE32;
- seg_tgate32.type = 11;
- seg_tgate32.base = SEL_TSS32_2;
- seg_tgate32.limit = 0;
-
- struct kvm_segment seg_cgate64 = seg_cgate16;
- seg_cgate64.selector = SEL_CGATE64;
- seg_cgate64.type = 12;
- seg_cgate64.base = SEL_CS64;
-
- int kvmfd = open("/dev/kvm", O_RDWR);
- char buf[sizeof(struct kvm_cpuid2) + 128 * sizeof(struct kvm_cpuid_entry2)];
- memset(buf, 0, sizeof(buf));
- struct kvm_cpuid2* cpuid = (struct kvm_cpuid2*)buf;
- cpuid->nent = 128;
- ioctl(kvmfd, KVM_GET_SUPPORTED_CPUID, cpuid);
- ioctl(cpufd, KVM_SET_CPUID2, cpuid);
- close(kvmfd);
-
- const char* text_prefix = 0;
- int text_prefix_size = 0;
- char* host_text = host_mem + ADDR_TEXT;
-
- if (text_type == 8) {
- if (flags & KVM_SETUP_SMM) {
- if (flags & KVM_SETUP_PROTECTED) {
- sregs.cs = seg_cs16;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16;
- sregs.cr0 |= CR0_PE;
- } else {
- sregs.cs.selector = 0;
- sregs.cs.base = 0;
- }
-
- *(host_mem + ADDR_TEXT) = 0xf4;
- host_text = host_mem + 0x8000;
-
- ioctl(cpufd, KVM_SMI, 0);
- } else if (flags & KVM_SETUP_VIRT86) {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
- sregs.cr0 |= CR0_PE;
- sregs.efer |= EFER_SCE;
-
- setup_syscall_msrs(cpufd, SEL_CS32, SEL_CS32_CPL3);
- setup_32bit_idt(&sregs, host_mem, guest_mem);
-
- if (flags & KVM_SETUP_PAGING) {
- uint64 pd_addr = guest_mem + ADDR_PD;
- uint64* pd = (uint64*)(host_mem + ADDR_PD);
- pd[0] = PDE32_PRESENT | PDE32_RW | PDE32_USER | PDE32_PS;
- sregs.cr3 = pd_addr;
- sregs.cr4 |= CR4_PSE;
-
- text_prefix = kvm_asm32_paged_vm86;
- text_prefix_size = sizeof(kvm_asm32_paged_vm86) - 1;
- } else {
- text_prefix = kvm_asm32_vm86;
- text_prefix_size = sizeof(kvm_asm32_vm86) - 1;
- }
- } else {
- sregs.cs.selector = 0;
- sregs.cs.base = 0;
- }
- } else if (text_type == 16) {
- if (flags & KVM_SETUP_CPL3) {
- sregs.cs = seg_cs16;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16;
-
- text_prefix = kvm_asm16_cpl3;
- text_prefix_size = sizeof(kvm_asm16_cpl3) - 1;
- } else {
- sregs.cr0 |= CR0_PE;
- sregs.cs = seg_cs16;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16;
- }
- } else if (text_type == 32) {
- sregs.cr0 |= CR0_PE;
- sregs.efer |= EFER_SCE;
-
- setup_syscall_msrs(cpufd, SEL_CS32, SEL_CS32_CPL3);
- setup_32bit_idt(&sregs, host_mem, guest_mem);
-
- if (flags & KVM_SETUP_SMM) {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
-
- *(host_mem + ADDR_TEXT) = 0xf4;
- host_text = host_mem + 0x8000;
-
- ioctl(cpufd, KVM_SMI, 0);
- } else if (flags & KVM_SETUP_PAGING) {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
-
- uint64 pd_addr = guest_mem + ADDR_PD;
- uint64* pd = (uint64*)(host_mem + ADDR_PD);
- pd[0] = PDE32_PRESENT | PDE32_RW | PDE32_USER | PDE32_PS;
- sregs.cr3 = pd_addr;
- sregs.cr4 |= CR4_PSE;
-
- text_prefix = kvm_asm32_paged;
- text_prefix_size = sizeof(kvm_asm32_paged) - 1;
- } else if (flags & KVM_SETUP_CPL3) {
- sregs.cs = seg_cs32_cpl3;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32_cpl3;
- } else {
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
- }
- } else {
- sregs.efer |= EFER_LME | EFER_SCE;
- sregs.cr0 |= CR0_PE;
-
- setup_syscall_msrs(cpufd, SEL_CS64, SEL_CS64_CPL3);
- setup_64bit_idt(&sregs, host_mem, guest_mem);
-
- sregs.cs = seg_cs32;
- sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32;
-
- uint64 pml4_addr = guest_mem + ADDR_PML4;
- uint64* pml4 = (uint64*)(host_mem + ADDR_PML4);
- uint64 pdpt_addr = guest_mem + ADDR_PDP;
- uint64* pdpt = (uint64*)(host_mem + ADDR_PDP);
- uint64 pd_addr = guest_mem + ADDR_PD;
- uint64* pd = (uint64*)(host_mem + ADDR_PD);
- pml4[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | pdpt_addr;
- pdpt[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | pd_addr;
- pd[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | PDE64_PS;
- sregs.cr3 = pml4_addr;
- sregs.cr4 |= CR4_PAE;
-
- if (flags & KVM_SETUP_VM) {
- sregs.cr0 |= CR0_NE;
-
- *((uint64*)(host_mem + ADDR_VAR_VMXON_PTR)) = ADDR_VAR_VMXON;
- *((uint64*)(host_mem + ADDR_VAR_VMCS_PTR)) = ADDR_VAR_VMCS;
- memcpy(host_mem + ADDR_VAR_VMEXIT_CODE, kvm_asm64_vm_exit, sizeof(kvm_asm64_vm_exit) - 1);
- *((uint64*)(host_mem + ADDR_VAR_VMEXIT_PTR)) = ADDR_VAR_VMEXIT_CODE;
-
- text_prefix = kvm_asm64_init_vm;
- text_prefix_size = sizeof(kvm_asm64_init_vm) - 1;
- } else if (flags & KVM_SETUP_CPL3) {
- text_prefix = kvm_asm64_cpl3;
- text_prefix_size = sizeof(kvm_asm64_cpl3) - 1;
- } else {
- text_prefix = kvm_asm64_enable_long;
- text_prefix_size = sizeof(kvm_asm64_enable_long) - 1;
- }
- }
-
- struct tss16 tss16;
- memset(&tss16, 0, sizeof(tss16));
- tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16;
- tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0;
- tss16.ip = ADDR_VAR_USER_CODE2;
- tss16.flags = (1 << 1);
- tss16.cs = SEL_CS16;
- tss16.es = tss16.ds = tss16.ss = SEL_DS16;
- tss16.ldt = SEL_LDT;
- struct tss16* tss16_addr = (struct tss16*)(host_mem + seg_tss16_2.base);
- memcpy(tss16_addr, &tss16, sizeof(tss16));
-
- memset(&tss16, 0, sizeof(tss16));
- tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16;
- tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0;
- tss16.ip = ADDR_VAR_USER_CODE2;
- tss16.flags = (1 << 1);
- tss16.cs = SEL_CS16_CPL3;
- tss16.es = tss16.ds = tss16.ss = SEL_DS16_CPL3;
- tss16.ldt = SEL_LDT;
- struct tss16* tss16_cpl3_addr = (struct tss16*)(host_mem + seg_tss16_cpl3.base);
- memcpy(tss16_cpl3_addr, &tss16, sizeof(tss16));
-
- struct tss32 tss32;
- memset(&tss32, 0, sizeof(tss32));
- tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32;
- tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0;
- tss32.ip = ADDR_VAR_USER_CODE;
- tss32.flags = (1 << 1) | (1 << 17);
- tss32.ldt = SEL_LDT;
- tss32.cr3 = sregs.cr3;
- tss32.io_bitmap = offsetof(struct tss32, io_bitmap);
- struct tss32* tss32_addr = (struct tss32*)(host_mem + seg_tss32_vm86.base);
- memcpy(tss32_addr, &tss32, sizeof(tss32));
-
- memset(&tss32, 0, sizeof(tss32));
- tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32;
- tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0;
- tss32.ip = ADDR_VAR_USER_CODE;
- tss32.flags = (1 << 1);
- tss32.cr3 = sregs.cr3;
- tss32.es = tss32.ds = tss32.ss = tss32.gs = tss32.fs = SEL_DS32;
- tss32.cs = SEL_CS32;
- tss32.ldt = SEL_LDT;
- tss32.cr3 = sregs.cr3;
- tss32.io_bitmap = offsetof(struct tss32, io_bitmap);
- struct tss32* tss32_cpl3_addr = (struct tss32*)(host_mem + seg_tss32_2.base);
- memcpy(tss32_cpl3_addr, &tss32, sizeof(tss32));
-
- struct tss64 tss64;
- memset(&tss64, 0, sizeof(tss64));
- tss64.rsp[0] = ADDR_STACK0;
- tss64.rsp[1] = ADDR_STACK0;
- tss64.rsp[2] = ADDR_STACK0;
- tss64.io_bitmap = offsetof(struct tss64, io_bitmap);
- struct tss64* tss64_addr = (struct tss64*)(host_mem + seg_tss64.base);
- memcpy(tss64_addr, &tss64, sizeof(tss64));
-
- memset(&tss64, 0, sizeof(tss64));
- tss64.rsp[0] = ADDR_STACK0;
- tss64.rsp[1] = ADDR_STACK0;
- tss64.rsp[2] = ADDR_STACK0;
- tss64.io_bitmap = offsetof(struct tss64, io_bitmap);
- struct tss64* tss64_cpl3_addr = (struct tss64*)(host_mem + seg_tss64_cpl3.base);
- memcpy(tss64_cpl3_addr, &tss64, sizeof(tss64));
-
- if (text_size > 1000)
- text_size = 1000;
- if (text_prefix) {
- memcpy(host_text, text_prefix, text_prefix_size);
- void* patch = memmem(host_text, text_prefix_size, "\xde\xc0\xad\x0b", 4);
- if (patch)
- *((uint32*)patch) = guest_mem + ADDR_TEXT + ((char*)patch - host_text) + 6;
- uint16 magic = PREFIX_SIZE;
- patch = memmem(host_text, text_prefix_size, &magic, sizeof(magic));
- if (patch)
- *((uint16*)patch) = guest_mem + ADDR_TEXT + text_prefix_size;
- }
- memcpy((void*)(host_text + text_prefix_size), text, text_size);
- *(host_text + text_prefix_size + text_size) = 0xf4;
-
- memcpy(host_mem + ADDR_VAR_USER_CODE, text, text_size);
- *(host_mem + ADDR_VAR_USER_CODE + text_size) = 0xf4;
-
- *(host_mem + ADDR_VAR_HLT) = 0xf4;
- memcpy(host_mem + ADDR_VAR_SYSRET, "\x0f\x07\xf4", 3);
- memcpy(host_mem + ADDR_VAR_SYSEXIT, "\x0f\x35\xf4", 3);
-
- *(uint64*)(host_mem + ADDR_VAR_VMWRITE_FLD) = 0;
- *(uint64*)(host_mem + ADDR_VAR_VMWRITE_VAL) = 0;
-
- if (opt_count > 2)
- opt_count = 2;
- for (uintptr_t i = 0; i < opt_count; i++) {
- uint64 typ = opt_array_ptr[i].typ;
- uint64 val = opt_array_ptr[i].val;
- switch (typ % 9) {
- case 0:
- sregs.cr0 ^= val & (CR0_MP | CR0_EM | CR0_ET | CR0_NE | CR0_WP | CR0_AM | CR0_NW | CR0_CD);
- break;
- case 1:
- sregs.cr4 ^= val & (CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PGE | CR4_PCE |
- CR4_OSFXSR | CR4_OSXMMEXCPT | CR4_UMIP | CR4_VMXE | CR4_SMXE | CR4_FSGSBASE | CR4_PCIDE |
- CR4_OSXSAVE | CR4_SMEP | CR4_SMAP | CR4_PKE);
- break;
- case 2:
- sregs.efer ^= val & (EFER_SCE | EFER_NXE | EFER_SVME | EFER_LMSLE | EFER_FFXSR | EFER_TCE);
- break;
- case 3:
- val &= ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13) | (1 << 14) |
- (1 << 15) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21));
- regs.rflags ^= val;
- tss16_addr->flags ^= val;
- tss16_cpl3_addr->flags ^= val;
- tss32_addr->flags ^= val;
- tss32_cpl3_addr->flags ^= val;
- break;
- case 4:
- seg_cs16.type = val & 0xf;
- seg_cs32.type = val & 0xf;
- seg_cs64.type = val & 0xf;
- break;
- case 5:
- seg_cs16_cpl3.type = val & 0xf;
- seg_cs32_cpl3.type = val & 0xf;
- seg_cs64_cpl3.type = val & 0xf;
- break;
- case 6:
- seg_ds16.type = val & 0xf;
- seg_ds32.type = val & 0xf;
- seg_ds64.type = val & 0xf;
- break;
- case 7:
- seg_ds16_cpl3.type = val & 0xf;
- seg_ds32_cpl3.type = val & 0xf;
- seg_ds64_cpl3.type = val & 0xf;
- break;
- case 8:
- *(uint64*)(host_mem + ADDR_VAR_VMWRITE_FLD) = (val & 0xffff);
- *(uint64*)(host_mem + ADDR_VAR_VMWRITE_VAL) = (val >> 16);
- break;
- default:
- fail("bad kvm setup opt");
- }
- }
- regs.rflags |= 2;
-
- fill_segment_descriptor(gdt, ldt, &seg_ldt);
- fill_segment_descriptor(gdt, ldt, &seg_cs16);
- fill_segment_descriptor(gdt, ldt, &seg_ds16);
- fill_segment_descriptor(gdt, ldt, &seg_cs16_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_ds16_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_cs32);
- fill_segment_descriptor(gdt, ldt, &seg_ds32);
- fill_segment_descriptor(gdt, ldt, &seg_cs32_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_ds32_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_cs64);
- fill_segment_descriptor(gdt, ldt, &seg_ds64);
- fill_segment_descriptor(gdt, ldt, &seg_cs64_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_ds64_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_tss32);
- fill_segment_descriptor(gdt, ldt, &seg_tss32_2);
- fill_segment_descriptor(gdt, ldt, &seg_tss32_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_tss32_vm86);
- fill_segment_descriptor(gdt, ldt, &seg_tss16);
- fill_segment_descriptor(gdt, ldt, &seg_tss16_2);
- fill_segment_descriptor(gdt, ldt, &seg_tss16_cpl3);
- fill_segment_descriptor_dword(gdt, ldt, &seg_tss64);
- fill_segment_descriptor_dword(gdt, ldt, &seg_tss64_cpl3);
- fill_segment_descriptor(gdt, ldt, &seg_cgate16);
- fill_segment_descriptor(gdt, ldt, &seg_tgate16);
- fill_segment_descriptor(gdt, ldt, &seg_cgate32);
- fill_segment_descriptor(gdt, ldt, &seg_tgate32);
- fill_segment_descriptor_dword(gdt, ldt, &seg_cgate64);
-
- if (ioctl(cpufd, KVM_SET_SREGS, &sregs))
- return -1;
- if (ioctl(cpufd, KVM_SET_REGS, &regs))
- return -1;
- return 0;
-}
-
-#elif GOARCH_arm64
-
-struct kvm_text {
- uintptr_t typ;
- const void* text;
- uintptr_t size;
-};
-
-struct kvm_opt {
- uint64 typ;
- uint64 val;
-};
-static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7)
-{
- const int vmfd = a0;
- const int cpufd = a1;
- char* const host_mem = (char*)a2;
- const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3;
- const uintptr_t text_count = a4;
- const uintptr_t flags = a5;
- const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6;
- uintptr_t opt_count = a7;
-
- (void)flags;
- (void)opt_count;
-
- const uintptr_t page_size = 4 << 10;
- const uintptr_t guest_mem = 0;
- const uintptr_t guest_mem_size = 24 * page_size;
-
- (void)text_count;
- int text_type = text_array_ptr[0].typ;
- const void* text = text_array_ptr[0].text;
- int text_size = text_array_ptr[0].size;
- (void)text_type;
- (void)opt_array_ptr;
-
- uint32 features = 0;
- if (opt_count > 1)
- opt_count = 1;
- for (uintptr_t i = 0; i < opt_count; i++) {
- uint64 typ = opt_array_ptr[i].typ;
- uint64 val = opt_array_ptr[i].val;
- switch (typ) {
- case 1:
- features = val;
- break;
- }
- }
-
- for (uintptr_t i = 0; i < guest_mem_size / page_size; i++) {
- struct kvm_userspace_memory_region memreg;
- memreg.slot = i;
- memreg.flags = 0;
- memreg.guest_phys_addr = guest_mem + i * page_size;
- memreg.memory_size = page_size;
- memreg.userspace_addr = (uintptr_t)host_mem + i * page_size;
- ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
- }
-
- struct kvm_vcpu_init init;
- ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &init);
- init.features[0] = features;
- ioctl(cpufd, KVM_ARM_VCPU_INIT, &init);
-
- if (text_size > 1000)
- text_size = 1000;
- memcpy(host_mem, text, text_size);
-
- return 0;
-}
-
-#elif GOARCH_ppc64 || GOARCH_ppc64le
-const char kvm_ppc64_mr[] = "\x00\x00\xa0\x3c\x00\x00\xa5\x60\xc6\x07\xa5\x78\xad\x0b\xa5\x64\xde\xc0\xa5\x60\x78\x2b\xa4\x7c\x78\x23\x83\x7c";
-const char kvm_ppc64_ld[] = "\x00\x00\xe0\x3d\x00\x00\xef\x61\xc6\x07\xef\x79\xad\x0b\xef\x65\xde\xc0\xef\x61\x00\x00\x20\x3f\x00\x00\x39\x63\xc6\x07\x39\x7b\x17\x00\x39\x67\xf8\xff\x39\x63\x00\x00\xf9\xf9\x00\x00\x79\xe8";
-const char kvm_ppc64_recharge_dec[] = "\x00\x00\x80\x3e\x00\x00\x94\x62\xc6\x07\x94\x7a\xff\x07\x94\x66\xff\xff\x94\x62\xa6\x03\x96\x7e\x24\x00\x00\x4c";
-
-
-#define BOOK3S_INTERRUPT_SYSTEM_RESET 0x100
-#define BOOK3S_INTERRUPT_MACHINE_CHECK 0x200
-#define BOOK3S_INTERRUPT_DATA_STORAGE 0x300
-#define BOOK3S_INTERRUPT_DATA_SEGMENT 0x380
-#define BOOK3S_INTERRUPT_INST_STORAGE 0x400
-#define BOOK3S_INTERRUPT_INST_SEGMENT 0x480
-#define BOOK3S_INTERRUPT_EXTERNAL 0x500
-#define BOOK3S_INTERRUPT_EXTERNAL_HV 0x502
-#define BOOK3S_INTERRUPT_ALIGNMENT 0x600
-#define BOOK3S_INTERRUPT_PROGRAM 0x700
-#define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800
-#define BOOK3S_INTERRUPT_DECREMENTER 0x900
-#define BOOK3S_INTERRUPT_HV_DECREMENTER 0x980
-#define BOOK3S_INTERRUPT_DOORBELL 0xa00
-#define BOOK3S_INTERRUPT_SYSCALL 0xc00
-#define BOOK3S_INTERRUPT_TRACE 0xd00
-#define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00
-#define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20
-#define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40
-#define BOOK3S_INTERRUPT_HMI 0xe60
-#define BOOK3S_INTERRUPT_H_DOORBELL 0xe80
-#define BOOK3S_INTERRUPT_H_VIRT 0xea0
-#define BOOK3S_INTERRUPT_PERFMON 0xf00
-#define BOOK3S_INTERRUPT_ALTIVEC 0xf20
-#define BOOK3S_INTERRUPT_VSX 0xf40
-#define BOOK3S_INTERRUPT_FAC_UNAVAIL 0xf60
-#define BOOK3S_INTERRUPT_H_FAC_UNAVAIL 0xf80
-
-#define BITS_PER_LONG 64
-#define PPC_BITLSHIFT(be) (BITS_PER_LONG - 1 - (be))
-#define PPC_BIT(bit) (1ULL << PPC_BITLSHIFT(bit))
-#define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
-
-#define RADIX_PTE_INDEX_SIZE 5
-#define RADIX_PMD_INDEX_SIZE 9
-#define RADIX_PUD_INDEX_SIZE 9
-#define RADIX_PGD_INDEX_SIZE 13
-
-#define cpu_to_be32(x) __builtin_bswap32(x)
-#define cpu_to_be64(x) __builtin_bswap64(x)
-#define be64_to_cpu(x) __builtin_bswap64(x)
-
-#define LPCR_ILE PPC_BIT(38)
-#define LPCR_UPRT PPC_BIT(41)
-#define LPCR_EVIRT PPC_BIT(42)
-#define LPCR_HR PPC_BIT(43)
-#ifndef KVM_REG_PPC_LPCR_64
-#define KVM_REG_PPC_LPCR_64 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5)
-#endif
-
-#define PRTB_SIZE_SHIFT 12
-#define PATB_GR (1UL << 63)
-#define PATB_HR (1UL << 63)
-#define PRTB_MASK 0x0ffffffffffff000UL
-
-#define ALIGNUP(p, q) ((void*)(((unsigned long)(p) + (q)-1) & ~((q)-1)))
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-
-#ifndef KVM_REG_PPC_DEC_EXPIRY
-#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
-#endif
-
-#ifndef KVM_PPC_CONFIGURE_V3_MMU
-#define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg)
-struct kvm_ppc_mmuv3_cfg {
- __u64 flags;
- __u64 process_table;
-};
-#define KVM_PPC_MMUV3_RADIX 1
-#define KVM_PPC_MMUV3_GTSE 2
-#endif
-
-#ifndef KVM_CAP_PPC_NESTED_HV
-#define KVM_CAP_PPC_NESTED_HV 160
-#endif
-
-struct kvm_text {
- uintptr_t typ;
- const void* text;
- uintptr_t size;
-};
-
-static int kvmppc_define_rtas_kernel_token(int vmfd, unsigned token, const char* func)
-{
- struct kvm_rtas_token_args args;
-
- args.token = token;
- strncpy(args.name, func, sizeof(args.name) - 1);
-
- return ioctl(vmfd, KVM_PPC_RTAS_DEFINE_TOKEN, &args);
-}
-
-static int kvmppc_get_one_reg(int cpufd, uint64 id, void* target)
-{
- struct kvm_one_reg reg = {.id = id, .addr = (uintptr_t)target};
-
- return ioctl(cpufd, KVM_GET_ONE_REG, &reg);
-}
-
-static int kvmppc_set_one_reg(int cpufd, uint64 id, void* target)
-{
- struct kvm_one_reg reg = {.id = id, .addr = (uintptr_t)target};
-
- return ioctl(cpufd, KVM_SET_ONE_REG, &reg);
-}
-
-static int kvm_vcpu_enable_cap(int cpufd, uint32 capability)
-{
- struct kvm_enable_cap cap = {
- .cap = capability,
- };
- return ioctl(cpufd, KVM_ENABLE_CAP, &cap);
-}
-
-static int kvm_vm_enable_cap(int vmfd, uint32 capability, uint64 p1, uint64 p2)
-{
- struct kvm_enable_cap cap = {
- .cap = capability,
- .flags = 0,
- .args = {p1, p2},
- };
- return ioctl(vmfd, KVM_ENABLE_CAP, &cap);
-}
-
-static void dump_text(const char* mem, unsigned start, unsigned cw, uint32 debug_inst_opcode)
-{
-#ifdef DEBUG
- printf("Text @%x: ", start);
-
- for (unsigned i = 0; i < cw; ++i) {
- uint32 w = ((uint32*)(mem + start))[i];
-
- printf(" %08x", w);
- if (debug_inst_opcode && debug_inst_opcode == w)
- break;
- }
-
- printf("\n");
-#endif
-}
-#define KVM_SETUP_PPC64_LE (1 << 0)
-#define KVM_SETUP_PPC64_IR (1 << 1)
-#define KVM_SETUP_PPC64_DR (1 << 2)
-#define KVM_SETUP_PPC64_PR (1 << 3)
-#define KVM_SETUP_PPC64_PID1 (1 << 4)
-static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7)
-{
- const int vmfd = a0;
- const int cpufd = a1;
- char* const host_mem = (char*)a2;
- const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3;
- const uintptr_t text_count = a4;
- uintptr_t flags = a5;
- const uintptr_t page_size = 0x10000;
- const uintptr_t guest_mem_size = 24 * page_size;
- unsigned long gpa_off = 0;
- uint32 debug_inst_opcode = 0;
-
- (void)text_count;
- const void* text = 0;
- uintptr_t text_size = 0;
- uint64 pid = 0;
- uint64 lpcr = 0;
- NONFAILING(text = text_array_ptr[0].text);
- NONFAILING(text_size = text_array_ptr[0].size);
-
- if (kvm_vcpu_enable_cap(cpufd, KVM_CAP_PPC_PAPR))
- return -1;
-
- if (kvm_vm_enable_cap(vmfd, KVM_CAP_PPC_NESTED_HV, true, 0))
- return -1;
-
- for (uintptr_t i = 0; i < guest_mem_size / page_size; i++) {
- struct kvm_userspace_memory_region memreg;
- memreg.slot = i;
- memreg.flags = 0;
- memreg.guest_phys_addr = i * page_size;
- memreg.memory_size = page_size;
- memreg.userspace_addr = (uintptr_t)host_mem + i * page_size;
- if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg))
- return -1;
- }
-
- struct kvm_regs regs;
- struct kvm_sregs sregs;
- if (ioctl(cpufd, KVM_GET_SREGS, &sregs))
- return -1;
- if (ioctl(cpufd, KVM_GET_REGS, &regs))
- return -1;
-
- regs.msr = PPC_BIT(0);
- if (flags & KVM_SETUP_PPC64_LE)
- regs.msr |= PPC_BIT(63);
- if (flags & KVM_SETUP_PPC64_PR) {
- regs.msr |= PPC_BIT(49);
- flags |= KVM_SETUP_PPC64_IR | KVM_SETUP_PPC64_DR | KVM_SETUP_PPC64_PID1;
- }
-
- if (flags & KVM_SETUP_PPC64_IR)
- regs.msr |= PPC_BIT(58);
- if (flags & KVM_SETUP_PPC64_DR)
- regs.msr |= PPC_BIT(59);
- if (flags & KVM_SETUP_PPC64_PID1)
- pid = 1;
- if (kvmppc_get_one_reg(cpufd, KVM_REG_PPC_DEBUG_INST, &debug_inst_opcode))
- return -1;
-
-#define VEC(x) (*((uint32*)(host_mem + (x))))
- VEC(BOOK3S_INTERRUPT_SYSTEM_RESET) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_MACHINE_CHECK) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_DATA_STORAGE) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_DATA_SEGMENT) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_INST_STORAGE) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_INST_SEGMENT) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_EXTERNAL) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_EXTERNAL_HV) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_ALIGNMENT) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_PROGRAM) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_FP_UNAVAIL) = debug_inst_opcode;
- memcpy(host_mem + BOOK3S_INTERRUPT_DECREMENTER, kvm_ppc64_recharge_dec, sizeof(kvm_ppc64_recharge_dec) - 1);
- VEC(BOOK3S_INTERRUPT_DECREMENTER + sizeof(kvm_ppc64_recharge_dec) - 1) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_HV_DECREMENTER) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_DOORBELL) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_SYSCALL) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_TRACE) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_H_DATA_STORAGE) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_H_INST_STORAGE) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_H_EMUL_ASSIST) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_HMI) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_H_DOORBELL) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_H_VIRT) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_PERFMON) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_ALTIVEC) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_VSX) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_FAC_UNAVAIL) = debug_inst_opcode;
- VEC(BOOK3S_INTERRUPT_H_FAC_UNAVAIL) = debug_inst_opcode;
-
- struct kvm_guest_debug dbg = {0};
- dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
-
- if (ioctl(cpufd, KVM_SET_GUEST_DEBUG, &dbg))
- return -1;
- gpa_off = 128 << 10;
- if (flags & (KVM_SETUP_PPC64_IR | KVM_SETUP_PPC64_DR)) {
- uintptr_t process_tb_off = gpa_off;
- unsigned long process_tb_size = 1UL << (PRTB_SIZE_SHIFT + 4);
- struct prtb_entry {
- __be64 prtb0;
- __be64 prtb1;
- }* process_tb = (struct prtb_entry*)(host_mem + gpa_off);
-
- memset(process_tb, 0xcc, process_tb_size);
- gpa_off += process_tb_size;
-
- unsigned long *pgd, *pud, *pmd, *pte, i;
- uintptr_t pgd_off = gpa_off;
- pgd = (unsigned long*)(host_mem + pgd_off);
- gpa_off += page_size;
- uintptr_t pud_off = gpa_off;
- pud = (unsigned long*)(host_mem + pud_off);
- gpa_off += page_size;
- uintptr_t pmd_off = gpa_off;
- pmd = (unsigned long*)(host_mem + pmd_off);
- gpa_off += page_size;
- uintptr_t pte_off = gpa_off;
- pte = (unsigned long*)(host_mem + pte_off);
- gpa_off += page_size;
-
- memset(pgd, 0, page_size);
- memset(pud, 0, page_size);
- memset(pmd, 0, page_size);
- memset(pte, 0, page_size);
- pgd[0] = cpu_to_be64(PPC_BIT(0) |
- (pud_off & PPC_BITMASK(4, 55)) |
- RADIX_PUD_INDEX_SIZE);
- pud[0] = cpu_to_be64(PPC_BIT(0) |
- (pmd_off & PPC_BITMASK(4, 55)) |
- RADIX_PMD_INDEX_SIZE);
- pmd[0] = cpu_to_be64(PPC_BIT(0) |
- (pte_off & PPC_BITMASK(4, 55)) |
- RADIX_PTE_INDEX_SIZE);
- for (i = 0; i < 24; ++i)
- pte[i] = cpu_to_be64(PPC_BIT(0) |
- PPC_BIT(1) |
- ((i * page_size) & PPC_BITMASK(7, 51)) |
- PPC_BIT(55) |
- PPC_BIT(56) |
- PPC_BIT(61) |
- PPC_BIT(62) |
- PPC_BIT(63));
-
- const long max_shift = 52;
- const unsigned long rts = (max_shift - 31) & 0x1f;
- const unsigned long rts1 = (rts >> 3) << PPC_BITLSHIFT(2);
- const unsigned long rts2 = (rts & 7) << PPC_BITLSHIFT(58);
-
- process_tb[0].prtb0 = cpu_to_be64(PATB_HR | rts1 | pgd_off | rts2 | RADIX_PGD_INDEX_SIZE);
- if (pid)
- process_tb[pid].prtb0 = cpu_to_be64(PATB_HR | rts1 | pgd_off | rts2 | RADIX_PGD_INDEX_SIZE);
- struct kvm_ppc_mmuv3_cfg cfg = {
- .flags = KVM_PPC_MMUV3_RADIX | KVM_PPC_MMUV3_GTSE,
- .process_table = (process_tb_off & PRTB_MASK) | (PRTB_SIZE_SHIFT - 12) | PATB_GR,
- };
- if (ioctl(vmfd, KVM_PPC_CONFIGURE_V3_MMU, &cfg))
- return -1;
-
- lpcr |= LPCR_UPRT | LPCR_HR;
-#ifdef DEBUG
- printf("MMUv3: flags=%lx %016lx\n", cfg.flags, cfg.process_table);
- printf("PTRB0=%016lx PGD0=%016lx PUD0=%016lx PMD0=%016lx\n",
- be64_to_cpu((unsigned long)process_tb[0].prtb0), be64_to_cpu((unsigned long)pgd[0]),
- be64_to_cpu((unsigned long)pud[0]), be64_to_cpu((unsigned long)pmd[0]));
- printf("PTEs @%lx:\n %016lx %016lx %016lx %016lx\n %016lx %016lx %016lx %016lx\n",
- pte_off,
- be64_to_cpu((unsigned long)pte[0]), be64_to_cpu((unsigned long)pte[1]),
- be64_to_cpu((unsigned long)pte[2]), be64_to_cpu((unsigned long)pte[3]),
- be64_to_cpu((unsigned long)pte[4]), be64_to_cpu((unsigned long)pte[5]),
- be64_to_cpu((unsigned long)pte[6]), be64_to_cpu((unsigned long)pte[7]));
-#endif
- }
-
- memcpy(host_mem + gpa_off, text, text_size);
- regs.pc = gpa_off;
-
- uintptr_t end_of_text = gpa_off + ((text_size + 3) & ~3);
- memcpy(host_mem + end_of_text, &debug_inst_opcode, sizeof(debug_inst_opcode));
- if (!(flags & KVM_SETUP_PPC64_LE)) {
- uint32* p = (uint32*)(host_mem + gpa_off);
- for (unsigned long i = 0; i < text_size / sizeof(*p); ++i)
- p[i] = cpu_to_be32(p[i]);
-
- p = (uint32*)(host_mem + BOOK3S_INTERRUPT_DECREMENTER);
- for (unsigned long i = 0; i < sizeof(kvm_ppc64_recharge_dec) / sizeof(*p); ++i)
- p[i] = cpu_to_be32(p[i]);
- } else {
- lpcr |= LPCR_ILE;
- }
-
- if (ioctl(cpufd, KVM_SET_SREGS, &sregs))
- return -1;
- if (ioctl(cpufd, KVM_SET_REGS, &regs))
- return -1;
- if (kvmppc_set_one_reg(cpufd, KVM_REG_PPC_LPCR_64, &lpcr))
- return -1;
- if (kvmppc_set_one_reg(cpufd, KVM_REG_PPC_PID, &pid))
- return -1;
-#define MAX_HCALL 0x450
- for (unsigned hcall = 4; hcall < MAX_HCALL; hcall += 4)
- kvm_vm_enable_cap(vmfd, KVM_CAP_PPC_ENABLE_HCALL, hcall, 1);
-
- for (unsigned hcall = 0xf000; hcall < 0xf810; hcall += 4)
- kvm_vm_enable_cap(vmfd, KVM_CAP_PPC_ENABLE_HCALL, hcall, 1);
-
- for (unsigned hcall = 0xef00; hcall < 0xef20; hcall += 4)
- kvm_vm_enable_cap(vmfd, KVM_CAP_PPC_ENABLE_HCALL, hcall, 1);
- kvmppc_define_rtas_kernel_token(vmfd, 1, "ibm,set-xive");
- kvmppc_define_rtas_kernel_token(vmfd, 2, "ibm,get-xive");
- kvmppc_define_rtas_kernel_token(vmfd, 3, "ibm,int-on");
- kvmppc_define_rtas_kernel_token(vmfd, 4, "ibm,int-off");
-
- dump_text(host_mem, regs.pc, 8, debug_inst_opcode);
- dump_text(host_mem, BOOK3S_INTERRUPT_DECREMENTER, 16, debug_inst_opcode);
-
- uint64 decr = 0x7fffffff;
- if (kvmppc_set_one_reg(cpufd, KVM_REG_PPC_DEC_EXPIRY, &decr))
- return -1;
-
- return 0;
-}
-
-#elif !GOARCH_arm
-static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7)
-{
- return 0;
-}
-#endif
-#endif
-#endif
-
-#if (SYZ_EXECUTOR || SYZ_NET_RESET) && SYZ_EXECUTOR_USES_FORK_SERVER
-#include <errno.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/socket.h>
-
-#include <linux/net.h>
-#define XT_TABLE_SIZE 1536
-#define XT_MAX_ENTRIES 10
-
-struct xt_counters {
- uint64 pcnt, bcnt;
-};
-
-struct ipt_getinfo {
- char name[32];
- unsigned int valid_hooks;
- unsigned int hook_entry[5];
- unsigned int underflow[5];
- unsigned int num_entries;
- unsigned int size;
-};
-
-struct ipt_get_entries {
- char name[32];
- unsigned int size;
- uint64 entrytable[XT_TABLE_SIZE / sizeof(uint64)];
-};
-
-struct ipt_replace {
- char name[32];
- unsigned int valid_hooks;
- unsigned int num_entries;
- unsigned int size;
- unsigned int hook_entry[5];
- unsigned int underflow[5];
- unsigned int num_counters;
- struct xt_counters* counters;
- uint64 entrytable[XT_TABLE_SIZE / sizeof(uint64)];
-};
-
-struct ipt_table_desc {
- const char* name;
- struct ipt_getinfo info;
- struct ipt_replace replace;
-};
-
-static struct ipt_table_desc ipv4_tables[] = {
- {.name = "filter"},
- {.name = "nat"},
- {.name = "mangle"},
- {.name = "raw"},
- {.name = "security"},
-};
-
-static struct ipt_table_desc ipv6_tables[] = {
- {.name = "filter"},
- {.name = "nat"},
- {.name = "mangle"},
- {.name = "raw"},
- {.name = "security"},
-};
-
-#define IPT_BASE_CTL 64
-#define IPT_SO_SET_REPLACE (IPT_BASE_CTL)
-#define IPT_SO_GET_INFO (IPT_BASE_CTL)
-#define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1)
-
-struct arpt_getinfo {
- char name[32];
- unsigned int valid_hooks;
- unsigned int hook_entry[3];
- unsigned int underflow[3];
- unsigned int num_entries;
- unsigned int size;
-};
-
-struct arpt_get_entries {
- char name[32];
- unsigned int size;
- uint64 entrytable[XT_TABLE_SIZE / sizeof(uint64)];
-};
-
-struct arpt_replace {
- char name[32];
- unsigned int valid_hooks;
- unsigned int num_entries;
- unsigned int size;
- unsigned int hook_entry[3];
- unsigned int underflow[3];
- unsigned int num_counters;
- struct xt_counters* counters;
- uint64 entrytable[XT_TABLE_SIZE / sizeof(uint64)];
-};
-
-struct arpt_table_desc {
- const char* name;
- struct arpt_getinfo info;
- struct arpt_replace replace;
-};
-
-static struct arpt_table_desc arpt_tables[] = {
- {.name = "filter"},
-};
-
-#define ARPT_BASE_CTL 96
-#define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL)
-#define ARPT_SO_GET_INFO (ARPT_BASE_CTL)
-#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1)
-
-static void checkpoint_iptables(struct ipt_table_desc* tables, int num_tables, int family, int level)
-{
- int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
- if (fd == -1) {
- switch (errno) {
- case EAFNOSUPPORT:
- case ENOPROTOOPT:
- case ENOENT:
- return;
- }
- failmsg("iptable checkpoint: socket(SOCK_STREAM, IPPROTO_TCP) failed", "family=%d", family);
- }
- for (int i = 0; i < num_tables; i++) {
- struct ipt_table_desc* table = &tables[i];
- strcpy(table->info.name, table->name);
- strcpy(table->replace.name, table->name);
- socklen_t optlen = sizeof(table->info);
- if (getsockopt(fd, level, IPT_SO_GET_INFO, &table->info, &optlen)) {
- switch (errno) {
- case EPERM:
- case ENOENT:
- case ENOPROTOOPT:
- continue;
- }
- failmsg("iptable checkpoint: getsockopt(IPT_SO_GET_INFO) failed",
- "table=%s, family=%d", table->name, family);
- }
- debug("iptable checkpoint %s/%d: checkpoint entries=%d hooks=%x size=%d\n",
- table->name, family, table->info.num_entries,
- table->info.valid_hooks, table->info.size);
- if (table->info.size > sizeof(table->replace.entrytable))
- failmsg("iptable checkpoint: table size is too large", "table=%s, family=%d, size=%u",
- table->name, family, table->info.size);
- if (table->info.num_entries > XT_MAX_ENTRIES)
- failmsg("iptable checkpoint: too many counters", "table=%s, family=%d, counters=%d",
- table->name, family, table->info.num_entries);
- struct ipt_get_entries entries;
- memset(&entries, 0, sizeof(entries));
- strcpy(entries.name, table->name);
- entries.size = table->info.size;
- optlen = sizeof(entries) - sizeof(entries.entrytable) + table->info.size;
- if (getsockopt(fd, level, IPT_SO_GET_ENTRIES, &entries, &optlen))
- failmsg("iptable checkpoint: getsockopt(IPT_SO_GET_ENTRIES) failed",
- "table=%s, family=%d", table->name, family);
- table->replace.valid_hooks = table->info.valid_hooks;
- table->replace.num_entries = table->info.num_entries;
- table->replace.size = table->info.size;
- memcpy(table->replace.hook_entry, table->info.hook_entry, sizeof(table->replace.hook_entry));
- memcpy(table->replace.underflow, table->info.underflow, sizeof(table->replace.underflow));
- memcpy(table->replace.entrytable, entries.entrytable, table->info.size);
- }
- close(fd);
-}
-
-static void reset_iptables(struct ipt_table_desc* tables, int num_tables, int family, int level)
-{
- int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
- if (fd == -1) {
- switch (errno) {
- case EAFNOSUPPORT:
- case ENOPROTOOPT:
- case ENOENT:
- return;
- }
- failmsg("iptable: socket(SOCK_STREAM, IPPROTO_TCP) failed", "family=%d", family);
- }
- for (int i = 0; i < num_tables; i++) {
- struct ipt_table_desc* table = &tables[i];
- if (table->info.valid_hooks == 0)
- continue;
- struct ipt_getinfo info;
- memset(&info, 0, sizeof(info));
- strcpy(info.name, table->name);
- socklen_t optlen = sizeof(info);
- if (getsockopt(fd, level, IPT_SO_GET_INFO, &info, &optlen))
- failmsg("iptable: getsockopt(IPT_SO_GET_INFO) failed",
- "table=%s, family=%d", table->name, family);
- if (memcmp(&table->info, &info, sizeof(table->info)) == 0) {
- struct ipt_get_entries entries;
- memset(&entries, 0, sizeof(entries));
- strcpy(entries.name, table->name);
- entries.size = table->info.size;
- optlen = sizeof(entries) - sizeof(entries.entrytable) + entries.size;
- if (getsockopt(fd, level, IPT_SO_GET_ENTRIES, &entries, &optlen))
- failmsg("iptable: getsockopt(IPT_SO_GET_ENTRIES) failed",
- "table=%s, family=%d", table->name, family);
- if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0)
- continue;
- }
- debug("iptable %s/%d: resetting\n", table->name, family);
- struct xt_counters counters[XT_MAX_ENTRIES];
- table->replace.num_counters = info.num_entries;
- table->replace.counters = counters;
- optlen = sizeof(table->replace) - sizeof(table->replace.entrytable) + table->replace.size;
- if (setsockopt(fd, level, IPT_SO_SET_REPLACE, &table->replace, optlen))
- failmsg("iptable: setsockopt(IPT_SO_SET_REPLACE) failed",
- "table=%s, family=%d", table->name, family);
- }
- close(fd);
-}
-
-static void checkpoint_arptables(void)
-{
- int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (fd == -1) {
- switch (errno) {
- case EAFNOSUPPORT:
- case ENOPROTOOPT:
- case ENOENT:
- return;
- }
- fail("arptable checkpoint: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) failed");
- }
- for (unsigned i = 0; i < sizeof(arpt_tables) / sizeof(arpt_tables[0]); i++) {
- struct arpt_table_desc* table = &arpt_tables[i];
- strcpy(table->info.name, table->name);
- strcpy(table->replace.name, table->name);
- socklen_t optlen = sizeof(table->info);
- if (getsockopt(fd, SOL_IP, ARPT_SO_GET_INFO, &table->info, &optlen)) {
- switch (errno) {
- case EPERM:
- case ENOENT:
- case ENOPROTOOPT:
- continue;
- }
- failmsg("arptable checkpoint: getsockopt(ARPT_SO_GET_INFO) failed", "table=%s", table->name);
- }
- debug("arptable checkpoint %s: entries=%d hooks=%x size=%d\n",
- table->name, table->info.num_entries, table->info.valid_hooks, table->info.size);
- if (table->info.size > sizeof(table->replace.entrytable))
- failmsg("arptable checkpoint: table size is too large",
- "table=%s, size=%u", table->name, table->info.size);
- if (table->info.num_entries > XT_MAX_ENTRIES)
- failmsg("arptable checkpoint: too many counters",
- "table=%s, counters=%u", table->name, table->info.num_entries);
- struct arpt_get_entries entries;
- memset(&entries, 0, sizeof(entries));
- strcpy(entries.name, table->name);
- entries.size = table->info.size;
- optlen = sizeof(entries) - sizeof(entries.entrytable) + table->info.size;
- if (getsockopt(fd, SOL_IP, ARPT_SO_GET_ENTRIES, &entries, &optlen))
- failmsg("arptable checkpoint: getsockopt(ARPT_SO_GET_ENTRIES) failed", "table=%s", table->name);
- table->replace.valid_hooks = table->info.valid_hooks;
- table->replace.num_entries = table->info.num_entries;
- table->replace.size = table->info.size;
- memcpy(table->replace.hook_entry, table->info.hook_entry, sizeof(table->replace.hook_entry));
- memcpy(table->replace.underflow, table->info.underflow, sizeof(table->replace.underflow));
- memcpy(table->replace.entrytable, entries.entrytable, table->info.size);
- }
- close(fd);
-}
-
-static void reset_arptables()
-{
- int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (fd == -1) {
- switch (errno) {
- case EAFNOSUPPORT:
- case ENOPROTOOPT:
- case ENOENT:
- return;
- }
- fail("arptable: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)");
- }
- for (unsigned i = 0; i < sizeof(arpt_tables) / sizeof(arpt_tables[0]); i++) {
- struct arpt_table_desc* table = &arpt_tables[i];
- if (table->info.valid_hooks == 0)
- continue;
- struct arpt_getinfo info;
- memset(&info, 0, sizeof(info));
- strcpy(info.name, table->name);
- socklen_t optlen = sizeof(info);
- if (getsockopt(fd, SOL_IP, ARPT_SO_GET_INFO, &info, &optlen))
- failmsg("arptable: getsockopt(ARPT_SO_GET_INFO) failed", "table=%s", table->name);
- if (memcmp(&table->info, &info, sizeof(table->info)) == 0) {
- struct arpt_get_entries entries;
- memset(&entries, 0, sizeof(entries));
- strcpy(entries.name, table->name);
- entries.size = table->info.size;
- optlen = sizeof(entries) - sizeof(entries.entrytable) + entries.size;
- if (getsockopt(fd, SOL_IP, ARPT_SO_GET_ENTRIES, &entries, &optlen))
- failmsg("arptable: getsockopt(ARPT_SO_GET_ENTRIES) failed", "table=%s", table->name);
- if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0)
- continue;
- debug("arptable %s: data changed\n", table->name);
- } else {
- debug("arptable %s: header changed\n", table->name);
- }
- debug("arptable %s: resetting\n", table->name);
- struct xt_counters counters[XT_MAX_ENTRIES];
- table->replace.num_counters = info.num_entries;
- table->replace.counters = counters;
- optlen = sizeof(table->replace) - sizeof(table->replace.entrytable) + table->replace.size;
- if (setsockopt(fd, SOL_IP, ARPT_SO_SET_REPLACE, &table->replace, optlen))
- failmsg("arptable: setsockopt(ARPT_SO_SET_REPLACE) failed",
- "table=%s", table->name);
- }
- close(fd);
-}
-
-#define NF_BR_NUMHOOKS 6
-#define EBT_TABLE_MAXNAMELEN 32
-#define EBT_CHAIN_MAXNAMELEN 32
-#define EBT_BASE_CTL 128
-#define EBT_SO_SET_ENTRIES (EBT_BASE_CTL)
-#define EBT_SO_GET_INFO (EBT_BASE_CTL)
-#define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO + 1)
-#define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES + 1)
-#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO + 1)
-
-struct ebt_replace {
- char name[EBT_TABLE_MAXNAMELEN];
- unsigned int valid_hooks;
- unsigned int nentries;
- unsigned int entries_size;
- struct ebt_entries* hook_entry[NF_BR_NUMHOOKS];
- unsigned int num_counters;
- struct ebt_counter* counters;
- char* entries;
-};
-
-struct ebt_entries {
- unsigned int distinguisher;
- char name[EBT_CHAIN_MAXNAMELEN];
- unsigned int counter_offset;
- int policy;
- unsigned int nentries;
- char data[0] __attribute__((aligned(__alignof__(struct ebt_replace))));
-};
-
-struct ebt_table_desc {
- const char* name;
- struct ebt_replace replace;
- char entrytable[XT_TABLE_SIZE];
-};
-
-static struct ebt_table_desc ebt_tables[] = {
- {.name = "filter"},
- {.name = "nat"},
- {.name = "broute"},
-};
-
-static void checkpoint_ebtables(void)
-{
- int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (fd == -1) {
- switch (errno) {
- case EAFNOSUPPORT:
- case ENOPROTOOPT:
- case ENOENT:
- return;
- }
- fail("ebtable checkpoint: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)");
- }
- for (size_t i = 0; i < sizeof(ebt_tables) / sizeof(ebt_tables[0]); i++) {
- struct ebt_table_desc* table = &ebt_tables[i];
- strcpy(table->replace.name, table->name);
- socklen_t optlen = sizeof(table->replace);
- if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_INFO, &table->replace, &optlen)) {
- switch (errno) {
- case EPERM:
- case ENOENT:
- case ENOPROTOOPT:
- continue;
- }
- failmsg("ebtable checkpoint: getsockopt(EBT_SO_GET_INIT_INFO) failed",
- "table=%s", table->name);
- }
- debug("ebtable checkpoint %s: entries=%d hooks=%x size=%d\n",
- table->name, table->replace.nentries, table->replace.valid_hooks,
- table->replace.entries_size);
- if (table->replace.entries_size > sizeof(table->entrytable))
- failmsg("ebtable checkpoint: table size is too large", "table=%s, size=%u",
- table->name, table->replace.entries_size);
- table->replace.num_counters = 0;
- table->replace.entries = table->entrytable;
- optlen = sizeof(table->replace) + table->replace.entries_size;
- if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_ENTRIES, &table->replace, &optlen))
- failmsg("ebtable checkpoint: getsockopt(EBT_SO_GET_INIT_ENTRIES) failed",
- "table=%s", table->name);
- }
- close(fd);
-}
-
-static void reset_ebtables()
-{
- int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (fd == -1) {
- switch (errno) {
- case EAFNOSUPPORT:
- case ENOPROTOOPT:
- case ENOENT:
- return;
- }
- fail("ebtable: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)");
- }
- for (unsigned i = 0; i < sizeof(ebt_tables) / sizeof(ebt_tables[0]); i++) {
- struct ebt_table_desc* table = &ebt_tables[i];
- if (table->replace.valid_hooks == 0)
- continue;
- struct ebt_replace replace;
- memset(&replace, 0, sizeof(replace));
- strcpy(replace.name, table->name);
- socklen_t optlen = sizeof(replace);
- if (getsockopt(fd, SOL_IP, EBT_SO_GET_INFO, &replace, &optlen))
- failmsg("ebtable: getsockopt(EBT_SO_GET_INFO)", "table=%s", table->name);
- replace.num_counters = 0;
- table->replace.entries = 0;
- for (unsigned h = 0; h < NF_BR_NUMHOOKS; h++)
- table->replace.hook_entry[h] = 0;
- if (memcmp(&table->replace, &replace, sizeof(table->replace)) == 0) {
- char entrytable[XT_TABLE_SIZE];
- memset(&entrytable, 0, sizeof(entrytable));
- replace.entries = entrytable;
- optlen = sizeof(replace) + replace.entries_size;
- if (getsockopt(fd, SOL_IP, EBT_SO_GET_ENTRIES, &replace, &optlen))
- failmsg("ebtable: getsockopt(EBT_SO_GET_ENTRIES) failed", "table=%s", table->name);
- if (memcmp(table->entrytable, entrytable, replace.entries_size) == 0)
- continue;
- }
- debug("ebtable %s: resetting\n", table->name);
- for (unsigned j = 0, h = 0; h < NF_BR_NUMHOOKS; h++) {
- if (table->replace.valid_hooks & (1 << h)) {
- table->replace.hook_entry[h] = (struct ebt_entries*)table->entrytable + j;
- j++;
- }
- }
- table->replace.entries = table->entrytable;
- optlen = sizeof(table->replace) + table->replace.entries_size;
- if (setsockopt(fd, SOL_IP, EBT_SO_SET_ENTRIES, &table->replace, optlen))
- failmsg("ebtable: setsockopt(EBT_SO_SET_ENTRIES) failed", "table=%s", table->name);
- }
- close(fd);
-}
-
-static void checkpoint_net_namespace(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_reset || flag_sandbox_setuid)
- return;
-#endif
- checkpoint_ebtables();
- checkpoint_arptables();
- checkpoint_iptables(ipv4_tables, sizeof(ipv4_tables) / sizeof(ipv4_tables[0]), AF_INET, SOL_IP);
- checkpoint_iptables(ipv6_tables, sizeof(ipv6_tables) / sizeof(ipv6_tables[0]), AF_INET6, SOL_IPV6);
-}
-
-static void reset_net_namespace(void)
-{
-#if SYZ_EXECUTOR
- if (!flag_net_reset || flag_sandbox_setuid)
- return;
-#endif
- reset_ebtables();
- reset_arptables();
- reset_iptables(ipv4_tables, sizeof(ipv4_tables) / sizeof(ipv4_tables[0]), AF_INET, SOL_IP);
- reset_iptables(ipv6_tables, sizeof(ipv6_tables) / sizeof(ipv6_tables[0]), AF_INET6, SOL_IPV6);
-}
-#endif
-
-#if SYZ_EXECUTOR || (SYZ_CGROUPS && (SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID))
-#include <fcntl.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static void mount_cgroups(const char* dir, const char** controllers, int count)
-{
- if (mkdir(dir, 0777)) {
- debug("mkdir(%s) failed: %d\n", dir, errno);
- return;
- }
- char enabled[128] = {0};
- int i = 0;
- for (; i < count; i++) {
- if (mount("none", dir, "cgroup", 0, controllers[i])) {
- debug("mount(%s, %s) failed: %d\n", dir, controllers[i], errno);
- continue;
- }
- umount(dir);
- strcat(enabled, ",");
- strcat(enabled, controllers[i]);
- }
- if (enabled[0] == 0) {
- if (rmdir(dir) && errno != EBUSY)
- failmsg("rmdir failed", "dir=%s", dir);
- return;
- }
- if (mount("none", dir, "cgroup", 0, enabled + 1)) {
- debug("mount(%s, %s) failed: %d\n", dir, enabled + 1, errno);
- if (rmdir(dir) && errno != EBUSY)
- failmsg("rmdir failed", "dir=%s enabled=%s", dir, enabled);
- }
- if (chmod(dir, 0777)) {
- debug("chmod(%s) failed: %d\n", dir, errno);
- }
-}
-
-static void mount_cgroups2(const char** controllers, int count)
-{
- if (mkdir("/syzcgroup/unified", 0777)) {
- debug("mkdir(/syzcgroup/unified) failed: %d\n", errno);
- return;
- }
- if (mount("none", "/syzcgroup/unified", "cgroup2", 0, NULL)) {
- debug("mount(cgroup2) failed: %d\n", errno);
- if (rmdir("/syzcgroup/unified") && errno != EBUSY)
- fail("rmdir(/syzcgroup/unified) failed");
- return;
- }
- if (chmod("/syzcgroup/unified", 0777)) {
- debug("chmod(/syzcgroup/unified) failed: %d\n", errno);
- }
- int control = open("/syzcgroup/unified/cgroup.subtree_control", O_WRONLY);
- if (control == -1)
- return;
- int i;
- for (i = 0; i < count; i++)
- if (write(control, controllers[i], strlen(controllers[i])) < 0) {
- debug("write(cgroup.subtree_control, %s) failed: %d\n", controllers[i], errno);
- }
- close(control);
-}
-
-static void setup_cgroups()
-{
- const char* unified_controllers[] = {"+cpu", "+io", "+pids"};
- const char* net_controllers[] = {"net", "net_prio", "devices", "blkio", "freezer"};
- const char* cpu_controllers[] = {"cpuset", "cpuacct", "hugetlb", "rlimit", "memory"};
- if (mkdir("/syzcgroup", 0777)) {
- debug("mkdir(/syzcgroup) failed: %d\n", errno);
- return;
- }
- mount_cgroups2(unified_controllers, sizeof(unified_controllers) / sizeof(unified_controllers[0]));
- mount_cgroups("/syzcgroup/net", net_controllers, sizeof(net_controllers) / sizeof(net_controllers[0]));
- mount_cgroups("/syzcgroup/cpu", cpu_controllers, sizeof(cpu_controllers) / sizeof(cpu_controllers[0]));
- write_file("/syzcgroup/cpu/cgroup.clone_children", "1");
- write_file("/syzcgroup/cpu/cpuset.memory_pressure_enabled", "1");
-}
-
-#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
-static void setup_cgroups_loop()
-{
-#if SYZ_EXECUTOR
- if (!flag_cgroups)
- return;
-#endif
- int pid = getpid();
- char file[128];
- char cgroupdir[64];
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
- if (mkdir(cgroupdir, 0777)) {
- debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
- }
- snprintf(file, sizeof(file), "%s/pids.max", cgroupdir);
- write_file(file, "32");
- snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
- write_file(file, "%d", pid);
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid);
- if (mkdir(cgroupdir, 0777)) {
- debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
- }
- snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
- write_file(file, "%d", pid);
- snprintf(file, sizeof(file), "%s/memory.soft_limit_in_bytes", cgroupdir);
- write_file(file, "%d", 299 << 20);
- snprintf(file, sizeof(file), "%s/memory.limit_in_bytes", cgroupdir);
- write_file(file, "%d", 300 << 20);
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid);
- if (mkdir(cgroupdir, 0777)) {
- debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
- }
- snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
- write_file(file, "%d", pid);
-}
-
-static void setup_cgroups_test()
-{
-#if SYZ_EXECUTOR
- if (!flag_cgroups)
- return;
-#endif
- char cgroupdir[64];
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
- if (symlink(cgroupdir, "./cgroup")) {
- debug("symlink(%s, ./cgroup) failed: %d\n", cgroupdir, errno);
- }
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid);
- if (symlink(cgroupdir, "./cgroup.cpu")) {
- debug("symlink(%s, ./cgroup.cpu) failed: %d\n", cgroupdir, errno);
- }
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid);
- if (symlink(cgroupdir, "./cgroup.net")) {
- debug("symlink(%s, ./cgroup.net) failed: %d\n", cgroupdir, errno);
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NAMESPACE
-static void initialize_cgroups()
-{
-#if SYZ_EXECUTOR
- if (!flag_cgroups)
- return;
-#endif
- if (mkdir("./syz-tmp/newroot/syzcgroup", 0700))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/syzcgroup/unified", 0700))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/syzcgroup/cpu", 0700))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/syzcgroup/net", 0700))
- fail("mkdir failed");
- unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE;
- if (mount("/syzcgroup/unified", "./syz-tmp/newroot/syzcgroup/unified", NULL, bind_mount_flags, NULL)) {
- debug("mount(cgroup2, MS_BIND) failed: %d\n", errno);
- }
- if (mount("/syzcgroup/cpu", "./syz-tmp/newroot/syzcgroup/cpu", NULL, bind_mount_flags, NULL)) {
- debug("mount(cgroup/cpu, MS_BIND) failed: %d\n", errno);
- }
- if (mount("/syzcgroup/net", "./syz-tmp/newroot/syzcgroup/net", NULL, bind_mount_flags, NULL)) {
- debug("mount(cgroup/net, MS_BIND) failed: %d\n", errno);
- }
-}
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID
-#include <errno.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static void setup_common()
-{
- if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) {
- debug("mount(fusectl) failed: %d\n", errno);
- }
-}
-
-static void setup_binderfs()
-{
- if (mkdir("/dev/binderfs", 0777)) {
- debug("mkdir(/dev/binderfs) failed: %d\n", errno);
- }
-
- if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) {
- debug("mount of binder at /dev/binderfs failed: %d\n", errno);
- }
-#if !SYZ_EXECUTOR && !SYZ_USE_TMP_DIR
- if (symlink("/dev/binderfs", "./binderfs")) {
- debug("symlink(/dev/binderfs, ./binderfs) failed: %d\n", errno);
- }
-#endif
-}
-
-#include <sched.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-static void loop();
-
-static void sandbox_common()
-{
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setsid();
-
-#if SYZ_EXECUTOR || __NR_syz_init_net_socket || SYZ_DEVLINK_PCI || __NR_syz_socket_connect_nvme_tcp
- int netns = open("/proc/self/ns/net", O_RDONLY);
- if (netns == -1)
- fail("open(/proc/self/ns/net) failed");
- if (dup2(netns, kInitNetNsFd) < 0)
- fail("dup2(netns, kInitNetNsFd) failed");
- close(netns);
-#endif
-
- struct rlimit rlim;
-#if SYZ_EXECUTOR
- rlim.rlim_cur = rlim.rlim_max = (200 << 20) +
- (kMaxThreads * kCoverSize + kExtraCoverSize) * sizeof(void*);
-#else
- rlim.rlim_cur = rlim.rlim_max = (200 << 20);
-#endif
- setrlimit(RLIMIT_AS, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 32 << 20;
- setrlimit(RLIMIT_MEMLOCK, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 136 << 20;
- setrlimit(RLIMIT_FSIZE, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 1 << 20;
- setrlimit(RLIMIT_STACK, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 128 << 20;
- setrlimit(RLIMIT_CORE, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 256;
- setrlimit(RLIMIT_NOFILE, &rlim);
- if (unshare(CLONE_NEWNS)) {
- debug("unshare(CLONE_NEWNS): %d\n", errno);
- }
- if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
- debug("mount(\"/\", MS_REC | MS_PRIVATE): %d\n", errno);
- }
- if (unshare(CLONE_NEWIPC)) {
- debug("unshare(CLONE_NEWIPC): %d\n", errno);
- }
- if (unshare(0x02000000)) {
- debug("unshare(CLONE_NEWCGROUP): %d\n", errno);
- }
- if (unshare(CLONE_NEWUTS)) {
- debug("unshare(CLONE_NEWUTS): %d\n", errno);
- }
- if (unshare(CLONE_SYSVSEM)) {
- debug("unshare(CLONE_SYSVSEM): %d\n", errno);
- }
- typedef struct {
- const char* name;
- const char* value;
- } sysctl_t;
- static const sysctl_t sysctls[] = {
- {"/proc/sys/kernel/shmmax", "16777216"},
- {"/proc/sys/kernel/shmall", "536870912"},
- {"/proc/sys/kernel/shmmni", "1024"},
- {"/proc/sys/kernel/msgmax", "8192"},
- {"/proc/sys/kernel/msgmni", "1024"},
- {"/proc/sys/kernel/msgmnb", "1024"},
- {"/proc/sys/kernel/sem", "1024 1048576 500 1024"},
- };
- unsigned i;
- for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++)
- write_file(sysctls[i].name, sysctls[i].value);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE
-static int wait_for_loop(int pid)
-{
- if (pid < 0)
- fail("sandbox fork failed");
- debug("spawned loop pid %d\n", pid);
- int status = 0;
- while (waitpid(-1, &status, __WALL) != pid) {
- }
- return WEXITSTATUS(status);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID
-#include <linux/capability.h>
-
-static void drop_caps(void)
-{
- 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");
- const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE);
- cap_data[0].effective &= ~drop;
- cap_data[0].permitted &= ~drop;
- cap_data[0].inheritable &= ~drop;
- if (syscall(SYS_capset, &cap_hdr, &cap_data))
- fail("capset failed");
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-#include <sched.h>
-#include <sys/types.h>
-
-static int do_sandbox_none(void)
-{
- if (unshare(CLONE_NEWPID)) {
- debug("unshare(CLONE_NEWPID): %d\n", errno);
- }
- int pid = fork();
- if (pid != 0)
- return wait_for_loop(pid);
-
- setup_common();
-#if SYZ_EXECUTOR || SYZ_VHCI_INJECTION
- initialize_vhci();
-#endif
- sandbox_common();
- drop_caps();
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices_init();
-#endif
- if (unshare(CLONE_NEWNET)) {
- debug("unshare(CLONE_NEWNET): %d\n", errno);
- }
- write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535");
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
- initialize_devlink_pci();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices();
-#endif
-#if SYZ_EXECUTOR || SYZ_WIFI
- initialize_wifi_devices();
-#endif
- setup_binderfs();
- loop();
- doexit(1);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID
-#include <grp.h>
-#include <sched.h>
-#include <sys/prctl.h>
-
-#define SYZ_HAVE_SANDBOX_SETUID 1
-static int do_sandbox_setuid(void)
-{
- if (unshare(CLONE_NEWPID)) {
- debug("unshare(CLONE_NEWPID): %d\n", errno);
- }
- int pid = fork();
- if (pid != 0)
- return wait_for_loop(pid);
-
- setup_common();
-#if SYZ_EXECUTOR || SYZ_VHCI_INJECTION
- initialize_vhci();
-#endif
- sandbox_common();
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices_init();
-#endif
- if (unshare(CLONE_NEWNET)) {
- debug("unshare(CLONE_NEWNET): %d\n", errno);
- }
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
- initialize_devlink_pci();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices();
-#endif
-#if SYZ_EXECUTOR || SYZ_WIFI
- initialize_wifi_devices();
-#endif
- setup_binderfs();
-
- const int nobody = 65534;
- if (setgroups(0, NULL))
- fail("failed to setgroups");
- if (syscall(SYS_setresgid, nobody, nobody, nobody))
- fail("failed to setresgid");
- if (syscall(SYS_setresuid, nobody, nobody, nobody))
- fail("failed to setresuid");
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-
- loop();
- doexit(1);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NAMESPACE
-#include <sched.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-
-static int real_uid;
-static int real_gid;
-__attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20];
-
-static int namespace_sandbox_proc(void* arg)
-{
- sandbox_common();
- write_file("/proc/self/setgroups", "deny");
- if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid))
- fail("write of /proc/self/uid_map failed");
- if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid))
- fail("write of /proc/self/gid_map failed");
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices_init();
-#endif
- if (unshare(CLONE_NEWNET))
- fail("unshare(CLONE_NEWNET)");
- write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535");
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
- initialize_devlink_pci();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices();
-#endif
-#if SYZ_EXECUTOR || SYZ_WIFI
- initialize_wifi_devices();
-#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");
- unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE;
- if (mount("/dev", "./syz-tmp/newroot/dev", NULL, bind_mount_flags, 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/newroot/selinux", 0700))
- fail("mkdir failed");
- const char* selinux_path = "./syz-tmp/newroot/selinux";
- if (mount("/selinux", selinux_path, NULL, bind_mount_flags, NULL)) {
- if (errno != ENOENT)
- fail("mount(/selinux) failed");
- if (mount("/sys/fs/selinux", selinux_path, NULL, bind_mount_flags, NULL) && errno != ENOENT)
- fail("mount(/sys/fs/selinux) failed");
- }
- if (mkdir("./syz-tmp/newroot/sys", 0700))
- fail("mkdir failed");
- if (mount("/sys", "./syz-tmp/newroot/sys", 0, bind_mount_flags, NULL))
- fail("mount(sysfs) failed");
-#if SYZ_EXECUTOR || SYZ_CGROUPS
- initialize_cgroups();
-#endif
- if (mkdir("./syz-tmp/pivot", 0777))
- fail("mkdir failed");
- if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) {
- debug("pivot_root failed\n");
- if (chdir("./syz-tmp"))
- fail("chdir failed");
- } else {
- debug("pivot_root OK\n");
- if (chdir("/"))
- fail("chdir failed");
- if (umount2("./pivot", MNT_DETACH))
- fail("umount failed");
- }
- if (chroot("./newroot"))
- fail("chroot failed");
- if (chdir("/"))
- fail("chdir failed");
- setup_binderfs();
- drop_caps();
-
- loop();
- doexit(1);
-}
-
-#define SYZ_HAVE_SANDBOX_NAMESPACE 1
-static int do_sandbox_namespace(void)
-{
- setup_common();
-#if SYZ_EXECUTOR || SYZ_VHCI_INJECTION
- initialize_vhci();
-#endif
- real_uid = getuid();
- real_gid = getgid();
- mprotect(sandbox_stack, 4096, PROT_NONE);
- int pid = clone(namespace_sandbox_proc, &sandbox_stack[sizeof(sandbox_stack) - 64],
- CLONE_NEWUSER | CLONE_NEWPID, 0);
- return wait_for_loop(pid);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_ANDROID
-#if GOARCH_arm || GOARCH_arm64 || GOARCH_386 || GOARCH_amd64
-#include <assert.h>
-#include <errno.h>
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#if GOARCH_arm64
-#define PRIMARY_ARCH AUDIT_ARCH_AARCH64
-
-const struct sock_filter arm64_app_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 68),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 98, 66, 0),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 29, 65, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 163, 33, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 101, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 52, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 30, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 18, 59, 58),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 29, 58, 57),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 57, 56),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 42, 55, 54),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 51, 54, 53),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 90, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 59, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 51, 50),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 50, 49),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 99, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 48, 47),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 100, 47, 46),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 147, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 113, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 107, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 104, 43, 42),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 112, 42, 41),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 40, 39),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 142, 39, 38),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 153, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 36, 35),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 151, 35, 34),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 160, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 159, 33, 32),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 161, 32, 31),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 267, 15, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 220, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 170, 27, 26),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 180, 26, 25),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 203, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 202, 24, 23),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 23, 22),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 240, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 226, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 20, 19),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 234, 19, 18),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 260, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 244, 17, 16),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 262, 16, 15),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 434, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 274, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 272, 12, 11),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 288, 11, 10),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 424, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 292, 9, 8),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 425, 8, 7),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 438, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 436, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 435, 5, 4),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 437, 4, 3),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 440, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 439, 2, 1),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 441, 1, 0),
-BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define arm64_app_filter_size (sizeof(arm64_app_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* primary_app_filter = arm64_app_filter;
-static const size_t primary_app_filter_size = arm64_app_filter_size;
-
-const struct sock_filter arm64_system_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 46),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 98, 44, 0),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 29, 43, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 226, 21, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 101, 11, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 30, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 18, 38, 37),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 29, 37, 36),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 42, 36, 35),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 99, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 59, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 33, 32),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 32, 31),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 100, 31, 30),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 203, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 105, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 104, 27, 26),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 180, 26, 25),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 202, 25, 24),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 220, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 23, 22),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 22, 21),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 424, 11, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 266, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 260, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 240, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 234, 17, 16),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 244, 16, 15),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 262, 15, 14),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 274, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 272, 12, 11),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 288, 11, 10),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 292, 10, 9),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 438, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 436, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 434, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 425, 6, 5),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 435, 5, 4),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 437, 4, 3),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 440, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 439, 2, 1),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 441, 1, 0),
-BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define arm64_system_filter_size (sizeof(arm64_system_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* system_filter = arm64_system_filter;
-static const size_t system_filter_size = arm64_system_filter_size;
-#define kFilterMaxSize (arm64_app_filter_size + 3 + 1 + 4 + 2)
-
-#elif GOARCH_arm
-#define PRIMARY_ARCH AUDIT_ARCH_ARM
-
-const struct sock_filter arm_app_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 146),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 240, 144, 0),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 54, 143, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 71, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 85, 35, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 45, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 26, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 10, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 8, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 136, 135),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 135, 134),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 134, 133),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 24, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 21, 132, 131),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 131, 130),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 128, 127),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 127, 126),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 125, 124),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 124, 123),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 63, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 55, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 52, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 119, 118),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 118, 117),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 117, 116),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 60, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 115, 114),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 61, 114, 113),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 75, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 66, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 111, 110),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 110, 109),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 77, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 108, 107),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 79, 107, 106),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 125, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 91, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 101, 100),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 100, 99),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 99, 98),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 104, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 97, 96),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 107, 96, 95),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 93, 92),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 92, 91),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 122, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 121, 90, 89),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 89, 88),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 140, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 84, 83),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 83, 82),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 82, 81),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 80, 79),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 79, 78),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 76, 75),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 75, 74),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 73, 72),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 72, 71),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 327, 35, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 219, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 211, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 207, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 205, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 203, 65, 64),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 206, 64, 63),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 210, 63, 62),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 61, 60),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 60, 59),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 241, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 57, 56),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 240, 56, 55),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 54, 53),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 53, 52),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 290, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 280, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 270, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 263, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 262, 48, 47),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 269, 47, 46),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 46, 45),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 286, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 44, 43),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 289, 43, 42),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 316, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 292, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 40, 39),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 298, 39, 38),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 319, 37, 36),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 326, 36, 35),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 403, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 369, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 348, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 345, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 340, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 339, 30, 29),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 344, 29, 28),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 347, 28, 27),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 350, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 349, 26, 25),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 367, 25, 24),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 380, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 373, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 370, 22, 21),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 378, 21, 20),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 397, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 394, 19, 18),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 398, 18, 17),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 438, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 434, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 420, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 417, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 415, 13, 12),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 418, 12, 11),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 425, 11, 10),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 436, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 435, 9, 8),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 437, 8, 7),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983042, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 440, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 439, 5, 4),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 441, 4, 3),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983045, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983043, 2, 1),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983046, 1, 0),
-BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define arm_app_filter_size (sizeof(arm_app_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* primary_app_filter = arm_app_filter;
-static const size_t primary_app_filter_size = arm_app_filter_size;
-
-const struct sock_filter arm_system_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 142),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 240, 140, 0),
-BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 54, 139, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 197, 69, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 91, 35, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 51, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 11, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 132, 131),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 131, 130),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 130, 129),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 26, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 128, 127),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 127, 126),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 38, 124, 123),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 42, 123, 122),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 45, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 121, 120),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 120, 119),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 74, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 64, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 60, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 115, 114),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 114, 113),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 113, 112),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 66, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 111, 110),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 110, 109),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 85, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 77, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 107, 106),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 106, 105),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 88, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 104, 103),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 103, 102),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 103, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 97, 96),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 96, 95),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 95, 94),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 107, 93, 92),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 92, 91),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 124, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 89, 88),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 88, 87),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 128, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 86, 85),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 85, 84),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 81, 80),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 80, 79),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 143, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 141, 78, 77),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 77, 76),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 74, 73),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 73, 72),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 71, 70),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 196, 70, 69),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 345, 35, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 270, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 63, 62),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 62, 61),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 61, 60),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 219, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 59, 58),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 58, 57),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 251, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 241, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 240, 55, 54),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 54, 53),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 252, 52, 51),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 269, 51, 50),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 317, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 290, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 286, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 280, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 46, 45),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 45, 44),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 289, 44, 43),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 292, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 42, 41),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 298, 41, 40),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 327, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 319, 38, 37),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 326, 37, 36),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 340, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 339, 35, 34),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 344, 34, 33),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 417, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 372, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 352, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 350, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 348, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 347, 28, 27),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 349, 27, 26),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 351, 26, 25),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 369, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 367, 24, 23),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 370, 23, 22),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 397, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 380, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 378, 20, 19),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 394, 19, 18),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 403, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 398, 17, 16),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 415, 16, 15),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 438, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 434, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 420, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 418, 12, 11),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 425, 11, 10),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 436, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 435, 9, 8),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 437, 8, 7),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983042, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 440, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 439, 5, 4),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 441, 4, 3),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983045, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983043, 2, 1),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983046, 1, 0),
-BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define arm_system_filter_size (sizeof(arm_system_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* system_filter = arm_system_filter;
-static const size_t system_filter_size = arm_system_filter_size;
-#define kFilterMaxSize (arm_app_filter_size + 3 + 1 + 4 + 2)
-#elif GOARCH_amd64
-#define PRIMARY_ARCH AUDIT_ARCH_X86_64
-
-const struct sock_filter x86_64_app_filter[] = {
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 0, 0, 108),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 202, 106, 0),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 16, 105, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 162, 53, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 104, 27, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 44, 13, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 32, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 17, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 8, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 6, 99, 98),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 16, 98, 97),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 24, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 21, 96, 95),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 29, 95, 94),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 38, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 35, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 33, 92, 91),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 37, 91, 90),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 43, 90, 89),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 91, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 72, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 58, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 57, 86, 85),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 64, 85, 84),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 89, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 82, 83, 82),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 90, 82, 81),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 95, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 93, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 92, 79, 78),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 94, 78, 77),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 103, 77, 76),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 135, 13, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 117, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 112, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 107, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 105, 72, 71),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 111, 71, 70),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 115, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 113, 69, 68),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 116, 68, 67),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 124, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 120, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 119, 65, 64),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 122, 64, 63),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 132, 63, 62),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 155, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 140, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 137, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 136, 59, 58),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 139, 58, 57),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 153, 57, 56),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 160, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 157, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 156, 54, 53),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 159, 53, 52),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 161, 52, 51),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 262, 25, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 228, 13, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 206, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 186, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 179, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 163, 46, 45),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 180, 45, 44),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 203, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 201, 43, 42),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 205, 42, 41),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 221, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 217, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 211, 39, 38),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 220, 38, 37),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 227, 37, 36),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 251, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 247, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 233, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 232, 33, 32),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 235, 32, 31),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 248, 31, 30),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 257, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 254, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 253, 28, 27),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 256, 27, 26),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 261, 26, 25),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 321, 13, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 302, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 283, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 280, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 279, 21, 20),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 282, 20, 19),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 285, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 284, 18, 17),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 300, 17, 16),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 314, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 306, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 303, 14, 13),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 312, 13, 12),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 320, 12, 11),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 434, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 424, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 332, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 329, 8, 7),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 333, 7, 6),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 425, 6, 5),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 440, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 438, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 437, 3, 2),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 439, 2, 1),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 441, 1, 0),
- BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define x86_64_app_filter_size (sizeof(x86_64_app_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* primary_app_filter = x86_64_app_filter;
-static const size_t primary_app_filter_size = x86_64_app_filter_size;
-
-const struct sock_filter x86_64_system_filter[] = {
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 0, 0, 98),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 202, 96, 0),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 16, 95, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 186, 47, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 91, 23, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 38, 11, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 24, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 17, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 8, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 6, 89, 88),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 16, 88, 87),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 21, 87, 86),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 35, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 32, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 29, 84, 83),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 33, 83, 82),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 37, 82, 81),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 72, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 58, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 44, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 43, 78, 77),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 57, 77, 76),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 64, 76, 75),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 89, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 79, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 78, 73, 72),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 82, 72, 71),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 90, 71, 70),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 140, 11, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 112, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 95, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 93, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 92, 66, 65),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 94, 65, 64),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 111, 64, 63),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 137, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 135, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 132, 61, 60),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 136, 60, 59),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 139, 59, 58),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 169, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 157, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 155, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 153, 55, 54),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 156, 54, 53),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 167, 53, 52),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 179, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 175, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 172, 50, 49),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 177, 49, 48),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 180, 48, 47),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 280, 23, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 247, 11, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 217, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 206, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 203, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 201, 42, 41),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 205, 41, 40),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 211, 40, 39),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 233, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 221, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 220, 37, 36),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 232, 36, 35),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 235, 35, 34),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 257, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 254, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 251, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 248, 31, 30),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 253, 30, 29),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 256, 29, 28),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 265, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 262, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 261, 26, 25),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 264, 25, 24),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 279, 24, 23),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 321, 11, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 302, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 285, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 283, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 282, 19, 18),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 284, 18, 17),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 300, 17, 16),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 314, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 305, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 303, 14, 13),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 312, 13, 12),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 320, 12, 11),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 434, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 424, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 332, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 329, 8, 7),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 333, 7, 6),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 425, 6, 5),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 440, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 438, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 437, 3, 2),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 439, 2, 1),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 441, 1, 0),
- BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define x86_64_system_filter_size (sizeof(x86_64_system_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* system_filter = x86_64_system_filter;
-static const size_t system_filter_size = x86_64_system_filter_size;
-#define kFilterMaxSize (x86_64_app_filter_size + 3 + 1 + 4 + 2)
-
-#elif GOARCH_386
-#define PRIMARY_ARCH AUDIT_ARCH_I386
-
-const struct sock_filter x86_app_filter[] = {
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 0, 0, 134),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 240, 132, 0),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 54, 131, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 172, 65, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 85, 33, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 45, 17, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 26, 9, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 19, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 10, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 8, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 7, 124, 123),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 9, 123, 122),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 13, 122, 121),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 24, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 21, 120, 119),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 25, 119, 118),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 36, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 33, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 27, 116, 115),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 34, 115, 114),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 41, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 40, 113, 112),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 44, 112, 111),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 63, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 57, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 55, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 46, 108, 107),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 56, 107, 106),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 60, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 58, 105, 104),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 61, 104, 103),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 75, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 66, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 65, 101, 100),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 68, 100, 99),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 77, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 76, 98, 97),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 79, 97, 96),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 118, 15, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 102, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 94, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 90, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 86, 92, 91),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 93, 91, 90),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 96, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 95, 89, 88),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 98, 88, 87),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 114, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 104, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 103, 85, 84),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 107, 84, 83),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 116, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 115, 82, 81),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 117, 81, 80),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 136, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 125, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 122, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 121, 77, 76),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 123, 76, 75),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 131, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 126, 74, 73),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 134, 73, 72),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 150, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 140, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 137, 70, 69),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 149, 69, 68),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 168, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 164, 67, 66),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 169, 66, 65),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 295, 33, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 241, 17, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 207, 9, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 199, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 190, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 183, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 182, 59, 58),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 188, 58, 57),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 198, 57, 56),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 205, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 203, 55, 54),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 206, 54, 53),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 218, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 211, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 210, 51, 50),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 212, 50, 49),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 224, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 222, 48, 47),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 240, 47, 46),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 265, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 252, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 245, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 244, 43, 42),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 250, 42, 41),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 254, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 253, 40, 39),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 264, 39, 38),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 284, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 272, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 271, 36, 35),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 273, 35, 34),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 291, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 285, 33, 32),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 294, 32, 31),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 374, 15, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 340, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 318, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 300, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 299, 27, 26),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 317, 26, 25),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 322, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 321, 24, 23),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 337, 23, 22),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 346, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 344, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 341, 20, 19),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 345, 19, 18),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 351, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 349, 17, 16),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 359, 16, 15),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 421, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 403, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 383, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 380, 12, 11),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 384, 11, 10),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 417, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 415, 9, 8),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 418, 8, 7),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 438, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 434, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 425, 5, 4),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 437, 4, 3),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 440, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 439, 2, 1),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 441, 1, 0),
- BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define x86_app_filter_size (sizeof(x86_app_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* primary_app_filter = x86_app_filter;
-static const size_t primary_app_filter_size = x86_app_filter_size;
-
-const struct sock_filter x86_system_filter[] = {
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 0, 0, 134),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 240, 132, 0),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 54, 131, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 183, 65, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 88, 33, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 51, 17, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 36, 9, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 19, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 11, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 3, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 2, 124, 123),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 7, 123, 122),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 13, 122, 121),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 26, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 22, 120, 119),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 27, 119, 118),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 43, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 41, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 38, 116, 115),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 42, 115, 114),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 45, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 44, 113, 112),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 46, 112, 111),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 66, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 60, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 57, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 53, 108, 107),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 58, 107, 106),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 64, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 62, 105, 104),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 65, 104, 103),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 77, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 74, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 68, 101, 100),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 76, 100, 99),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 85, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 80, 98, 97),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 86, 97, 96),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 124, 15, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 102, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 94, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 91, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 89, 92, 91),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 93, 91, 90),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 96, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 95, 89, 88),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 98, 88, 87),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 116, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 114, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 107, 85, 84),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 115, 84, 83),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 118, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 117, 82, 81),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 123, 81, 80),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 140, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 131, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 128, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 126, 77, 76),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 130, 76, 75),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 136, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 134, 74, 73),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 137, 73, 72),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 150, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 143, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 141, 70, 69),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 149, 69, 68),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 172, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 164, 67, 66),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 182, 66, 65),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 303, 33, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 252, 17, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 218, 9, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 199, 5, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 197, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 190, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 188, 59, 58),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 196, 58, 57),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 198, 57, 56),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 213, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 212, 55, 54),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 217, 54, 53),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 241, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 224, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 222, 51, 50),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 240, 50, 49),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 245, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 244, 48, 47),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 250, 47, 46),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 284, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 258, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 255, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 253, 43, 42),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 256, 42, 41),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 272, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 271, 40, 39),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 273, 39, 38),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 295, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 292, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 285, 36, 35),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 294, 35, 34),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 300, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 299, 33, 32),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 302, 32, 31),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 374, 15, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 340, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 322, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 318, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 317, 27, 26),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 321, 26, 25),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 324, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 323, 24, 23),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 337, 23, 22),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 346, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 343, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 341, 20, 19),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 345, 19, 18),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 351, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 349, 17, 16),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 359, 16, 15),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 421, 7, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 403, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 383, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 380, 12, 11),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 384, 11, 10),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 417, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 415, 9, 8),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 418, 8, 7),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 438, 3, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 434, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 425, 5, 4),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 437, 4, 3),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 440, 1, 0),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 439, 2, 1),
- BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 441, 1, 0),
- BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-};
-
-#define x86_system_filter_size (sizeof(x86_system_filter) / sizeof(struct sock_filter))
-
-static const struct sock_filter* system_filter = x86_system_filter;
-static const size_t system_filter_size = x86_system_filter_size;
-#define kFilterMaxSize (x86_app_filter_size + 3 + 1 + 4 + 2)
-
-#else
-#error No architecture was defined!
-#endif
-
-#define syscall_nr (offsetof(struct seccomp_data, nr))
-#define arch_nr (offsetof(struct seccomp_data, arch))
-
-typedef struct Filter_t {
- struct sock_filter data[kFilterMaxSize];
- size_t count;
-} Filter;
-
-static void push_back(Filter* filter_array, struct sock_filter filter)
-{
- if (filter_array->count == kFilterMaxSize)
- failmsg("can't add another syscall to seccomp filter", "count=%zu", filter_array->count);
- filter_array->data[filter_array->count++] = filter;
-}
-
-static void Disallow(Filter* f)
-{
- struct sock_filter filter = BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP);
- push_back(f, filter);
-}
-
-static void ExamineSyscall(Filter* f)
-{
- struct sock_filter filter = BPF_STMT(BPF_LD | BPF_W | BPF_ABS, syscall_nr);
- push_back(f, filter);
-}
-
-static void ValidateArchitecture(Filter* f)
-{
- struct sock_filter filter1 = BPF_STMT(BPF_LD | BPF_W | BPF_ABS, arch_nr);
- struct sock_filter filter2 = BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, PRIMARY_ARCH, 1, 0);
- push_back(f, filter1);
- push_back(f, filter2);
- Disallow(f);
-}
-static void install_filter(const Filter* f)
-{
- struct sock_fprog prog = {
- (unsigned short)f->count,
- (struct sock_filter*)&f->data[0],
- };
- if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
- failmsg("could not set seccomp filter", "size=%zu", f->count);
-}
-static void set_seccomp_filter(const struct sock_filter* filter, size_t size)
-{
- Filter f;
- f.count = 0;
- ValidateArchitecture(&f);
- ExamineSyscall(&f);
-
- for (size_t i = 0; i < size; ++i)
- push_back(&f, filter[i]);
- Disallow(&f);
- install_filter(&f);
-}
-
-enum {
- SCFS_RestrictedApp,
- SCFS_SystemAccount
-};
-
-static void set_app_seccomp_filter(int account)
-{
- if (account == SCFS_SystemAccount) {
- set_seccomp_filter(system_filter, system_filter_size);
- } else {
- set_seccomp_filter(primary_app_filter, primary_app_filter_size);
- }
-}
-
-
-#if GOARCH_amd64 || GOARCH_386
-inline int mkdir(const char* path, mode_t mode)
-{
- return mkdirat(AT_FDCWD, path, mode);
-}
-
-inline int rmdir(const char* path)
-{
- return unlinkat(AT_FDCWD, path, AT_REMOVEDIR);
-}
-
-inline int symlink(const char* old_path, const char* new_path)
-{
- return symlinkat(old_path, AT_FDCWD, new_path);
-}
-#endif
-
-#endif
-#include <fcntl.h>
-#include <grp.h>
-#include <sys/xattr.h>
-
-#define AID_NET_BT_ADMIN 3001
-#define AID_NET_BT 3002
-#define AID_INET 3003
-#define AID_EVERYBODY 9997
-#define AID_APP 10000
-
-#define UNTRUSTED_APP_UID (AID_APP + 999)
-#define UNTRUSTED_APP_GID (AID_APP + 999)
-
-#define SYSTEM_UID 1000
-#define SYSTEM_GID 1000
-
-const char* const SELINUX_CONTEXT_UNTRUSTED_APP = "u:r:untrusted_app:s0:c512,c768";
-const char* const SELINUX_LABEL_APP_DATA_FILE = "u:object_r:app_data_file:s0:c512,c768";
-const char* const SELINUX_CONTEXT_FILE = "/proc/thread-self/attr/current";
-const char* const SELINUX_XATTR_NAME = "security.selinux";
-
-const gid_t UNTRUSTED_APP_GROUPS[] = {UNTRUSTED_APP_GID, AID_NET_BT_ADMIN, AID_NET_BT, AID_INET, AID_EVERYBODY};
-const size_t UNTRUSTED_APP_NUM_GROUPS = sizeof(UNTRUSTED_APP_GROUPS) / sizeof(UNTRUSTED_APP_GROUPS[0]);
-
-const gid_t SYSTEM_GROUPS[] = {SYSTEM_GID, AID_NET_BT_ADMIN, AID_NET_BT, AID_INET, AID_EVERYBODY};
-const size_t SYSTEM_NUM_GROUPS = sizeof(SYSTEM_GROUPS) / sizeof(SYSTEM_GROUPS[0]);
-static void getcon(char* context, size_t context_size)
-{
- int fd = open(SELINUX_CONTEXT_FILE, O_RDONLY);
- if (fd < 0)
- fail("getcon: couldn't open context file");
-
- ssize_t nread = read(fd, context, context_size);
-
- close(fd);
-
- if (nread <= 0)
- fail("getcon: failed to read context file");
- if (context[nread - 1] == '\n')
- context[nread - 1] = '\0';
-}
-static void setcon(const char* context)
-{
- char new_context[512];
- int fd = open(SELINUX_CONTEXT_FILE, O_WRONLY);
-
- if (fd < 0)
- fail("setcon: could not open context file");
-
- ssize_t bytes_written = write(fd, context, strlen(context));
- close(fd);
-
- if (bytes_written != (ssize_t)strlen(context))
- failmsg("setcon: could not write entire context", "wrote=%zi, expected=%zu", bytes_written, strlen(context));
- getcon(new_context, sizeof(new_context));
-
- if (strcmp(context, new_context) != 0)
- failmsg("setcon: failed to change", "want=%s, context=%s", context, new_context);
-}
-static void setfilecon(const char* path, const char* context)
-{
- char new_context[512];
-
- if (setxattr(path, SELINUX_XATTR_NAME, context, strlen(context) + 1, 0) != 0)
- fail("setfilecon: setxattr failed");
- if (getxattr(path, SELINUX_XATTR_NAME, new_context, sizeof(new_context)) < 0)
- fail("setfilecon: getxattr failed");
- if (strcmp(context, new_context) != 0)
- failmsg("setfilecon: could not set context", "want=%s, got=%s", context, new_context);
-}
-
-#define SYZ_HAVE_SANDBOX_ANDROID 1
-
-static int do_sandbox_android(uint64 sandbox_arg)
-{
- setup_common();
-#if SYZ_EXECUTOR || SYZ_VHCI_INJECTION
- initialize_vhci();
-#endif
- sandbox_common();
- drop_caps();
-
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices_init();
-#endif
- if (unshare(CLONE_NEWNET)) {
- debug("unshare(CLONE_NEWNET): %d\n", errno);
- }
- write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535");
-#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI
- initialize_devlink_pci();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- initialize_tun();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_DEVICES
- initialize_netdevices();
-#endif
- uid_t uid = UNTRUSTED_APP_UID;
- size_t num_groups = UNTRUSTED_APP_NUM_GROUPS;
- const gid_t* groups = UNTRUSTED_APP_GROUPS;
- gid_t gid = UNTRUSTED_APP_GID;
- debug("executor received sandbox_arg=%llu\n", sandbox_arg);
- if (sandbox_arg == 1) {
- uid = SYSTEM_UID;
- num_groups = SYSTEM_NUM_GROUPS;
- groups = SYSTEM_GROUPS;
- gid = SYSTEM_GID;
-
- debug("fuzzing under SYSTEM account\n");
- }
- if (chown(".", uid, uid) != 0)
- failmsg("do_sandbox_android: chmod failed", "sandbox_arg=%llu", sandbox_arg);
-
- if (setgroups(num_groups, groups) != 0)
- failmsg("do_sandbox_android: setgroups failed", "sandbox_arg=%llu", sandbox_arg);
-
- if (setresgid(gid, gid, gid) != 0)
- failmsg("do_sandbox_android: setresgid failed", "sandbox_arg=%llu", sandbox_arg);
-
- setup_binderfs();
-
-#if GOARCH_arm || GOARCH_arm64 || GOARCH_386 || GOARCH_amd64
- int account = SCFS_RestrictedApp;
- if (sandbox_arg == 1)
- account = SCFS_SystemAccount;
- set_app_seccomp_filter(account);
-#endif
-
- if (setresuid(uid, uid, uid) != 0)
- failmsg("do_sandbox_android: setresuid failed", "sandbox_arg=%llu", sandbox_arg);
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
-
- setfilecon(".", SELINUX_LABEL_APP_DATA_FILE);
- if (uid == UNTRUSTED_APP_UID)
- setcon(SELINUX_CONTEXT_UNTRUSTED_APP);
-
- loop();
- doexit(1);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_USE_TMP_DIR
-#include <dirent.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-
-#define FS_IOC_SETFLAGS _IOW('f', 2, long)
-static void remove_dir(const char* dir)
-{
- int iter = 0;
- DIR* dp = 0;
-retry:
-#if SYZ_EXECUTOR || !SYZ_SANDBOX_ANDROID
- const int umount_flags = MNT_FORCE | UMOUNT_NOFOLLOW;
-#if SYZ_EXECUTOR
- if (!flag_sandbox_android)
-#endif
- while (umount2(dir, umount_flags) == 0) {
- debug("umount(%s)\n", dir);
- }
-#endif
- dp = opendir(dir);
- if (dp == NULL) {
- if (errno == EMFILE) {
- exitf("opendir(%s) failed due to NOFILE, exiting", dir);
- }
- exitf("opendir(%s) failed", dir);
- }
- struct dirent* ep = 0;
- 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);
-#if SYZ_EXECUTOR || !SYZ_SANDBOX_ANDROID
-#if SYZ_EXECUTOR
- if (!flag_sandbox_android)
-#endif
- while (umount2(filename, umount_flags) == 0) {
- debug("umount(%s)\n", filename);
- }
-#endif
- 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++) {
- if (unlink(filename) == 0)
- break;
- if (errno == EPERM) {
- int fd = open(filename, O_RDONLY);
- if (fd != -1) {
- long flags = 0;
- if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
- debug("reset FS_XFLAG_IMMUTABLE\n");
- }
- close(fd);
- continue;
- }
- }
- if (errno == EROFS) {
- debug("ignoring EROFS\n");
- break;
- }
- if (errno != EBUSY || i > 100)
- exitf("unlink(%s) failed", filename);
-#if SYZ_EXECUTOR || !SYZ_SANDBOX_ANDROID
-#if SYZ_EXECUTOR
- if (!flag_sandbox_android) {
-#endif
- debug("umount(%s)\n", filename);
- if (umount2(filename, umount_flags))
- exitf("umount(%s) failed", filename);
-#if SYZ_EXECUTOR
- }
-#endif
-#endif
- }
- }
- closedir(dp);
- for (int i = 0;; i++) {
- if (rmdir(dir) == 0)
- break;
- if (i < 100) {
- if (errno == EPERM) {
- int fd = open(dir, O_RDONLY);
- if (fd != -1) {
- long flags = 0;
- if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
- debug("reset FS_XFLAG_IMMUTABLE\n");
- }
- close(fd);
- continue;
- }
- }
- if (errno == EROFS) {
- debug("ignoring EROFS\n");
- break;
- }
- if (errno == EBUSY) {
-#if SYZ_EXECUTOR || !SYZ_SANDBOX_ANDROID
-#if SYZ_EXECUTOR
- if (!flag_sandbox_android) {
-#endif
- debug("umount(%s)\n", dir);
- if (umount2(dir, umount_flags))
- exitf("umount(%s) failed", dir);
-#if SYZ_EXECUTOR
- }
-#endif
-#endif
- continue;
- }
- if (errno == ENOTEMPTY) {
- if (iter < 100) {
- iter++;
- goto retry;
- }
- }
- }
- exitf("rmdir(%s) failed", dir);
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_FAULT
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static int inject_fault(int nth)
-{
- int fd;
- fd = open("/proc/thread-self/fail-nth", O_RDWR);
- if (fd == -1)
- exitf("failed to open /proc/thread-self/fail-nth");
- char buf[16];
- sprintf(buf, "%d", nth);
- if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf))
- exitf("failed to write /proc/thread-self/fail-nth");
- return fd;
-}
-#endif
-
-#if SYZ_EXECUTOR
-static int fault_injected(int fail_fd)
-{
- char buf[16];
- int n = read(fail_fd, buf, sizeof(buf) - 1);
- if (n <= 0)
- exitf("failed to read /proc/thread-self/fail-nth");
- int res = n == 2 && buf[0] == '0' && buf[1] == '\n';
- buf[0] = '0';
- if (write(fail_fd, buf, 1) != 1)
- exitf("failed to write /proc/thread-self/fail-nth");
- close(fail_fd);
- return res;
-}
-#endif
-
-#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-static void kill_and_wait(int pid, int* status)
-{
- kill(-pid, SIGKILL);
- kill(pid, SIGKILL);
- for (int i = 0; i < 100; i++) {
- if (waitpid(-1, status, WNOHANG | __WALL) == pid)
- return;
- usleep(1000);
- }
- debug("kill is not working\n");
- DIR* dir = opendir("/sys/fs/fuse/connections");
- if (dir) {
- for (;;) {
- struct dirent* ent = readdir(dir);
- if (!ent)
- break;
- if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
- continue;
- char abort[300];
- snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name);
- int fd = open(abort, O_WRONLY);
- if (fd == -1) {
- debug("failed to open %s: %d\n", abort, errno);
- continue;
- }
- debug("aborting fuse conn %s\n", ent->d_name);
- if (write(fd, abort, 1) < 0) {
- debug("failed to abort: %d\n", errno);
- }
- close(fd);
- }
- closedir(dir);
- } else {
- debug("failed to open /sys/fs/fuse/connections: %d\n", errno);
- }
- while (waitpid(-1, status, __WALL) != pid) {
- }
-}
-#endif
-
-#if (SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_CGROUPS || SYZ_NET_RESET)) && SYZ_EXECUTOR_USES_FORK_SERVER
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#define SYZ_HAVE_SETUP_LOOP 1
-static void setup_loop()
-{
-#if SYZ_EXECUTOR || SYZ_CGROUPS
- setup_cgroups_loop();
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_RESET
- checkpoint_net_namespace();
-#endif
-}
-#endif
-
-#if (SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_NET_RESET || __NR_syz_mount_image || __NR_syz_read_part_table)) && SYZ_EXECUTOR_USES_FORK_SERVER
-#define SYZ_HAVE_RESET_LOOP 1
-static void reset_loop()
-{
-#if SYZ_EXECUTOR || __NR_syz_mount_image || __NR_syz_read_part_table
- char buf[64];
- snprintf(buf, sizeof(buf), "/dev/loop%llu", procid);
- int loopfd = open(buf, O_RDWR);
- if (loopfd != -1) {
- ioctl(loopfd, LOOP_CLR_FD, 0);
- close(loopfd);
- }
-#endif
-#if SYZ_EXECUTOR || SYZ_NET_RESET
- reset_net_namespace();
-#endif
-}
-#endif
-
-#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#define SYZ_HAVE_SETUP_TEST 1
-static void setup_test()
-{
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setpgrp();
-#if SYZ_EXECUTOR || SYZ_CGROUPS
- setup_cgroups_test();
-#endif
- write_file("/proc/self/oom_score_adj", "1000");
-#if SYZ_EXECUTOR || SYZ_NET_INJECTION
- flush_tun();
-#endif
-#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
- if (symlink("/dev/binderfs", "./binderfs")) {
- debug("symlink(/dev/binderfs, ./binderfs) failed: %d", errno);
- }
-#endif
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_CLOSE_FDS
-#define SYZ_HAVE_CLOSE_FDS 1
-static void close_fds()
-{
-#if SYZ_EXECUTOR
- if (!flag_close_fds)
- return;
-#endif
- for (int fd = 3; fd < MAX_FDS; fd++)
- close(fd);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_FAULT
-#include <errno.h>
-
-static void setup_fault()
-{
- int fd = open("/proc/self/make-it-fail", O_WRONLY);
- if (fd == -1)
- fail("CONFIG_FAULT_INJECTION is not enabled");
- close(fd);
-
- fd = open("/proc/thread-self/fail-nth", O_WRONLY);
- if (fd == -1)
- fail("kernel does not have systematic fault injection support");
- close(fd);
-
- static struct {
- const char* file;
- const char* val;
- bool fatal;
- } files[] = {
- {"/sys/kernel/debug/failslab/ignore-gfp-wait", "N", true},
- {"/sys/kernel/debug/fail_futex/ignore-private", "N", false},
- {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem", "N", false},
- {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-wait", "N", false},
- {"/sys/kernel/debug/fail_page_alloc/min-order", "0", false},
- };
- unsigned i;
- for (i = 0; i < sizeof(files) / sizeof(files[0]); i++) {
- if (!write_file(files[i].file, files[i].val)) {
- debug("failed to write %s: %d\n", files[i].file, errno);
- if (files[i].fatal)
- failmsg("failed to write fault injection file", "file=%s", files[i].file);
- }
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_LEAK
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#define KMEMLEAK_FILE "/sys/kernel/debug/kmemleak"
-
-static void setup_leak()
-{
- if (!write_file(KMEMLEAK_FILE, "scan=off")) {
- if (errno == EBUSY)
- fail("KMEMLEAK disabled: increase CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE"
- " or unset CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF");
- fail("failed to write(kmemleak, \"scan=off\")");
- }
- if (!write_file(KMEMLEAK_FILE, "scan"))
- fail("failed to write(kmemleak, \"scan\")");
- sleep(5);
- if (!write_file(KMEMLEAK_FILE, "scan"))
- fail("failed to write(kmemleak, \"scan\")");
- if (!write_file(KMEMLEAK_FILE, "clear"))
- fail("failed to write(kmemleak, \"clear\")");
-}
-
-#define SYZ_HAVE_LEAK_CHECK 1
-#if SYZ_EXECUTOR
-static void check_leaks(char** frames, int nframes)
-#else
-static void check_leaks(void)
-#endif
-{
- int fd = open(KMEMLEAK_FILE, O_RDWR);
- if (fd == -1)
- fail("failed to open(kmemleak)");
- uint64 start = current_time_ms();
- if (write(fd, "scan", 4) != 4)
- fail("failed to write(kmemleak, \"scan\")");
- sleep(1);
- while (current_time_ms() - start < 4 * 1000)
- sleep(1);
- if (write(fd, "scan", 4) != 4)
- fail("failed to write(kmemleak, \"scan\")");
- static char buf[128 << 10];
- ssize_t n = read(fd, buf, sizeof(buf) - 1);
- if (n < 0)
- fail("failed to read(kmemleak)");
- int nleaks = 0;
- if (n != 0) {
- sleep(1);
- if (write(fd, "scan", 4) != 4)
- fail("failed to write(kmemleak, \"scan\")");
- if (lseek(fd, 0, SEEK_SET) < 0)
- fail("failed to lseek(kmemleak)");
- n = read(fd, buf, sizeof(buf) - 1);
- if (n < 0)
- fail("failed to read(kmemleak)");
- buf[n] = 0;
- char* pos = buf;
- char* end = buf + n;
- while (pos < end) {
- char* next = strstr(pos + 1, "unreferenced object");
- if (!next)
- next = end;
- char prev = *next;
- *next = 0;
-#if SYZ_EXECUTOR
- int f;
- for (f = 0; f < nframes; f++) {
- if (strstr(pos, frames[f]))
- break;
- }
- if (f != nframes) {
- *next = prev;
- pos = next;
- continue;
- }
-#endif
- fprintf(stderr, "BUG: memory leak\n%s\n", pos);
- *next = prev;
- pos = next;
- nleaks++;
- }
- }
- if (write(fd, "clear", 5) != 5)
- fail("failed to write(kmemleak, \"clear\")");
- close(fd);
- if (nleaks)
- doexit(1);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_BINFMT_MISC
-#include <fcntl.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-static void setup_binfmt_misc()
-{
- if (mount(0, "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, 0)) {
- debug("mount(binfmt_misc) failed: %d\n", errno);
- }
- if (!write_file("/proc/sys/fs/binfmt_misc/register", ":syz0:M:0:\x01::./file0:") ||
- !write_file("/proc/sys/fs/binfmt_misc/register", ":syz1:M:1:\x02::./file0:POC"))
- fail("write(/proc/sys/fs/binfmt_misc/register) failed");
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_KCSAN
-#define KCSAN_DEBUGFS_FILE "/sys/kernel/debug/kcsan"
-
-static void setup_kcsan()
-{
- if (!write_file(KCSAN_DEBUGFS_FILE, "on"))
- fail("write(/sys/kernel/debug/kcsan, on) failed");
-}
-
-#if SYZ_EXECUTOR
-static void setup_kcsan_filterlist(char** frames, int nframes, bool suppress)
-{
- int fd = open(KCSAN_DEBUGFS_FILE, O_WRONLY);
- if (fd == -1)
- fail("failed to open kcsan debugfs file");
-
- printf("%s KCSAN reports in functions: ",
- suppress ? "suppressing" : "only showing");
- if (!suppress)
- dprintf(fd, "whitelist\n");
- for (int i = 0; i < nframes; ++i) {
- printf("'%s' ", frames[i]);
- dprintf(fd, "!%s\n", frames[i]);
- }
- printf("\n");
-
- close(fd);
-}
-
-#define SYZ_HAVE_KCSAN 1
-#endif
-#endif
-
-#if SYZ_EXECUTOR || SYZ_USB
-static void setup_usb()
-{
- if (chmod("/dev/raw-gadget", 0666))
- fail("failed to chmod /dev/raw-gadget");
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SYSCTL
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-static void setup_sysctl()
-{
- char mypid[32];
- snprintf(mypid, sizeof(mypid), "%d", getpid());
- struct {
- const char* name;
- const char* data;
- } files[] = {
-#if GOARCH_amd64 || GOARCH_386
- {"/sys/kernel/debug/x86/nmi_longest_ns", "10000000000"},
-#endif
- {"/proc/sys/kernel/hung_task_check_interval_secs", "20"},
- {"/proc/sys/net/core/bpf_jit_kallsyms", "1"},
- {"/proc/sys/net/core/bpf_jit_harden", "0"},
- {"/proc/sys/kernel/kptr_restrict", "0"},
- {"/proc/sys/kernel/softlockup_all_cpu_backtrace", "1"},
- {"/proc/sys/fs/mount-max", "100"},
- {"/proc/sys/vm/oom_dump_tasks", "0"},
- {"/proc/sys/debug/exception-trace", "0"},
- {"/proc/sys/kernel/printk", "7 4 1 3"},
- {"/proc/sys/kernel/keys/gc_delay", "1"},
- {"/proc/sys/vm/oom_kill_allocating_task", "1"},
- {"/proc/sys/kernel/ctrl-alt-del", "0"},
- {"/proc/sys/kernel/cad_pid", mypid},
- };
- for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); i++) {
- if (!write_file(files[i].name, files[i].data))
- printf("write to %s failed: %s\n", files[i].name, strerror(errno));
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_802154
-#include <net/if.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#define NL802154_CMD_SET_SHORT_ADDR 11
-#define NL802154_ATTR_IFINDEX 3
-#define NL802154_ATTR_SHORT_ADDR 10
-
-static void setup_802154()
-{
- int sock_route = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (sock_route == -1)
- fail("socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) failed");
- int sock_generic = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock_generic < 0)
- fail("socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC) failed");
- int nl802154_family_id = netlink_query_family_id(&nlmsg, sock_generic, "nl802154", true);
- for (int i = 0; i < 2; i++) {
- char devname[] = "wpan0";
- devname[strlen(devname) - 1] += i;
- uint64 hwaddr = 0xaaaaaaaaaaaa0002 + (i << 8);
- uint16 shortaddr = 0xaaa0 + i;
- int ifindex = if_nametoindex(devname);
- struct genlmsghdr genlhdr;
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = NL802154_CMD_SET_SHORT_ADDR;
- netlink_init(&nlmsg, nl802154_family_id, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(&nlmsg, NL802154_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
- netlink_attr(&nlmsg, NL802154_ATTR_SHORT_ADDR, &shortaddr, sizeof(shortaddr));
- int err = netlink_send(&nlmsg, sock_generic);
- if (err < 0)
- fail("NL802154_CMD_SET_SHORT_ADDR failed");
- netlink_device_change(&nlmsg, sock_route, devname, true, 0, &hwaddr, sizeof(hwaddr), 0);
- if (i == 0) {
- netlink_add_device_impl(&nlmsg, "lowpan", "lowpan0", false);
- netlink_done(&nlmsg);
- netlink_attr(&nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
- int err = netlink_send(&nlmsg, sock_route);
- if (err < 0)
- fail("netlink: adding device lowpan0 type lowpan link wpan0");
- }
- }
- close(sock_route);
- close(sock_generic);
-}
-#endif
-
-#if GOARCH_s390x
-#include <sys/mman.h>
-#define CAST(f) ({void* p = (void*)f; p; })
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_fuse_handle_req
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#define FUSE_MIN_READ_BUFFER 8192
-enum fuse_opcode {
- FUSE_LOOKUP = 1,
- FUSE_FORGET = 2,
- FUSE_GETATTR = 3,
- FUSE_SETATTR = 4,
- FUSE_READLINK = 5,
- FUSE_SYMLINK = 6,
- FUSE_MKNOD = 8,
- FUSE_MKDIR = 9,
- FUSE_UNLINK = 10,
- FUSE_RMDIR = 11,
- FUSE_RENAME = 12,
- FUSE_LINK = 13,
- FUSE_OPEN = 14,
- FUSE_READ = 15,
- FUSE_WRITE = 16,
- FUSE_STATFS = 17,
- FUSE_RELEASE = 18,
- FUSE_FSYNC = 20,
- FUSE_SETXATTR = 21,
- FUSE_GETXATTR = 22,
- FUSE_LISTXATTR = 23,
- FUSE_REMOVEXATTR = 24,
- FUSE_FLUSH = 25,
- FUSE_INIT = 26,
- FUSE_OPENDIR = 27,
- FUSE_READDIR = 28,
- FUSE_RELEASEDIR = 29,
- FUSE_FSYNCDIR = 30,
- FUSE_GETLK = 31,
- FUSE_SETLK = 32,
- FUSE_SETLKW = 33,
- FUSE_ACCESS = 34,
- FUSE_CREATE = 35,
- FUSE_INTERRUPT = 36,
- FUSE_BMAP = 37,
- FUSE_DESTROY = 38,
- FUSE_IOCTL = 39,
- FUSE_POLL = 40,
- FUSE_NOTIFY_REPLY = 41,
- FUSE_BATCH_FORGET = 42,
- FUSE_FALLOCATE = 43,
- FUSE_READDIRPLUS = 44,
- FUSE_RENAME2 = 45,
- FUSE_LSEEK = 46,
- FUSE_COPY_FILE_RANGE = 47,
- FUSE_SETUPMAPPING = 48,
- FUSE_REMOVEMAPPING = 49,
- CUSE_INIT = 4096,
- CUSE_INIT_BSWAP_RESERVED = 1048576,
- FUSE_INIT_BSWAP_RESERVED = 436207616,
-};
-struct fuse_in_header {
- uint32 len;
- uint32 opcode;
- uint64 unique;
- uint64 nodeid;
- uint32 uid;
- uint32 gid;
- uint32 pid;
- uint32 padding;
-};
-struct fuse_out_header {
- uint32 len;
- uint32 error;
- uint64 unique;
-};
-struct syz_fuse_req_out {
- struct fuse_out_header* init;
- struct fuse_out_header* lseek;
- struct fuse_out_header* bmap;
- struct fuse_out_header* poll;
- struct fuse_out_header* getxattr;
- struct fuse_out_header* lk;
- struct fuse_out_header* statfs;
- struct fuse_out_header* write;
- struct fuse_out_header* read;
- struct fuse_out_header* open;
- struct fuse_out_header* attr;
- struct fuse_out_header* entry;
- struct fuse_out_header* dirent;
- struct fuse_out_header* direntplus;
- struct fuse_out_header* create_open;
- struct fuse_out_header* ioctl;
-};
-static int fuse_send_response(int fd,
- const struct fuse_in_header* in_hdr,
- struct fuse_out_header* out_hdr)
-{
- if (!out_hdr) {
- debug("fuse_send_response: received a NULL out_hdr\n");
- return -1;
- }
-
- out_hdr->unique = in_hdr->unique;
- if (write(fd, out_hdr, out_hdr->len) == -1) {
- debug("fuse_send_response > write failed: %d\n", errno);
- return -1;
- }
-
- return 0;
-}
-static volatile long syz_fuse_handle_req(volatile long a0,
- volatile long a1,
- volatile long a2,
- volatile long a3)
-{
- struct syz_fuse_req_out* req_out = (struct syz_fuse_req_out*)a3;
- struct fuse_out_header* out_hdr = NULL;
- char* buf = (char*)a1;
- int buf_len = (int)a2;
- int fd = (int)a0;
-
- if (!req_out) {
- debug("syz_fuse_handle_req: received a NULL syz_fuse_req_out\n");
- return -1;
- }
- if (buf_len < FUSE_MIN_READ_BUFFER) {
- debug("FUSE requires the read buffer to be at least %u\n", FUSE_MIN_READ_BUFFER);
- return -1;
- }
-
- int ret = read(fd, buf, buf_len);
- if (ret == -1) {
- debug("syz_fuse_handle_req > read failed: %d\n", errno);
- return -1;
- }
- if ((size_t)ret < sizeof(struct fuse_in_header)) {
- debug("syz_fuse_handle_req: received a truncated FUSE header\n");
- return -1;
- }
-
- const struct fuse_in_header* in_hdr = (const struct fuse_in_header*)buf;
- debug("syz_fuse_handle_req: received opcode %d\n", in_hdr->opcode);
- if (in_hdr->len > (uint32)ret) {
- debug("syz_fuse_handle_req: received a truncated message\n");
- return -1;
- }
-
- switch (in_hdr->opcode) {
- case FUSE_GETATTR:
- case FUSE_SETATTR:
- out_hdr = req_out->attr;
- break;
- case FUSE_LOOKUP:
- case FUSE_SYMLINK:
- case FUSE_LINK:
- case FUSE_MKNOD:
- case FUSE_MKDIR:
- out_hdr = req_out->entry;
- break;
- case FUSE_OPEN:
- case FUSE_OPENDIR:
- out_hdr = req_out->open;
- break;
- case FUSE_STATFS:
- out_hdr = req_out->statfs;
- break;
- case FUSE_RMDIR:
- case FUSE_RENAME:
- case FUSE_RENAME2:
- case FUSE_FALLOCATE:
- case FUSE_SETXATTR:
- case FUSE_REMOVEXATTR:
- case FUSE_FSYNCDIR:
- case FUSE_FSYNC:
- case FUSE_SETLKW:
- case FUSE_SETLK:
- case FUSE_ACCESS:
- case FUSE_FLUSH:
- case FUSE_RELEASE:
- case FUSE_RELEASEDIR:
- case FUSE_UNLINK:
- case FUSE_DESTROY:
- out_hdr = req_out->init;
- if (!out_hdr) {
- debug("syz_fuse_handle_req: received a NULL out_hdr\n");
- return -1;
- }
- out_hdr->len = sizeof(struct fuse_out_header);
- break;
- case FUSE_READ:
- out_hdr = req_out->read;
- break;
- case FUSE_READDIR:
- out_hdr = req_out->dirent;
- break;
- case FUSE_READDIRPLUS:
- out_hdr = req_out->direntplus;
- break;
- case FUSE_INIT:
- out_hdr = req_out->init;
- break;
- case FUSE_LSEEK:
- out_hdr = req_out->lseek;
- break;
- case FUSE_GETLK:
- out_hdr = req_out->lk;
- break;
- case FUSE_BMAP:
- out_hdr = req_out->bmap;
- break;
- case FUSE_POLL:
- out_hdr = req_out->poll;
- break;
- case FUSE_GETXATTR:
- case FUSE_LISTXATTR:
- out_hdr = req_out->getxattr;
- break;
- case FUSE_WRITE:
- case FUSE_COPY_FILE_RANGE:
- out_hdr = req_out->write;
- break;
- case FUSE_FORGET:
- case FUSE_BATCH_FORGET:
- return 0;
- case FUSE_CREATE:
- out_hdr = req_out->create_open;
- break;
- case FUSE_IOCTL:
- out_hdr = req_out->ioctl;
- break;
- default:
- debug("syz_fuse_handle_req: unknown FUSE opcode\n");
- return -1;
- }
-
- return fuse_send_response(fd, in_hdr, out_hdr);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_80211_inject_frame
-#include <errno.h>
-#include <linux/genetlink.h>
-#include <linux/if_ether.h>
-#include <linux/nl80211.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-
-#define HWSIM_ATTR_RX_RATE 5
-#define HWSIM_ATTR_SIGNAL 6
-#define HWSIM_ATTR_ADDR_RECEIVER 1
-#define HWSIM_ATTR_FRAME 3
-
-#define WIFI_MAX_INJECT_LEN 2048
-
-static int hwsim_register_socket(struct nlmsg* nlmsg, int sock, int hwsim_family)
-{
- struct genlmsghdr genlhdr;
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = HWSIM_CMD_REGISTER;
- netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
- int err = netlink_send_ext(nlmsg, sock, 0, NULL, false);
- if (err < 0) {
- debug("hwsim_register_device failed: %s\n", strerror(errno));
- }
- return err;
-}
-
-static int hwsim_inject_frame(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8* mac_addr, uint8* data, int len)
-{
- struct genlmsghdr genlhdr;
- uint32 rx_rate = WIFI_DEFAULT_RX_RATE;
- uint32 signal = WIFI_DEFAULT_SIGNAL;
-
- memset(&genlhdr, 0, sizeof(genlhdr));
- genlhdr.cmd = HWSIM_CMD_FRAME;
- netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
- netlink_attr(nlmsg, HWSIM_ATTR_RX_RATE, &rx_rate, sizeof(rx_rate));
- netlink_attr(nlmsg, HWSIM_ATTR_SIGNAL, &signal, sizeof(signal));
- netlink_attr(nlmsg, HWSIM_ATTR_ADDR_RECEIVER, mac_addr, ETH_ALEN);
- netlink_attr(nlmsg, HWSIM_ATTR_FRAME, data, len);
- int err = netlink_send_ext(nlmsg, sock, 0, NULL, false);
- if (err < 0) {
- debug("hwsim_inject_frame failed: %s\n", strerror(errno));
- }
- return err;
-}
-
-static long syz_80211_inject_frame(volatile long a0, volatile long a1, volatile long a2)
-{
- uint8* mac_addr = (uint8*)a0;
- uint8* buf = (uint8*)a1;
- int buf_len = (int)a2;
- struct nlmsg tmp_msg;
-
- if (buf_len < 0 || buf_len > WIFI_MAX_INJECT_LEN) {
- debug("syz_80211_inject_frame: wrong buffer size %d\n", buf_len);
- return -1;
- }
-
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock < 0) {
- debug("syz_80211_inject_frame: socket creation failed, errno %d\n", errno);
- return -1;
- }
-
- int hwsim_family_id = netlink_query_family_id(&tmp_msg, sock, "MAC80211_HWSIM", false);
- int ret = hwsim_register_socket(&tmp_msg, sock, hwsim_family_id);
- if (ret < 0) {
- debug("syz_80211_inject_frame: failed to register socket, ret %d\n", ret);
- close(sock);
- return -1;
- }
-
- ret = hwsim_inject_frame(&tmp_msg, sock, hwsim_family_id, mac_addr, buf, buf_len);
- close(sock);
- if (ret < 0) {
- debug("syz_80211_inject_frame: failed to inject message, ret %d\n", ret);
- return -1;
- }
-
- return 0;
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_80211_join_ibss
-
-#define WIFI_MAX_SSID_LEN 32
-
-#define WIFI_JOIN_IBSS_NO_SCAN 0
-#define WIFI_JOIN_IBSS_BG_SCAN 1
-#define WIFI_JOIN_IBSS_BG_NO_SCAN 2
-
-static long syz_80211_join_ibss(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
-{
- char* interface = (char*)a0;
- uint8* ssid = (uint8*)a1;
- int ssid_len = (int)a2;
- int mode = (int)a3;
-
- struct nlmsg tmp_msg;
- uint8 bssid[ETH_ALEN] = WIFI_IBSS_BSSID;
-
- if (ssid_len < 0 || ssid_len > WIFI_MAX_SSID_LEN) {
- debug("syz_80211_join_ibss: invalid ssid len %d\n", ssid_len);
- return -1;
- }
-
- if (mode < 0 || mode > WIFI_JOIN_IBSS_BG_NO_SCAN) {
- debug("syz_80211_join_ibss: invalid mode %d\n", mode);
- return -1;
- }
-
- int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
- if (sock < 0) {
- debug("syz_80211_join_ibss: socket creation failed, errno %d\n", errno);
- return -1;
- }
-
- int nl80211_family_id = netlink_query_family_id(&tmp_msg, sock, "nl80211", false);
- struct join_ibss_props ibss_props = {
- .wiphy_freq = WIFI_DEFAULT_FREQUENCY,
- .wiphy_freq_fixed = (mode == WIFI_JOIN_IBSS_NO_SCAN || mode == WIFI_JOIN_IBSS_BG_NO_SCAN),
- .mac = bssid,
- .ssid = ssid,
- .ssid_len = ssid_len};
-
- int ret = nl80211_setup_ibss_interface(&tmp_msg, sock, nl80211_family_id, interface, &ibss_props, false);
- close(sock);
- if (ret < 0) {
- debug("syz_80211_join_ibss: failed set up IBSS network for %.32s\n", interface);
- return -1;
- }
-
- if (mode == WIFI_JOIN_IBSS_NO_SCAN) {
- ret = await_ifla_operstate(&tmp_msg, interface, IF_OPER_UP, false);
- if (ret < 0) {
- debug("syz_80211_join_ibss: await_ifla_operstate failed for %.32s, ret %d\n", interface, ret);
- return -1;
- }
- }
-
- return 0;
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_clone || __NR_syz_clone3
-#if SYZ_EXECUTOR
-#define USLEEP_FORKED_CHILD (3 * syscall_timeout_ms * 1000)
-#else
-#define USLEEP_FORKED_CHILD (3 * /*{{{BASE_CALL_TIMEOUT_MS}}}*/ *1000)
-#endif
-
-static long handle_clone_ret(long ret)
-{
- if (ret != 0) {
-#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
- __atomic_store_n(&clone_ongoing, 0, __ATOMIC_RELAXED);
-#endif
- return ret;
- }
- usleep(USLEEP_FORKED_CHILD);
- syscall(__NR_exit, 0);
- while (1) {
- }
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_clone
-#include <sched.h>
-static long syz_clone(volatile long flags, volatile long stack, volatile long stack_len,
- volatile long ptid, volatile long ctid, volatile long tls)
-{
- long sp = (stack + stack_len) & ~15;
-#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
- __atomic_store_n(&clone_ongoing, 1, __ATOMIC_RELAXED);
-#endif
- long ret = (long)syscall(__NR_clone, flags & ~CLONE_VM, sp, ptid, ctid, tls);
- return handle_clone_ret(ret);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_clone3
-#include <linux/sched.h>
-#include <sched.h>
-
-#define MAX_CLONE_ARGS_BYTES 256
-static long syz_clone3(volatile long a0, volatile long a1)
-{
- unsigned long copy_size = a1;
- if (copy_size < sizeof(uint64) || copy_size > MAX_CLONE_ARGS_BYTES)
- return -1;
- char clone_args[MAX_CLONE_ARGS_BYTES];
- memcpy(&clone_args, (void*)a0, copy_size);
- uint64* flags = (uint64*)&clone_args;
- *flags &= ~CLONE_VM;
-#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
- __atomic_store_n(&clone_ongoing, 1, __ATOMIC_RELAXED);
-#endif
- return handle_clone_ret((long)syscall(__NR_clone3, &clone_args, copy_size));
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_pkey_set
-static long syz_pkey_set(volatile long pkey, volatile long val)
-{
-#if GOARCH_amd64 || GOARCH_386
- uint32 eax = 0;
- uint32 ecx = 0;
- asm volatile("rdpkru"
- : "=a"(eax)
- : "c"(ecx)
- : "edx");
- eax &= ~(3 << ((pkey % 16) * 2));
- eax |= (val & 3) << ((pkey % 16) * 2);
- uint32 edx = 0;
- asm volatile("wrpkru" ::"a"(eax), "c"(ecx), "d"(edx));
-#endif
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SWAP
-#include <fcntl.h>
-#include <linux/falloc.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/swap.h>
-#include <sys/types.h>
-
-#define SWAP_FILE "./swap-file"
-#define SWAP_FILE_SIZE (128 * 1000 * 1000)
-
-static void setup_swap()
-{
- swapoff(SWAP_FILE);
- unlink(SWAP_FILE);
- int fd = open(SWAP_FILE, O_CREAT | O_WRONLY | O_CLOEXEC, 0600);
- if (fd == -1)
- failmsg("swap file open failed", "file: %s", SWAP_FILE);
- fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, SWAP_FILE_SIZE);
- close(fd);
- char cmdline[64];
- sprintf(cmdline, "mkswap %s", SWAP_FILE);
- if (runcmdline(cmdline))
- fail("mkswap failed");
- if (swapon(SWAP_FILE, SWAP_FLAG_PREFER) == 1)
- failmsg("swapon failed", "file: %s", SWAP_FILE);
-}
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_pidfd_open
-#include <sys/syscall.h>
-static long syz_pidfd_open(volatile long pid, volatile long flags)
-{
- if (pid == 1) {
- pid = 0;
- }
- return syscall(__NR_pidfd_open, pid, flags);
-}
-
-#endif
-
-#elif GOOS_test
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#if SYZ_EXECUTOR || __NR_syz_mmap
-#include <sys/mman.h>
-static long syz_mmap(volatile long a0, volatile long a1)
-{
- return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_errno
-#include <errno.h>
-static long syz_errno(volatile long v)
-{
- errno = v;
- return v == 0 ? 0 : -1;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_exit
-static long syz_exit(volatile long status)
-{
- _exit(status);
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_sleep_ms
-static long syz_sleep_ms(volatile long ms)
-{
- sleep_ms(ms);
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_compare
-#include <errno.h>
-#include <string.h>
-static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len)
-{
- if (want_len != got_len) {
- errno = EBADF;
- goto error;
- }
- if (memcmp((void*)want, (void*)got, want_len)) {
- errno = EINVAL;
- goto error;
- }
- return 0;
-
-error:
- debug("syz_compare: want (%lu):\n", want_len);
- debug_dump_data((char*)want, want_len);
- debug("got (%lu):\n", got_len);
- debug_dump_data((char*)got, got_len);
- return -1;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_compare_int
-#include <errno.h>
-#include <stdarg.h>
-static long syz_compare_int(volatile long n, ...)
-{
- va_list args;
- va_start(args, n);
- long v0 = va_arg(args, long);
- long v1 = va_arg(args, long);
- long v2 = va_arg(args, long);
- long v3 = va_arg(args, long);
- va_end(args);
- if (n < 2 || n > 4)
- return errno = E2BIG, -1;
- if (n <= 2 && v2 != 0)
- return errno = EFAULT, -1;
- if (n <= 3 && v3 != 0)
- return errno = EFAULT, -1;
- if (v0 != v1)
- return errno = EINVAL, -1;
- if (n > 2 && v0 != v2)
- return errno = EINVAL, -1;
- if (n > 3 && v0 != v3)
- return errno = EINVAL, -1;
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_compare_zlib
-
-//% This code is derived from puff.{c,h}, found in the zlib development. The
-//% original files come with the following copyright notice:
-
-//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
-//% version 2.3, 21 Jan 2013
-//% This software is provided 'as-is', without any express or implied
-//% warranty. In no event will the author be held liable for any damages
-//% arising from the use of this software.
-//% Permission is granted to anyone to use this software for any purpose,
-//% including commercial applications, and to alter it and redistribute it
-//% freely, subject to the following restrictions:
-//% 1. The origin of this software must not be misrepresented; you must not
-//% claim that you wrote the original software. If you use this software
-//% in a product, an acknowledgment in the product documentation would be
-//% appreciated but is not required.
-//% 2. Altered source versions must be plainly marked as such, and must not be
-//% misrepresented as being the original software.
-//% 3. This notice may not be removed or altered from any source distribution.
-//% Mark Adler madler@alumni.caltech.edu
-
-//% BEGIN CODE DERIVED FROM puff.{c,h}
-
-#include <setjmp.h>
-#define MAXBITS 15
-#define MAXLCODES 286
-#define MAXDCODES 30
-#define MAXCODES (MAXLCODES + MAXDCODES)
-#define FIXLCODES 288
-
-struct puff_state {
- unsigned char* out;
- unsigned long outlen;
- unsigned long outcnt;
- const unsigned char* in;
- unsigned long inlen;
- unsigned long incnt;
- int bitbuf;
- int bitcnt;
- jmp_buf env;
-};
-static int puff_bits(struct puff_state* s, int need)
-{
- long val = s->bitbuf;
- while (s->bitcnt < need) {
- if (s->incnt == s->inlen)
- longjmp(s->env, 1);
- val |= (long)(s->in[s->incnt++]) << s->bitcnt;
- s->bitcnt += 8;
- }
- s->bitbuf = (int)(val >> need);
- s->bitcnt -= need;
- return (int)(val & ((1L << need) - 1));
-}
-static int puff_stored(struct puff_state* s)
-{
- s->bitbuf = 0;
- s->bitcnt = 0;
- if (s->incnt + 4 > s->inlen)
- return 2;
- unsigned len = s->in[s->incnt++];
- len |= s->in[s->incnt++] << 8;
- if (s->in[s->incnt++] != (~len & 0xff) ||
- s->in[s->incnt++] != ((~len >> 8) & 0xff))
- return -2;
- if (s->incnt + len > s->inlen)
- return 2;
- if (s->outcnt + len > s->outlen)
- return 1;
- for (; len--; s->outcnt++, s->incnt++) {
- if (s->in[s->incnt])
- s->out[s->outcnt] = s->in[s->incnt];
- }
- return 0;
-}
-struct puff_huffman {
- short* count;
- short* symbol;
-};
-static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
-{
- int first = 0;
- int index = 0;
- int bitbuf = s->bitbuf;
- int left = s->bitcnt;
- int code = first = index = 0;
- int len = 1;
- short* next = h->count + 1;
- while (1) {
- while (left--) {
- code |= bitbuf & 1;
- bitbuf >>= 1;
- int count = *next++;
- if (code - count < first) {
- s->bitbuf = bitbuf;
- s->bitcnt = (s->bitcnt - len) & 7;
- return h->symbol[index + (code - first)];
- }
- index += count;
- first += count;
- first <<= 1;
- code <<= 1;
- len++;
- }
- left = (MAXBITS + 1) - len;
- if (left == 0)
- break;
- if (s->incnt == s->inlen)
- longjmp(s->env, 1);
- bitbuf = s->in[s->incnt++];
- if (left > 8)
- left = 8;
- }
- return -10;
-}
-static int puff_construct(struct puff_huffman* h, const short* length, int n)
-{
- int len;
- for (len = 0; len <= MAXBITS; len++)
- h->count[len] = 0;
- int symbol;
- for (symbol = 0; symbol < n; symbol++)
- (h->count[length[symbol]])++;
- if (h->count[0] == n)
- return 0;
- int left = 1;
- for (len = 1; len <= MAXBITS; len++) {
- left <<= 1;
- left -= h->count[len];
- if (left < 0)
- return left;
- }
- short offs[MAXBITS + 1];
- offs[1] = 0;
- for (len = 1; len < MAXBITS; len++)
- offs[len + 1] = offs[len] + h->count[len];
- for (symbol = 0; symbol < n; symbol++)
- if (length[symbol] != 0)
- h->symbol[offs[length[symbol]]++] = symbol;
- return left;
-}
-static int puff_codes(struct puff_state* s,
- const struct puff_huffman* lencode,
- const struct puff_huffman* distcode)
-{
- static const short lens[29] = {
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
- static const short lext[29] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
- static const short dists[30] = {
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577};
- static const short dext[30] = {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13};
- int symbol;
- do {
- symbol = puff_decode(s, lencode);
- if (symbol < 0)
- return symbol;
- if (symbol < 256) {
- if (s->outcnt == s->outlen)
- return 1;
- if (symbol)
- s->out[s->outcnt] = symbol;
- s->outcnt++;
- } else if (symbol > 256) {
- symbol -= 257;
- if (symbol >= 29)
- return -10;
- int len = lens[symbol] + puff_bits(s, lext[symbol]);
- symbol = puff_decode(s, distcode);
- if (symbol < 0)
- return symbol;
- unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
- if (dist > s->outcnt)
- return -11;
- if (s->outcnt + len > s->outlen)
- return 1;
- while (len--) {
- if (dist <= s->outcnt && s->out[s->outcnt - dist])
- s->out[s->outcnt] = s->out[s->outcnt - dist];
- s->outcnt++;
- }
- }
- } while (symbol != 256);
- return 0;
-}
-static int puff_fixed(struct puff_state* s)
-{
- static int virgin = 1;
- static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
- static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- static struct puff_huffman lencode, distcode;
- if (virgin) {
- lencode.count = lencnt;
- lencode.symbol = lensym;
- distcode.count = distcnt;
- distcode.symbol = distsym;
- short lengths[FIXLCODES];
- int symbol;
- for (symbol = 0; symbol < 144; symbol++)
- lengths[symbol] = 8;
- for (; symbol < 256; symbol++)
- lengths[symbol] = 9;
- for (; symbol < 280; symbol++)
- lengths[symbol] = 7;
- for (; symbol < FIXLCODES; symbol++)
- lengths[symbol] = 8;
- puff_construct(&lencode, lengths, FIXLCODES);
- for (symbol = 0; symbol < MAXDCODES; symbol++)
- lengths[symbol] = 5;
- puff_construct(&distcode, lengths, MAXDCODES);
- virgin = 0;
- }
- return puff_codes(s, &lencode, &distcode);
-}
-static int puff_dynamic(struct puff_state* s)
-{
- static const short order[19] =
- {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
- int nlen = puff_bits(s, 5) + 257;
- int ndist = puff_bits(s, 5) + 1;
- int ncode = puff_bits(s, 4) + 4;
- if (nlen > MAXLCODES || ndist > MAXDCODES)
- return -3;
- short lengths[MAXCODES];
- int index;
- for (index = 0; index < ncode; index++)
- lengths[order[index]] = puff_bits(s, 3);
- for (; index < 19; index++)
- lengths[order[index]] = 0;
- short lencnt[MAXBITS + 1], lensym[MAXLCODES];
- struct puff_huffman lencode = {lencnt, lensym};
- int err = puff_construct(&lencode, lengths, 19);
- if (err != 0)
- return -4;
- index = 0;
- while (index < nlen + ndist) {
- int symbol;
- int len;
-
- symbol = puff_decode(s, &lencode);
- if (symbol < 0)
- return symbol;
- if (symbol < 16)
- lengths[index++] = symbol;
- else {
- len = 0;
- if (symbol == 16) {
- if (index == 0)
- return -5;
- len = lengths[index - 1];
- symbol = 3 + puff_bits(s, 2);
- } else if (symbol == 17)
- symbol = 3 + puff_bits(s, 3);
- else
- symbol = 11 + puff_bits(s, 7);
- if (index + symbol > nlen + ndist)
- return -6;
- while (symbol--)
- lengths[index++] = len;
- }
- }
- if (lengths[256] == 0)
- return -9;
- err = puff_construct(&lencode, lengths, nlen);
- if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
- return -7;
- short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- struct puff_huffman distcode = {distcnt, distsym};
- err = puff_construct(&distcode, lengths + nlen, ndist);
- if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
- return -8;
- return puff_codes(s, &lencode, &distcode);
-}
-static int puff(
- unsigned char* dest,
- unsigned long* destlen,
- const unsigned char* source,
- unsigned long sourcelen)
-{
- struct puff_state s = {
- .out = dest,
- .outlen = *destlen,
- .outcnt = 0,
- .in = source,
- .inlen = sourcelen,
- .incnt = 0,
- .bitbuf = 0,
- .bitcnt = 0,
- };
- int err;
- if (setjmp(s.env) != 0)
- err = 2;
- else {
- int last;
- do {
- last = puff_bits(&s, 1);
- int type = puff_bits(&s, 2);
- err = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));
- if (err != 0)
- break;
- } while (!last);
- }
-
- *destlen = s.outcnt;
- return err;
-}
-
-//% END CODE DERIVED FROM puff.{c,h}
-
-#include <errno.h>
-#include <sys/mman.h>
-#define ZLIB_HEADER_WIDTH 2
-
-static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
-{
- if (sourcelen < ZLIB_HEADER_WIDTH)
- return 0;
- source += ZLIB_HEADER_WIDTH;
- sourcelen -= ZLIB_HEADER_WIDTH;
- const unsigned long max_destlen = 132 << 20;
- void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
- if (ret == MAP_FAILED)
- return -1;
- unsigned char* dest = (unsigned char*)ret;
- unsigned long destlen = max_destlen;
- int err = puff(dest, &destlen, source, sourcelen);
- if (err) {
- munmap(dest, max_destlen);
- errno = -err;
- return -1;
- }
- if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
- munmap(dest, max_destlen);
- return -1;
- }
- return munmap(dest, max_destlen);
-}
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-static long syz_compare_zlib(volatile long data, volatile long size, volatile long zdata, volatile long zsize)
-{
- int fd = open("./uncompressed", O_RDWR | O_CREAT | O_EXCL, 0666);
- if (fd == -1)
- return -1;
- if (puff_zlib_to_file((unsigned char*)zdata, zsize, fd))
- return -1;
- struct stat statbuf;
- if (fstat(fd, &statbuf))
- return -1;
- void* uncompressed = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (uncompressed == MAP_FAILED)
- return -1;
- return syz_compare(data, size, (long)uncompressed, statbuf.st_size);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-static void loop();
-static int do_sandbox_none(void)
-{
- loop();
- return 0;
-}
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_test_fuzzer1
-
-static void fake_crash(const char* name)
-{
- failmsg("crash", "{{CRASH: %s}}", name);
- doexit(1);
-}
-
-static long syz_test_fuzzer1(volatile long a, volatile long b, volatile long c)
-{
- if (a == 1 && b == 1 && c == 1)
- fake_crash("first bug");
- if (a == 1 && b == 2 && c == 3)
- fake_crash("second bug");
- return 0;
-}
-
-#endif
-
-#elif GOOS_windows
-
-#include <direct.h>
-#include <io.h>
-#include <windows.h>
-
-#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
-static void install_segv_handler()
-{
-}
-
-#define NONFAILING(...) \
- ([&]() { __try { __VA_ARGS__; } __except (EXCEPTION_EXECUTE_HANDLER) { return false; } return true; }())
-#endif
-
-#if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER
-static uint64 current_time_ms()
-{
- return GetTickCount64();
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER
-static void sleep_ms(uint64 ms)
-{
- Sleep(ms);
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_THREADED
-static void thread_start(void* (*fn)(void*), void* arg)
-{
- HANDLE th = CreateThread(NULL, 128 << 10, (LPTHREAD_START_ROUTINE)fn, arg, 0, NULL);
- if (th == NULL)
- exitf("CreateThread failed");
-}
-
-struct event_t {
- CRITICAL_SECTION cs;
- CONDITION_VARIABLE cv;
- int state;
-};
-
-static void event_init(event_t* ev)
-{
- InitializeCriticalSection(&ev->cs);
- InitializeConditionVariable(&ev->cv);
- ev->state = 0;
-}
-
-static void event_reset(event_t* ev)
-{
- ev->state = 0;
-}
-
-static void event_set(event_t* ev)
-{
- EnterCriticalSection(&ev->cs);
- if (ev->state)
- exitf("event already set");
- ev->state = 1;
- LeaveCriticalSection(&ev->cs);
- WakeAllConditionVariable(&ev->cv);
-}
-
-static void event_wait(event_t* ev)
-{
- EnterCriticalSection(&ev->cs);
- while (!ev->state)
- SleepConditionVariableCS(&ev->cv, &ev->cs, INFINITE);
- LeaveCriticalSection(&ev->cs);
-}
-
-static int event_isset(event_t* ev)
-{
- EnterCriticalSection(&ev->cs);
- int res = ev->state;
- LeaveCriticalSection(&ev->cs);
- return res;
-}
-
-static int event_timedwait(event_t* ev, uint64 timeout_ms)
-{
- EnterCriticalSection(&ev->cs);
- uint64 start = current_time_ms();
- for (;;) {
- if (ev->state)
- break;
- uint64 now = current_time_ms();
- if (now - start > timeout_ms)
- break;
- SleepConditionVariableCS(&ev->cv, &ev->cs, timeout_ms - (now - start));
- }
- int res = ev->state;
- LeaveCriticalSection(&ev->cs);
- return res;
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-static void loop();
-static int do_sandbox_none(void)
-{
- loop();
- return 0;
-}
-#endif
-
-static void use_temporary_dir(void)
-{
- char tmpdir_template[] = "./syzkaller.XXXXXX";
- char* tmpdir = mktemp(tmpdir_template);
-
- CreateDirectory(tmpdir, NULL);
- _chdir(tmpdir);
-}
-
-#else
-#error "unknown OS"
-#endif
-
-#if SYZ_TEST_COMMON_EXT_EXAMPLE
-#include "common_ext_example.h"
-#else
-
-#endif
-
-#if SYZ_EXECUTOR || __NR_syz_execute_func
-static long syz_execute_func(volatile long text)
-{
-#if defined(__GNUC__)
- volatile long p[8] = {0};
- (void)p;
-#if GOARCH_amd64
- asm volatile("" ::"r"(0l), "r"(1l), "r"(2l), "r"(3l), "r"(4l), "r"(5l), "r"(6l),
- "r"(7l), "r"(8l), "r"(9l), "r"(10l), "r"(11l), "r"(12l), "r"(13l));
-#endif
-#endif
- ((void (*)(void))(text))();
- return 0;
-}
-#endif
-
-#if SYZ_THREADED
-struct thread_t {
- int created, call;
- event_t ready, done;
-};
-
-static struct thread_t threads[16];
-static void execute_call(int call);
-static int running;
-
-static void* thr(void* arg)
-{
- struct thread_t* th = (struct thread_t*)arg;
- for (;;) {
- event_wait(&th->ready);
- event_reset(&th->ready);
- execute_call(th->call);
- __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
- event_set(&th->done);
- }
- return 0;
-}
-
-#if SYZ_REPEAT
-static void execute_one(void)
-#else
-static void loop(void)
-#endif
-{
-#if SYZ_REPRO
- if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
- }
-#endif
-#if SYZ_TRACE
- fprintf(stderr, "### start\n");
-#endif
- int i, call, thread;
- for (call = 0; call < /*{{{NUM_CALLS}}}*/; call++) {
- for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
- struct thread_t* th = &threads[thread];
- if (!th->created) {
- th->created = 1;
- event_init(&th->ready);
- event_init(&th->done);
- event_set(&th->done);
- thread_start(thr, th);
- }
- if (!event_isset(&th->done))
- continue;
- event_reset(&th->done);
- th->call = call;
- __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
- event_set(&th->ready);
-#if SYZ_ASYNC
- if (/*{{{ASYNC_CONDITIONS}}}*/)
- break;
-#endif
- event_timedwait(&th->done, /*{{{CALL_TIMEOUT_MS}}}*/);
- break;
- }
- }
- for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
- sleep_ms(1);
-#if SYZ_HAVE_CLOSE_FDS
- close_fds();
-#endif
-}
-#endif
-
-#if SYZ_EXECUTOR || SYZ_REPEAT
-static void execute_one(void);
-#if SYZ_EXECUTOR_USES_FORK_SERVER
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#if GOOS_linux
-#define WAIT_FLAGS __WALL
-#else
-#define WAIT_FLAGS 0
-#endif
-
-#if SYZ_EXECUTOR
-static void reply_handshake();
-#endif
-
-static void loop(void)
-{
-#if SYZ_HAVE_SETUP_LOOP
- setup_loop();
-#endif
-#if SYZ_EXECUTOR
- reply_handshake();
-#endif
- int iter = 0;
-#if SYZ_REPEAT_TIMES
- for (; iter < /*{{{REPEAT_TIMES}}}*/; iter++) {
-#else
- for (;; iter++) {
-#endif
-#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
- char cwdbuf[32];
- sprintf(cwdbuf, "./%d", iter);
- if (mkdir(cwdbuf, 0777))
- fail("failed to mkdir");
-#endif
-#if SYZ_HAVE_RESET_LOOP
- reset_loop();
-#endif
-#if SYZ_EXECUTOR
- receive_execute();
-#endif
- int pid = fork();
- if (pid < 0)
- fail("clone failed");
- if (pid == 0) {
-#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
- if (chdir(cwdbuf))
- fail("failed to chdir");
-#endif
-#if SYZ_HAVE_SETUP_TEST
- setup_test();
-#endif
-#if SYZ_HAVE_SETUP_EXT_TEST
- setup_ext_test();
-#endif
-#if SYZ_EXECUTOR
- close(kInPipeFd);
-#endif
-#if SYZ_EXECUTOR && SYZ_EXECUTOR_USES_SHMEM
- close(kOutPipeFd);
-#endif
- execute_one();
-#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED
- close_fds();
-#endif
- doexit(0);
- }
- debug("spawned worker pid %d\n", pid);
- int status = 0;
- uint64 start = current_time_ms();
-#if SYZ_EXECUTOR && SYZ_EXECUTOR_USES_SHMEM
- uint64 last_executed = start;
- uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
-#endif
- for (;;) {
- if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
- break;
- sleep_ms(1);
-#if SYZ_EXECUTOR
-#if SYZ_EXECUTOR_USES_SHMEM
- uint64 min_timeout_ms = program_timeout_ms * 3 / 5;
- uint64 inactive_timeout_ms = syscall_timeout_ms * 20;
- uint64 now = current_time_ms();
- uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
- if (executed_calls != now_executed) {
- executed_calls = now_executed;
- last_executed = now;
- }
- if ((now - start < program_timeout_ms) &&
- (now - start < min_timeout_ms || now - last_executed < inactive_timeout_ms))
- continue;
-#else
- if (current_time_ms() - start < program_timeout_ms)
- continue;
-#endif
-#else
- if (current_time_ms() - start < /*{{{PROGRAM_TIMEOUT_MS}}}*/)
- continue;
-#endif
- debug("killing hanging pid %d\n", pid);
- kill_and_wait(pid, &status);
- break;
- }
-#if SYZ_EXECUTOR
- if (WEXITSTATUS(status) == kFailStatus) {
- errno = 0;
- fail("child failed");
- }
- reply_execute(0);
-#endif
-#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
- remove_dir(cwdbuf);
-#endif
-#if SYZ_LEAK
- check_leaks();
-#endif
- }
-}
-#else
-static void loop(void)
-{
- execute_one();
-}
-#endif
-#endif
-
-#if !SYZ_EXECUTOR
-
-/*{{{RESULTS}}}*/
-
-#if SYZ_THREADED || SYZ_REPEAT || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID
-#if SYZ_THREADED
-void execute_call(int call)
-#elif SYZ_REPEAT
-void execute_one(void)
-#else
-void loop(void)
-#endif
-{
- /*{{{SYSCALLS}}}*/
-#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT
- close_fds();
-#endif
-}
-#endif
-int main(void)
-{
- /*{{{MMAP_DATA}}}*/
-
-#if SYZ_SYSCTL
- setup_sysctl();
-#endif
-#if SYZ_CGROUPS
- setup_cgroups();
-#endif
-#if SYZ_BINFMT_MISC
- setup_binfmt_misc();
-#endif
-#if SYZ_LEAK
- setup_leak();
-#endif
-#if SYZ_FAULT
- setup_fault();
-#endif
-#if SYZ_KCSAN
- setup_kcsan();
-#endif
-#if SYZ_USB
- setup_usb();
-#endif
-#if SYZ_802154
- setup_802154();
-#endif
-#if SYZ_SWAP
- setup_swap();
-#endif
-#if SYZ_HANDLE_SEGV
- install_segv_handler();
-#endif
-#if SYZ_HAVE_SETUP_EXT
- setup_ext();
-#endif
-#if SYZ_MULTI_PROC
- for (procid = 0; procid < /*{{{PROCS}}}*/; procid++) {
- if (fork() == 0) {
-#endif
-#if SYZ_USE_TMP_DIR || SYZ_SANDBOX_ANDROID
- use_temporary_dir();
-#endif
- /*{{{SANDBOX_FUNC}}}*/
-#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT && !SYZ_SANDBOX_NONE && \
- !SYZ_SANDBOX_SETUID && !SYZ_SANDBOX_NAMESPACE && !SYZ_SANDBOX_ANDROID
- close_fds();
-#endif
-#if SYZ_MULTI_PROC
- }
- }
- sleep(1000000);
-#endif
-#if !SYZ_MULTI_PROC && !SYZ_REPEAT && SYZ_LEAK
- check_leaks();
-#endif
- return 0;
-}
-#endif
-`