diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-05-08 12:24:46 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-05-08 12:26:59 +0000 |
| commit | 4dbd403fd0978b91ffe3bb2f2a749511591644dd (patch) | |
| tree | a43a92648849d5127c4165b744e05e38c90bf9ee /pkg | |
| parent | dc488c459880e3f3af557dc336697138ecb8228b (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')
| -rw-r--r-- | pkg/csource/common.go | 3 | ||||
| -rw-r--r-- | pkg/csource/csource_test.go | 3 | ||||
| -rw-r--r-- | pkg/csource/gen.go | 88 | ||||
| -rw-r--r-- | pkg/csource/generated.go | 12736 |
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, - ®s, 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, ®s, 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(®s, 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, ®s)) - 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, ®); -} - -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, ®); -} - -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, ®s)) - 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, ®s)) - 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 -` |
