// https://syzkaller.appspot.com/bug?id=4eff52538c71b39676731e9cf84c0eff42f9dc5e // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static unsigned long long procid; 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) { exit(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 (skip && valid) { _longjmp(segv_env, 1); } exit(sig); } static void install_segv_handler(void) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = segv_handler; sa.sa_flags = SA_NODEFER | SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGBUS, &sa, NULL); } #define NONFAILING(...) \ ({ \ 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; \ }) static void sleep_ms(uint64_t ms) { usleep(ms * 1000); } static uint64_t current_time_ms(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) exit(1); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; } static void use_temporary_dir(void) { char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) exit(1); if (chmod(tmpdir, 0777)) exit(1); if (chdir(tmpdir)) exit(1); } 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; } exit(1); } #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)))) 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) exit(1); __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_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; for (;;) { uint64_t 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; } } 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); errno = err; return false; } close(fd); return true; } 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); } 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; } static int netlink_send_ext(struct nlmsg* nlmsg, int sock, uint16_t reply_type, int* reply_len, bool dofail) { if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting) exit(1); 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) exit(1); return -1; } n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0); if (reply_len) *reply_len = 0; if (n < 0) { if (dofail) exit(1); return -1; } if (n < (ssize_t)sizeof(struct nlmsghdr)) { errno = EINVAL; if (dofail) exit(1); 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) exit(1); return -1; } if (hdr->nlmsg_type != NLMSG_ERROR) { errno = EINVAL; if (dofail) exit(1); return -1; } errno = -((struct nlmsgerr*)(hdr + 1))->error; return -errno; } static int netlink_send(struct nlmsg* nlmsg, int sock) { return netlink_send_ext(nlmsg, sock, 0, NULL, true); } 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) { return -1; } uint16_t 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_t*)(attr + 1); break; } } if (!id) { errno = EINVAL; return -1; } recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0); return id; } 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; } static unsigned int queue_count = 2; 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_attr(nlmsg, IFLA_NUM_TX_QUEUES, &queue_count, sizeof(queue_count)); netlink_attr(nlmsg, IFLA_NUM_RX_QUEUES, &queue_count, sizeof(queue_count)); netlink_nest(nlmsg, IFLA_LINKINFO); netlink_attr(nlmsg, IFLA_INFO_KIND, type, strlen(type)); } 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) { } } 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_attr(nlmsg, IFLA_NUM_TX_QUEUES, &queue_count, sizeof(queue_count)); netlink_attr(nlmsg, IFLA_NUM_RX_QUEUES, &queue_count, sizeof(queue_count)); netlink_done(nlmsg); netlink_done(nlmsg); netlink_done(nlmsg); int err = netlink_send(nlmsg, sock); if (err < 0) { } } 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) { } } 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) { } } 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) { } } static void netlink_add_vlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t id, uint16_t 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) { } } 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_t 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) { } } static void netlink_add_geneve(struct nlmsg* nlmsg, int sock, const char* name, uint32_t 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) { } } #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_t mode, uint16_t 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) { } } 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) { } } 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) { } } 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) { } } static struct nlmsg nlmsg; #define DEVLINK_FAMILY_NAME "devlink" #define DEVLINK_CMD_PORT_GET 5 #define DEVLINK_ATTR_BUS_NAME 1 #define DEVLINK_ATTR_DEV_NAME 2 #define DEVLINK_ATTR_NETDEV_NAME 7 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_t netdev_index; int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (sock == -1) exit(1); int rtsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (rtsock == -1) exit(1); 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) { 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); } static int runcmdline(char* cmdline) { int ret = system(cmdline); if (ret) { } return ret; } #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_t listen_a = 20001; const uint16_t listen_b = 20002; const uint16_t listen_c = 20003; const uint16_t af_inet = AF_INET; const uint16_t 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_t)htonl(128 << 24)}; const struct in6_addr first_half_v6 = {{{0}}}; const struct in6_addr second_half_v6 = {{{0x80}}}; const uint8_t half_cidr = 1; const uint16_t 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) { 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) { } 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) { } 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) { } error: close(sock); } static void initialize_netdevices(void) { 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"}, {"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}, {"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) exit(1); 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) exit(1); struct in6_addr geneve_addr6; if (inet_pton(AF_INET6, "fc00::01", &geneve_addr6) <= 0) exit(1); 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(); 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_t 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) { int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock == -1) exit(1); 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_t 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); } #define MAX_FDS 30 #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_t bInterfaceNumber; uint8_t bAlternateSetting; uint8_t 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_t bDeviceClass; uint8_t 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; }; 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; } 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_t desc_length = buffer[offset]; uint8_t 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); 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]; 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; } struct vusb_connect_string_descriptor { uint32_t len; char* str; } __attribute__((packed)); struct vusb_connect_descriptors { uint32_t qual_len; char* qual; uint32_t bos_len; char* bos; uint32_t strs_len; struct vusb_connect_string_descriptor strs[0]; } __attribute__((packed)); 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_t* response_length) { struct usb_device_index* index = lookup_usb_index(fd); uint8_t 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_t)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; } return false; } typedef bool (*lookup_connect_out_response_t)( int fd, const struct vusb_connect_descriptors* descs, const struct usb_ctrlrequest* ctrl, bool* done); 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; } return false; } struct vusb_descriptor { uint8_t req_type; uint8_t desc_type; uint32_t len; char data[0]; } __attribute__((packed)); struct vusb_descriptors { uint32_t len; struct vusb_descriptor* generic; struct vusb_descriptor* descs[0]; } __attribute__((packed)); struct vusb_response { uint8_t type; uint8_t req; uint32_t len; char data[0]; } __attribute__((packed)); struct vusb_responses { uint32_t 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_t* 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_t req = ctrl->bRequest; uint8_t req_type = ctrl->bRequestType & USB_TYPE_MASK; uint8_t 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; } #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) static int usb_raw_open() { return open("/dev/raw-gadget", O_RDWR); } static int usb_raw_init(int fd, uint32_t 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); } static int usb_raw_ep_write(int fd, struct usb_raw_ep_io* io) { return ioctl(fd, USB_RAW_IOCTL_EP_WRITE, io); } static int usb_raw_configure(int fd) { return ioctl(fd, USB_RAW_IOCTL_CONFIGURE, 0); } static int usb_raw_vbus_draw(int fd, uint32_t power) { return ioctl(fd, USB_RAW_IOCTL_VBUS_DRAW, power); } 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); } static int lookup_interface(int fd, uint8_t bInterfaceNumber, uint8_t 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; } static int lookup_endpoint(int fd, uint8_t 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; } #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]; }; 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) { } else { } } } 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) { } else { index->ifaces[n].eps[ep].handle = rv; } } index->iface_cur = n; } } 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) { return rv; } rv = usb_raw_configure(fd); if (rv < 0) { return rv; } set_interface(fd, 0); return 0; } static volatile long syz_usb_connect_impl(uint64_t speed, uint64_t dev_len, const char* dev, const struct vusb_connect_descriptors* descs, lookup_connect_out_response_t lookup_connect_response_out) { if (!dev) { return -1; } int fd = usb_raw_open(); if (fd < 0) { return fd; } if (fd >= MAX_FDS) { close(fd); return -1; } struct usb_device_index* index = add_usb_index(fd, dev, dev_len); if (!index) { return -1; } char device[32]; sprintf(&device[0], "dummy_udc.%llu", procid); int rv = usb_raw_init(fd, speed, "dummy_udc", &device[0]); if (rv < 0) { return rv; } rv = usb_raw_run(fd); if (rv < 0) { return rv; } 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) { return rv; } if (event.inner.type != USB_RAW_EVENT_CONTROL) continue; char* response_data = NULL; uint32_t 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)) { usb_raw_ep0_stall(fd); continue; } } else { if (!lookup_connect_response_out(fd, descs, &event.ctrl, &done)) { 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) { 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) { 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); } if (rv < 0) { return rv; } } sleep_ms(200); return fd; } static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatile long a2, volatile long a3) { uint64_t speed = a0; uint64_t 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); } 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) { return rv; } if (event.inner.type != USB_RAW_EVENT_CONTROL) { return -1; } char* response_data = NULL; uint32_t 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)) { 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; int iface_index = lookup_interface(fd, iface_num, alt_set); if (iface_index < 0) { } else { set_interface(fd, iface_index); } } 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) { 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); } if (rv < 0) { return rv; } sleep_ms(200); return 0; } static volatile long syz_usb_ep_write(volatile long a0, volatile long a1, volatile long a2, volatile long a3) { int fd = a0; uint8_t ep = a1; uint32_t len = a2; char* data = (char*)a3; int ep_handle = lookup_endpoint(fd, ep); if (ep_handle < 0) { return -1; } 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) { return rv; } sleep_ms(200); return 0; } 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_t)a1, (uint8_t)a2); return open(buf, O_RDWR, 0); } else { unsigned long nb = a1; char buf[1024]; char* hash; strncpy(buf, (char*)a0, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; while ((hash = strchr(buf, '#'))) { *hash = '0' + (char)(nb % 10); nb /= 10; } return open(buf, a2 & ~O_CREAT, 0); } } #define XT_TABLE_SIZE 1536 #define XT_MAX_ENTRIES 10 struct xt_counters { uint64_t 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_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; 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_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; 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_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; 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_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; 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; } exit(1); } 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; } exit(1); } if (table->info.size > sizeof(table->replace.entrytable)) exit(1); if (table->info.num_entries > XT_MAX_ENTRIES) exit(1); 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)) exit(1); 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; } exit(1); } 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)) exit(1); 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)) exit(1); if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0) continue; } 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)) exit(1); } 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; } exit(1); } 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; } exit(1); } if (table->info.size > sizeof(table->replace.entrytable)) exit(1); if (table->info.num_entries > XT_MAX_ENTRIES) exit(1); 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)) exit(1); 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; } exit(1); } 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)) exit(1); 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)) exit(1); if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0) continue; } else { } 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)) exit(1); } 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; } exit(1); } 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; } exit(1); } if (table->replace.entries_size > sizeof(table->entrytable)) exit(1); 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)) exit(1); } 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; } exit(1); } 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)) exit(1); 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)) exit(1); if (memcmp(table->entrytable, entrytable, replace.entries_size) == 0) continue; } 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)) exit(1); } close(fd); } static void checkpoint_net_namespace(void) { 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) { 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); } static void mount_cgroups(const char* dir, const char** controllers, int count) { if (mkdir(dir, 0777)) { return; } char enabled[128] = {0}; int i = 0; for (; i < count; i++) { if (mount("none", dir, "cgroup", 0, controllers[i])) { continue; } umount(dir); strcat(enabled, ","); strcat(enabled, controllers[i]); } if (enabled[0] == 0) { if (rmdir(dir) && errno != EBUSY) exit(1); return; } if (mount("none", dir, "cgroup", 0, enabled + 1)) { if (rmdir(dir) && errno != EBUSY) exit(1); } if (chmod(dir, 0777)) { } } static void mount_cgroups2(const char** controllers, int count) { if (mkdir("/syzcgroup/unified", 0777)) { return; } if (mount("none", "/syzcgroup/unified", "cgroup2", 0, NULL)) { if (rmdir("/syzcgroup/unified") && errno != EBUSY) exit(1); return; } if (chmod("/syzcgroup/unified", 0777)) { } 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) { } 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)) { 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"); } static void setup_cgroups_loop() { int pid = getpid(); char file[128]; char cgroupdir[64]; snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid); if (mkdir(cgroupdir, 0777)) { } 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)) { } 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)) { } snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir); write_file(file, "%d", pid); } static void setup_cgroups_test() { char cgroupdir[64]; snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid); if (symlink(cgroupdir, "./cgroup")) { } snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid); if (symlink(cgroupdir, "./cgroup.cpu")) { } snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid); if (symlink(cgroupdir, "./cgroup.net")) { } } static void initialize_cgroups() { if (mkdir("./syz-tmp/newroot/syzcgroup", 0700)) exit(1); if (mkdir("./syz-tmp/newroot/syzcgroup/unified", 0700)) exit(1); if (mkdir("./syz-tmp/newroot/syzcgroup/cpu", 0700)) exit(1); if (mkdir("./syz-tmp/newroot/syzcgroup/net", 0700)) exit(1); unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE; if (mount("/syzcgroup/unified", "./syz-tmp/newroot/syzcgroup/unified", NULL, bind_mount_flags, NULL)) { } if (mount("/syzcgroup/cpu", "./syz-tmp/newroot/syzcgroup/cpu", NULL, bind_mount_flags, NULL)) { } if (mount("/syzcgroup/net", "./syz-tmp/newroot/syzcgroup/net", NULL, bind_mount_flags, NULL)) { } } static void setup_gadgetfs(); static void setup_binderfs(); static void setup_fusectl(); static void sandbox_common_mount_tmpfs(void) { write_file("/proc/sys/fs/mount-max", "100000"); if (mkdir("./syz-tmp", 0777)) exit(1); if (mount("", "./syz-tmp", "tmpfs", 0, NULL)) exit(1); if (mkdir("./syz-tmp/newroot", 0777)) exit(1); if (mkdir("./syz-tmp/newroot/dev", 0700)) exit(1); unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE; if (mount("/dev", "./syz-tmp/newroot/dev", NULL, bind_mount_flags, NULL)) exit(1); if (mkdir("./syz-tmp/newroot/proc", 0700)) exit(1); if (mount("syz-proc", "./syz-tmp/newroot/proc", "proc", 0, NULL)) exit(1); if (mkdir("./syz-tmp/newroot/selinux", 0700)) exit(1); const char* selinux_path = "./syz-tmp/newroot/selinux"; if (mount("/selinux", selinux_path, NULL, bind_mount_flags, NULL)) { if (errno != ENOENT) exit(1); if (mount("/sys/fs/selinux", selinux_path, NULL, bind_mount_flags, NULL) && errno != ENOENT) exit(1); } if (mkdir("./syz-tmp/newroot/sys", 0700)) exit(1); if (mount("/sys", "./syz-tmp/newroot/sys", 0, bind_mount_flags, NULL)) exit(1); if (mount("/sys/kernel/debug", "./syz-tmp/newroot/sys/kernel/debug", NULL, bind_mount_flags, NULL) && errno != ENOENT) exit(1); if (mount("/sys/fs/smackfs", "./syz-tmp/newroot/sys/fs/smackfs", NULL, bind_mount_flags, NULL) && errno != ENOENT) exit(1); if (mount("/proc/sys/fs/binfmt_misc", "./syz-tmp/newroot/proc/sys/fs/binfmt_misc", NULL, bind_mount_flags, NULL) && errno != ENOENT) exit(1); if (mkdir("./syz-tmp/newroot/syz-inputs", 0700)) exit(1); if (mount("/syz-inputs", "./syz-tmp/newroot/syz-inputs", NULL, bind_mount_flags | MS_RDONLY, NULL) && errno != ENOENT) exit(1); initialize_cgroups(); if (mkdir("./syz-tmp/pivot", 0777)) exit(1); if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) { if (chdir("./syz-tmp")) exit(1); } else { if (chdir("/")) exit(1); if (umount2("./pivot", MNT_DETACH)) exit(1); } if (chroot("./newroot")) exit(1); if (chdir("/")) exit(1); setup_gadgetfs(); setup_binderfs(); setup_fusectl(); } static void setup_gadgetfs() { if (mkdir("/dev/gadgetfs", 0777)) { } if (mount("gadgetfs", "/dev/gadgetfs", "gadgetfs", 0, NULL)) { } } static void setup_fusectl() { if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) { } } static void setup_binderfs() { if (mkdir("/dev/binderfs", 0777)) { } if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) { } } static void loop(); static void sandbox_common() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); if (getppid() == 1) exit(1); struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = (200 << 20); 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)) { } if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) { } if (unshare(CLONE_NEWIPC)) { } if (unshare(0x02000000)) { } if (unshare(CLONE_NEWUTS)) { } if (unshare(CLONE_SYSVSEM)) { } 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); } static int wait_for_loop(int pid) { if (pid < 0) exit(1); int status = 0; while (waitpid(-1, &status, __WALL) != pid) { } return WEXITSTATUS(status); } 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)) exit(1); 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)) exit(1); } static int do_sandbox_none(void) { if (unshare(CLONE_NEWPID)) { } int pid = fork(); if (pid != 0) return wait_for_loop(pid); sandbox_common(); drop_caps(); initialize_netdevices_init(); if (unshare(CLONE_NEWNET)) { } write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535"); initialize_netdevices(); sandbox_common_mount_tmpfs(); loop(); exit(1); } #define FS_IOC_SETFLAGS _IOW('f', 2, long) static void remove_dir(const char* dir) { int iter = 0; DIR* dp = 0; const int umount_flags = MNT_FORCE | UMOUNT_NOFOLLOW; retry: while (umount2(dir, umount_flags) == 0) { } dp = opendir(dir); if (dp == NULL) { if (errno == EMFILE) { exit(1); } exit(1); } 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); while (umount2(filename, umount_flags) == 0) { } struct stat st; if (lstat(filename, &st)) exit(1); 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) { } close(fd); continue; } } if (errno == EROFS) { break; } if (errno != EBUSY || i > 100) exit(1); if (umount2(filename, umount_flags)) exit(1); } } 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) { } close(fd); continue; } } if (errno == EROFS) { break; } if (errno == EBUSY) { if (umount2(dir, umount_flags)) exit(1); continue; } if (errno == ENOTEMPTY) { if (iter < 100) { iter++; goto retry; } } } exit(1); } } 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); } 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) { continue; } if (write(fd, abort, 1) < 0) { } close(fd); } closedir(dir); } else { } while (waitpid(-1, status, __WALL) != pid) { } } static void setup_loop() { setup_cgroups_loop(); checkpoint_net_namespace(); } static void reset_loop() { reset_net_namespace(); } static void setup_test() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); setup_cgroups_test(); write_file("/proc/self/oom_score_adj", "1000"); if (symlink("/dev/binderfs", "./binderfs")) { } } static void close_fds() { for (int fd = 3; fd < MAX_FDS; fd++) close(fd); } static const char* setup_binfmt_misc() { if (mount(0, "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, 0) && errno != EBUSY) { return NULL; } 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")) return "write(/proc/sys/fs/binfmt_misc/register) failed"; return NULL; } static const char* setup_usb() { if (chmod("/dev/raw-gadget", 0666)) return "failed to chmod /dev/raw-gadget"; return NULL; } static void setup_sysctl() { int cad_pid = fork(); if (cad_pid < 0) exit(1); if (cad_pid == 0) { for (;;) sleep(100); } char tmppid[32]; snprintf(tmppid, sizeof(tmppid), "%d", cad_pid); struct { const char* name; const char* data; } files[] = { {"/sys/kernel/debug/x86/nmi_longest_ns", "10000000000"}, {"/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"}, {"/sys/kernel/debug/failslab/task-filter", "Y"}, {"/sys/kernel/debug/fail_page_alloc/task-filter", "Y"}, {"/sys/kernel/debug/fail_futex/task-filter", "Y"}, {"/sys/kernel/debug/fail_usercopy/task-filter", "Y"}, {"/sys/kernel/debug/fail_make_request/task-filter", "Y"}, {"/sys/kernel/debug/fail_io_timeout/task-filter", "Y"}, {"/sys/kernel/debug/fail_iommufd/task-filter", "Y"}, {"/proc/sys/kernel/ctrl-alt-del", "0"}, {"/proc/sys/kernel/cad_pid", tmppid}, }; for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); i++) { if (!write_file(files[i].name, files[i].data)) { } } kill(cad_pid, SIGKILL); while (waitpid(cad_pid, NULL, 0) != cad_pid) ; } #define SWAP_FILE "./swap-file" #define SWAP_FILE_SIZE (128 * 1000 * 1000) static const char* setup_swap() { swapoff(SWAP_FILE); unlink(SWAP_FILE); int fd = open(SWAP_FILE, O_CREAT | O_WRONLY | O_CLOEXEC, 0600); if (fd == -1) return "swap file open failed"; fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, SWAP_FILE_SIZE); close(fd); char cmdline[64]; sprintf(cmdline, "mkswap %s", SWAP_FILE); if (runcmdline(cmdline)) return "mkswap failed"; if (swapon(SWAP_FILE, SWAP_FLAG_PREFER) == 1) return "swapon failed"; return NULL; } 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; } static void execute_one(void) { if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } int i, call, thread; for (call = 0; call < 16; 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 (call == 12 || call == 13 || call == 14 || call == 15) break; event_timedwait(&th->done, 50 + (call == 1 ? 3000 : 0) + (call == 2 ? 300 : 0) + (call == 3 ? 3000 : 0) + (call == 4 ? 300 : 0) + (call == 5 ? 300 : 0) + (call == 6 ? 300 : 0) + (call == 9 ? 3000 : 0) + (call == 10 ? 300 : 0) + (call == 11 ? 300 : 0) + (call == 13 ? 3000 : 0) + (call == 14 ? 300 : 0) + (call == 15 ? 3000 : 0)); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); close_fds(); } static void execute_one(void); #define WAIT_FLAGS __WALL static void loop(void) { setup_loop(); int iter = 0; for (;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); reset_loop(); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); setup_test(); execute_one(); exit(0); } int status = 0; uint64_t start = current_time_ms(); for (;;) { sleep_ms(10); if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) break; if (current_time_ms() - start < 5000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; void execute_call(int call) { intptr_t res = 0; switch (call) { case 0: // ioctl$HIDIOCGRDESCSIZE arguments: [ // fd: fd_hidraw (resource) // cmd: const = 0x80044801 (4 bytes) // arg: ptr[out, int32] { // int32 = 0x0 (4 bytes) // } // ] syscall(__NR_ioctl, /*fd=*/(intptr_t)-1, /*cmd=*/0x80044801, /*arg=*/0x200000000100ul); break; case 1: // syz_usb_connect arguments: [ // speed: usb_device_speed = 0x0 (8 bytes) // dev_len: len = 0x39 (8 bytes) // dev: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYBLOB: buffer: {12 01 00 02 00 00 00 40 d1 18 af 1e 00 00 01 // 02 03 01 09 02 27 00 01 01 00 80 fa 09 04 00 00 03 ff ff ff 00 // 07 05 81 02 00 02 00 07 05 82 02 00 02 00 07 05 03 02} (length // 0x36) // } // } // } // conn_descs: nil // ] // returns fd_usb NONFAILING(memcpy((void*)0x200000000000, "\x12\x01\x00\x02\x00\x00\x00\x40\xd1\x18\xaf\x1e\x00\x00" "\x01\x02\x03\x01\x09\x02\x27\x00\x01\x01\x00\x80\xfa\x09" "\x04\x00\x00\x03\xff\xff\xff\x00\x07\x05\x81\x02\x00\x02" "\x00\x07\x05\x82\x02\x00\x02\x00\x07\x05\x03\x02", 54)); res = -1; NONFAILING(res = syz_usb_connect(/*speed=*/0, /*dev_len=*/0x39, /*dev=*/0x200000000000, /*conn_descs=*/0)); if (res != -1) r[0] = res; break; case 2: // syz_usb_ep_write arguments: [ // fd: fd_usb (resource) // ep: int8 = 0x3 (1 bytes) // len: len = 0x8 (8 bytes) // data: ptr[in, buffer] { // buffer: {62 18 81 10 53 79 a0 6b} (length 0x8) // } // ] NONFAILING( memcpy((void*)0x200000000040, "\x62\x18\x81\x10\x53\x79\xa0\x6b", 8)); NONFAILING(syz_usb_ep_write(/*fd=*/r[0], /*ep=*/3, /*len=*/8, /*data=*/0x200000000040)); break; case 3: // syz_usb_connect arguments: [ // speed: usb_device_speed = 0x0 (8 bytes) // dev_len: len = 0x2d (8 bytes) // dev: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYRES64: ANYRES64 (resource) // } // } // } // conn_descs: nil // ] // returns fd_usb NONFAILING(*(uint64_t*)0x200000000040 = r[0]); res = -1; NONFAILING(res = syz_usb_connect(/*speed=*/0, /*dev_len=*/0x2d, /*dev=*/0x200000000040, /*conn_descs=*/0)); if (res != -1) r[1] = res; break; case 4: // syz_usb_ep_write$ath9k_ep1 arguments: [ // fd: fd_usb_ath9k (resource) // ep: const = 0x82 (1 bytes) // len: bytesize = 0x0 (8 bytes) // data: nil // ] NONFAILING( syz_usb_ep_write(/*fd=*/r[1], /*ep=*/0x82, /*len=*/0, /*data=*/0)); break; case 5: // syz_usb_control_io$cdc_ecm arguments: [ // fd: fd_usb_cdc_ecm (resource) // descs: nil // resps: ptr[in, vusb_responses_cdc_ecm] { // vusb_responses_cdc_ecm { // len: len = 0x1c (4 bytes) // generic: ptr[in, vusb_response_generic] { // vusb_response_generic { // type: usb_request_types = 0x20 (1 bytes) // req: usb_requests = 0x18 (1 bytes) // len: bytesize = 0x2 (4 bytes) // data: buffer: {02 00} (length 0x2) // } // } // USB_REQ_GET_INTERFACE: nil // USB_REQ_GET_CONFIGURATION: nil // } // } // ] NONFAILING(*(uint32_t*)0x200000000080 = 0x1c); NONFAILING(*(uint64_t*)0x200000000084 = 0x2000000000c0); NONFAILING(*(uint8_t*)0x2000000000c0 = 0x20); NONFAILING(*(uint8_t*)0x2000000000c1 = 0x18); NONFAILING(*(uint32_t*)0x2000000000c2 = 2); NONFAILING(memcpy((void*)0x2000000000c6, "\x02\x00", 2)); NONFAILING(*(uint64_t*)0x20000000008c = 0); NONFAILING(*(uint64_t*)0x200000000094 = 0); NONFAILING( syz_usb_control_io(/*fd=*/r[0], /*descs=*/0, /*resps=*/0x200000000080)); break; case 6: // syz_usb_control_io$lan78xx arguments: [ // fd: fd_usb_lan78xx (resource) // descs: nil // resps: nil // ] NONFAILING(syz_usb_control_io(/*fd=*/r[0], /*descs=*/0, /*resps=*/0)); break; case 7: // syz_open_dev$hidraw arguments: [ // dev: ptr[in, buffer] { // buffer: {2f 64 65 76 2f 68 69 64 72 61 77 23 00} (length 0xd) // } // id: intptr = 0x3 (8 bytes) // flags: open_flags = 0x300 (8 bytes) // ] // returns fd_hidraw NONFAILING(memcpy((void*)0x2000000006c0, "/dev/hidraw#\000", 13)); res = -1; NONFAILING(res = syz_open_dev(/*dev=*/0x2000000006c0, /*id=*/3, /*flags=O_TRUNC|O_NOCTTY*/ 0x300)); if (res != -1) r[2] = res; break; case 8: // ioctl$HIDIOCGRDESC arguments: [ // fd: fd_hidraw (resource) // cmd: const = 0x90044802 (4 bytes) // arg: ptr[inout, hidraw_report_descriptor] { // hidraw_report_descriptor { // size: bytesize = 0xbe2 (4 bytes) // value: buffer: {c7 7f da ce 6d 0f 08 d3 30 a8 c0 35 34 c2 11 fb 2d // b8 ff 69 67 d0 25 b4 c0 50 d8 d5 4d eb ea ab 55 a0 af d0 27 97 7e // 80 a8 38 cf 4a 36 88 a9 dc c3 99 70 9c c3 c7 e3 ea 3d 2d ee d7 69 // ad 01 33 11 8f a8 0c a6 dc 68 3f 34 44 67 d6 8f 3e 6d 78 22 8e fd // 0a c6 9b c0 74 20 18 1e 90 1c 5b 82 a3 6a a3 ee 8e 46 eb 6f 9d 3e // de d3 af 67 27 00 28 e0 32 8c 6d e3 ea 2c 54 88 a8 44 97 39 4c 5f // 0d d1 12 2b 92 cc 10 f8 f0 a9 cd 25 5d 16 6a b2 3e f6 6d 01 49 4f // 3a 7d fb 3e 02 23 34 76 a2 30 76 60 c3 ff d4 0d 50 22 82 d2 5c 51 // a3 3f 74 dd df c6 a3 8c 03 c3 1d 8e 7a 8e fd 70 ec 44 5a ac 15 a8 // 08 c5 46 f7 21 ac 36 9b 05 fd ae 73 29 53 53 a7 9a 94 4b 33 fc 69 // 76 bc 4e 8d 3f 33 e2 a5 4e 88 83 89 e6 f8 45 8e 61 2c 25 05 cb 23 // 9a 33 87 a6 c6 44 75 a1 dd d2 cd d7 4d 1c de 80 23 f2 a2 7c 3a 06 // 48 c8 06 5d 5e 73 99 f1 56 78 28 f9 ca 1b 62 89 a4 d6 7c 5d 8c 87 // b6 22 69 98 94 fb 2f fd d7 e1 87 6c 93 02 42 d6 5f bb 69 47 67 b1 // 07 f8 ba 56 06 27 d2 1a 8c 76 52 aa 0c d5 f8 0e fb 97 32 99 7a a3 // 60 47 0d 5c e5 42 50 f3 a1 3f 65 c0 65 5e 9a cd 61 28 88 ec fa 32 // 71 34 c6 4b 18 0c a5 d0 3b d9 44 da 46 88 12 7c 50 b0 56 89 d6 70 // 11 3f c9 5b 13 f6 67 d1 37 b8 63 af 51 45 f2 96 88 d1 fe fe fe 23 // 30 f0 fd 90 7e 86 46 1c 3c a0 af 23 99 6d 7b 1a 01 51 7f cc 2d e4 // 40 07 c0 6f 6d 95 1d c2 23 38 37 88 7e 73 a9 48 bd d5 96 f5 ad bc // 03 1b 38 52 fc c2 c9 e6 8b 70 13 ec 84 71 54 90 39 1d 3a 11 8a d2 // 9c cf 58 78 f3 8a 10 79 4d 50 20 b9 09 d3 40 75 09 30 c6 25 1a 6a // 0e 2e d8 c1 fc 36 52 51 d2 ac e0 75 24 92 f3 15 72 54 e4 25 e8 1a // 71 af 2e 86 97 66 e4 fc 67 ba b9 7d 68 d1 e1 a9 93 fc f0 6d 91 0c // f8 4e be 1d bd 13 ab f5 16 d5 91 5f 2f f8 3b d1 7a 24 85 92 6b 9e // a1 39 4a 72 af d7 ac 0e 8f 53 13 1d 90 b5 4b fe 1c 5d e2 18 d0 43 // 23 2a c3 47 9c f5 bc f6 cd f8 62 2f e2 0e 88 3a 0d f5 95 81 85 55 // fc 02 4c 20 b4 b3 e5 40 3d 3e 46 42 bb ea d0 0e 03 86 07 e5 9a 33 // cb a9 d5 35 58 31 ac 2f 66 34 46 c2 78 d0 0b 0e 38 0b fe f8 9a 97 // 61 e7 c9 3b 9a 02 de 77 1f e1 67 61 d9 93 9e a0 a1 81 ef ec 58 2d // 08 8c 07 25 95 c6 e1 e8 61 5e de d5 f9 2c 88 7a 2d cc 49 bc ca 76 // d5 bb 4e 45 b9 55 5b 6c 52 b9 2a 4f 6c 78 5b b8 82 97 58 50 a6 0f // 8f 04 ca 61 40 3a e4 3c 02 ee 8a d6 90 da 95 78 4d b2 71 3c cc b6 // fe c2 74 23 49 8e 99 33 16 33 08 a4 d7 01 5c 23 a4 e0 1c 31 b1 fa // 7c 0e 9b 66 46 30 d8 59 60 7b 2f 21 11 37 b4 4d 90 d4 cf 14 ec c7 // c2 69 75 35 53 b9 33 39 3d f3 82 8a d7 3a a5 59 da 46 81 5d 09 6b // 95 fe 37 0e 8b ee dd 7d 50 52 fa d3 c6 c5 d8 f1 ed 38 81 c8 fb 34 // f6 e9 44 a3 77 d8 3a 06 32 ed 6c 47 dc 26 93 fb 9c cf 87 f6 c3 de // 3e ce 88 02 55 27 a6 31 6f 49 2f 8f 6b 37 28 43 9d 93 3d d8 d1 bf // e0 55 12 5a 12 74 02 a9 48 9e 7e 87 26 fd 7c ec 9d 9b b2 df 33 11 // 62 f8 07 ce a2 69 6f 3f 0a 48 07 62 bd 0e 53 16 c8 fb 30 75 bf 4f // b2 92 7a cb 0e 41 ce f9 52 ca 2f 30 ec a2 fa 99 cd 26 08 39 7b 66 // 0a f1 4a ad 57 e8 fa 54 c4 3b 25 81 c9 f6 0d ef 44 46 a1 2e c9 9b // 6c ed 3a 93 2a e3 8a 2c 9e 5e a7 48 77 2b 8a 22 b7 6a c5 d0 1f a7 // 51 9f 92 c9 20 6b cc f7 c0 e6 8d a1 d1 51 7a ae 97 16 e5 f2 a7 c7 // 93 f9 27 9e f8 63 d2 54 88 fc c0 72 47 79 7e 97 c3 94 ba 4f c1 14 // a1 0c 46 3d 4d 98 4b b3 4b fb da c8 4b 87 38 98 c8 ce 11 4d e3 34 // 6f eb d5 0e 48 78 5c a9 9c 59 5f 23 f2 57 d4 6c 8b 39 b5 4b 70 62 // ab b9 45 5e b7 d6 ed 42 88 cf 0f c1 e0 27 bd 36 f5 43 dd 0b 4c 13 // 16 f9 aa f6 0b c2 3e 04 65 bc 0f 5e 0e 86 06 12 c7 2f 24 bf 99 ae // d2 74 70 c0 61 7a 0c 35 33 23 f4 70 1c c7 d6 d4 b8 07 b0 14 8b d2 // f1 e1 c0 06 65 1e 81 64 bc d1 c2 a3 66 0a c3 c0 c6 05 b1 2a 7d 3d // d3 0e 4b cc 94 ed b0 ae 36 e7 8b 73 6c 43 a3 b9 b1 b9 20 b4 70 4d // 62 67 33 59 b1 7c 74 db ad 94 aa 4b 0e 32 6b 92 41 ef bf eb 27 b9 // 9b 5c c9 af 35 90 74 88 5c a0 72 d0 03 53 ea 47 74 79 ee 0a c1 06 // 34 54 31 00 30 71 3d cd 21 73 d2 d5 c7 f6 8d 5f 62 f7 8f 54 78 de // 60 d0 e4 30 3a d0 df 57 b3 50 98 2d 61 81 53 95 32 5b e8 6c 18 f1 // 33 e1 0f 71 aa 84 92 49 49 82 e5 80 cc 00 f0 da 7a 1d c2 a2 5a a8 // d7 5d 6d bd c0 42 c9 ee e0 eb c8 11 b3 22 54 99 f9 05 51 36 35 9d // 40 63 e8 34 46 6d 05 66 cc c8 3c 7c 1e d8 7d 27 0b dd 94 44 5f f5 // 46 5f 42 1b 13 4b c4 be 15 1c f5 11 14 b6 98 61 66 d1 5e a9 f5 f6 // 5b c6 db cd 44 39 2f f1 f3 32 2a 5c f1 88 d1 d9 6b ac ed e7 b8 6f // 02 36 33 d9 66 d8 0d 29 83 a1 88 5c 87 24 e4 82 6a 86 dc 27 a9 5a // ba 59 5f 90 41 56 6d 66 18 73 3e ca 72 fa 1c b8 73 47 bf a0 21 b7 // 5c be 93 8c cb 89 1b 6a 75 55 d7 47 01 8b d7 f5 52 ae c0 c5 79 9f // 31 10 01 8d df b3 af 0d 1c e9 5d f7 38 ef 4b fc de 02 bb 50 7d 7d // 7b 9b 21 ad 26 e7 2f c5 4d d8 34 9a 6f 15 e6 87 e3 6e 15 75 7a 4b // f2 69 ce 9b 76 6a f6 5f a2 e6 33 65 12 93 69 45 9b c4 dc 41 14 d1 // 3e 94 c2 1f 05 e3 6a 40 da 90 46 a4 80 ed 62 5a 22 c1 91 67 27 b3 // 4b 83 c6 1f fd e3 05 e5 18 3b 1b 8a d8 b4 75 dd f7 a0 6a e0 d4 90 // 3b 16 5b 43 13 d0 91 9f ef 78 8c 36 59 2c 2f 03 82 0a cf 52 3e 52 // 80 fb e2 71 30 db 58 ed 07 05 33 07 dc 98 0d 98 30 ed 34 08 73 de // be 0a c8 dd 2e 0e f2 f7 0b 2b 51 e9 e3 a6 44 ec 5d 0d 80 c7 66 9c // b2 59 d3 ae 4b dd 41 b8 8b 15 15 9c e1 e6 45 76 2f 40 cb 76 0f 3c // 83 ab a2 b6 33 26 80 80 3d 13 83 17 0d d6 c4 e3 38 cc 1a e4 06 24 // 7d 44 a5 5d de b1 93 35 93 70 a5 d0 f3 ed 0f b2 c4 d0 49 2c 0d fa // ca 2c 7a 53 6f 7d d6 17 fa 3a ca e0 a0 e1 83 c6 61 81 17 15 4c 67 // 47 e6 54 60 34 c6 d7 41 ce 55 cf 9a 3c b2 28 1f cd 7d 64 6a 2c 6b // 13 3f 6d fa c9 92 25 35 85 2c af ad 7f 18 c9 f0 cb b3 f6 b5 fe 2c // e6 a8 2a 4a 78 d8 35 41 50 a3 93 4c d8 49 78 42 2c 36 d4 e4 14 49 // 7b f5 b9 08 07 80 fb c5 8b 5e 48 32 6c 68 4b 9e 99 8b 0d ba 80 2d // 81 0d a5 31 f4 fc f9 69 a2 0a 6e ee d9 99 3f ce 95 4d cc 90 13 34 // 54 e7 ae fa f4 55 28 48 09 29 20 1d 49 48 24 c3 a0 1f e9 c9 03 7b // a0 02 d9 49 00 5c b2 a0 49 10 4f 5b 4f 90 ac 3d 1d 42 d6 12 5f 8f // e8 a5 c6 91 6e 87 9e a6 39 a7 77 e0 cf 61 f0 01 69 b5 af e3 33 2d // 29 2a 6c 29 0e 70 a2 e1 ba 75 fb 2e 56 22 3a ae 76 4b 58 de 8a c2 // d1 0e 87 e2 63 1f 10 08 42 d5 e2 d7 54 74 89 68 b4 84 80 89 7e da // 9f 00 5f 56 a4 97 0b 12 01 12 89 04 52 24 10 d5 50 a7 bc 69 8e 09 // 09 04 c4 d9 86 e1 8e 73 cc 28 d6 6f 4a cb 43 b1 e4 3f 74 f9 d1 94 // 14 ad 22 52 09 e9 ee b7 13 35 ce 0c d0 37 fd 0b 1a 34 2d dc c3 c0 // 53 b0 7c 55 a2 48 ec 97 f2 ef 67 17 54 84 eb 84 c6 c7 82 1d 13 97 // 8b 08 ba 3d ad 13 6e 71 74 a6 49 4c 01 d5 96 c9 cd 1c 2d af b6 4e // 9e 4f 8a 2e c1 ab da 66 f7 3b ba 32 a7 38 90 fc 53 6b 12 f8 3f 89 // 51 a8 95 d2 7b 58 b7 5e 30 3c 5e 22 af 70 98 1b 16 c9 f2 9e b3 26 // 72 73 68 04 63 b2 17 f7 a3 69 5c 28 45 e6 bf f7 e3 7f 94 17 7d eb // 2e 58 29 b3 b3 53 0f 9f 3f 7d 43 ed 1a 3f f1 74 c0 4f f4 ba 9b 2a // 21 f3 e1 9e 2f 39 6c 82 51 7a 0c ed 44 ba 0a 65 c6 37 8a 7d c6 e7 // 9d 0b 8c 41 69 24 c1 2a ce 94 0b 40 ba 49 87 fd 24 cd 45 8d cd 46 // 9b c6 e5 cf 78 87 e2 0c cc a1 60 c5 35 e4 1b f2 79 73 b1 3b c4 5c // 7a bc 70 90 1d 8e 22 ae c7 d3 09 d3 34 63 a1 d3 ef 30 20 7c fb 5d // 4f 61 bf 34 4d 00 55 ec 17 8a cc 2b 76 38 3b 62 21 18 05 17 28 d5 // e0 58 4d c6 25 b9 6f 01 d5 e0 24 32 8f 8d 95 90 6e 47 5b 4f 8c 0e // 4a 81 23 28 0b f1 bf fb 8c 6d 95 82 7a 20 8d 91 f4 d0 a1 fa 4c e8 // f5 90 54 b9 b4 91 cf d8 68 d4 34 c7 38 77 40 e9 c5 e3 23 1f 63 fc // 0f 60 aa 6e fd b1 75 18 cf b6 65 d6 95 09 92 2e c7 2c 02 91 74 75 // 8d 5f 96 8f 1d 3a 17 0d 07 b6 12 c2 3d 8e 97 25 58 fa cf 83 58 34 // 9c 47 c8 95 e1 bb 8e 7f d9 68 29 67 31 4a 5b 42 41 1c 41 92 69 96 // 8a 53 43 bc c9 0d 5a a9 22 02 3c 3d fc 2f 48 c8 a8 46 fd 3f b3 a6 // 9d 3a a7 2d b7 3f 58 35 b6 2e ae 61 cb b1 46 12 b3 45 76 06 56 e7 // c5 79 53 9f d0 ca 4c 5b 35 6a 9b a0 76 be 0c 6f 24 c2 ea 33 89 c3 // 73 a7 1b 6e 15 6a 50 6e 65 84 90 e9 4a 19 8a bb 55 cd fd 13 66 7e // f5 6a 4d c9 03 5d 78 e2 9f 50 cf d0 20 05 33 e8 3f 36 5a a7 7a 6e // 0b 19 b4 be 92 10 7e 64 13 ff 45 f3 61 77 2b c2 16 25 fb 6e 0c 30 // ae 36 90 78 3a 3f c6 9f 21 39 37 d8 88 f7 c8 f6 e4 38 ff 34 3a d1 // 62 77 68 c3 bb e4 b8 41 92 cb 0b a1 03 aa f2 1f 52 30 05 a1 94 7c // 32 16 95 47 f4 b1 d0 9d 8f b1 fa e3 c2 be 96 94 b1 ee b6 c2 3b 05 // a0 16 59 10 ae 66 d1 48 3b 83 59 7c 02 12 5f 98 6b d9 9f 53 8d a9 // 3f 61 3a 97 63 00 9d 8e aa bb 3c 5a 50 71 ea 93 63 a9 fe fe 59 2f // 7e ff 3c ad 7e ba 08 1e fb 1e 64 dc 2d 6c c3 48 bc 87 7c 98 d9 a5 // f0 a4 8e 43 f1 d8 5c 37 b2 b8 02 fa 0a 68 5d e4 d7 e4 ae 16 a3 f3 // 6a 02 fb 4f 7f 8d 3b 07 12 b0 32 e7 b6 09 e8 ed 07 31 86 65 bf fb // ee a5 35 63 b5 0f 21 6c b0 b7 17 07 c6 42 3e b4 60 98 1c b3 97 1a // 28 69 97 69 a9 aa 2a 6c 43 08 bf 98 59 44 c2 79 21 19 d7 9f 89 89 // 96 ce a9 70 0d ee 87 26 cd e9 24 e9 f3 25 51 5a 80 cf 8a 3c 52 71 // 7f 40 d6 84 f1 65 0d 40 a5 95 96 7a a6 30 1c 0a a6 7c 24 06 1d 2f // 0c 36 02 d0 6f 82 6c 30 fd f3 c3 5e be d5 06 ab 6e 9a c0 19 e5 55 // 98 29 bc 19 1d 1a 27 b4 45 13 b2 2d 1f 35 a1 29 d2 af 59 2d 50 ca // 7d fb f3 87 94 a6 74 84 ac 52 92 90 a4 43 13 90 d1 dd b2 50 d0 d9 // 48 62 bf 27 27 f1 24 5c 1d a5 2e 82 e5 8f bf 1f 0f 61 3d c9 7d d7 // f2 83 ca fa 66 34 e4 fc f0 9b b0 c7 a5 ae 81 c0 b7 b5 ad fc 56 dc // df 80 16 dd c9 8c 8f 4e ff 1f f9 89 95 74 4b 5d d8 af b0 34 b4 95 // 41 f8 10 f4 ff bd 81 9f 89 14 c4 f2 3f 01 38 06 a6 b0 69 78 12 da // 1e c2 ba 6d ee 40 45 6b 20 6d 94 6f c5 0d ed d2 97 2f ea 49 f4 bd // bf fa b0 45 c0 1e 8a 18 f5 bd 29 8d 97 51 56 ea 02 92 73 a6 86 a0 // ab 67 1c 92 e3 78 f5 d9 36 69 fc 01 ff 34 fd 6e 28 0d 16 19 42 7c // 46 ff b6 1d 48 20 67 31 d0 93 0d 5d 17 aa 28 2f 53 85 28 7d 1f aa // 54 ff bc 4c 80 d1 4e 06 b6 f6 46 2d 6c b6 de 61 df 76 5f e2 d6 dc // 9a b8 ab 1d 3b 30 75 42 f2 f6 69 8b 94 e3 2a 87 9e 13 5e 14 cc 24 // 5a 96 95 b9 b3 4b d5 3b 23 96 3c} (length 0xbe2) // } // } // ] NONFAILING(*(uint32_t*)0x200000000700 = 0xbe2); NONFAILING(memcpy( (void*)0x200000000704, "\xc7\x7f\xda\xce\x6d\x0f\x08\xd3\x30\xa8\xc0\x35\x34\xc2\x11\xfb\x2d" "\xb8\xff\x69\x67\xd0\x25\xb4\xc0\x50\xd8\xd5\x4d\xeb\xea\xab\x55\xa0" "\xaf\xd0\x27\x97\x7e\x80\xa8\x38\xcf\x4a\x36\x88\xa9\xdc\xc3\x99\x70" "\x9c\xc3\xc7\xe3\xea\x3d\x2d\xee\xd7\x69\xad\x01\x33\x11\x8f\xa8\x0c" "\xa6\xdc\x68\x3f\x34\x44\x67\xd6\x8f\x3e\x6d\x78\x22\x8e\xfd\x0a\xc6" "\x9b\xc0\x74\x20\x18\x1e\x90\x1c\x5b\x82\xa3\x6a\xa3\xee\x8e\x46\xeb" "\x6f\x9d\x3e\xde\xd3\xaf\x67\x27\x00\x28\xe0\x32\x8c\x6d\xe3\xea\x2c" "\x54\x88\xa8\x44\x97\x39\x4c\x5f\x0d\xd1\x12\x2b\x92\xcc\x10\xf8\xf0" "\xa9\xcd\x25\x5d\x16\x6a\xb2\x3e\xf6\x6d\x01\x49\x4f\x3a\x7d\xfb\x3e" "\x02\x23\x34\x76\xa2\x30\x76\x60\xc3\xff\xd4\x0d\x50\x22\x82\xd2\x5c" "\x51\xa3\x3f\x74\xdd\xdf\xc6\xa3\x8c\x03\xc3\x1d\x8e\x7a\x8e\xfd\x70" "\xec\x44\x5a\xac\x15\xa8\x08\xc5\x46\xf7\x21\xac\x36\x9b\x05\xfd\xae" "\x73\x29\x53\x53\xa7\x9a\x94\x4b\x33\xfc\x69\x76\xbc\x4e\x8d\x3f\x33" "\xe2\xa5\x4e\x88\x83\x89\xe6\xf8\x45\x8e\x61\x2c\x25\x05\xcb\x23\x9a" "\x33\x87\xa6\xc6\x44\x75\xa1\xdd\xd2\xcd\xd7\x4d\x1c\xde\x80\x23\xf2" "\xa2\x7c\x3a\x06\x48\xc8\x06\x5d\x5e\x73\x99\xf1\x56\x78\x28\xf9\xca" "\x1b\x62\x89\xa4\xd6\x7c\x5d\x8c\x87\xb6\x22\x69\x98\x94\xfb\x2f\xfd" "\xd7\xe1\x87\x6c\x93\x02\x42\xd6\x5f\xbb\x69\x47\x67\xb1\x07\xf8\xba" "\x56\x06\x27\xd2\x1a\x8c\x76\x52\xaa\x0c\xd5\xf8\x0e\xfb\x97\x32\x99" "\x7a\xa3\x60\x47\x0d\x5c\xe5\x42\x50\xf3\xa1\x3f\x65\xc0\x65\x5e\x9a" "\xcd\x61\x28\x88\xec\xfa\x32\x71\x34\xc6\x4b\x18\x0c\xa5\xd0\x3b\xd9" "\x44\xda\x46\x88\x12\x7c\x50\xb0\x56\x89\xd6\x70\x11\x3f\xc9\x5b\x13" "\xf6\x67\xd1\x37\xb8\x63\xaf\x51\x45\xf2\x96\x88\xd1\xfe\xfe\xfe\x23" "\x30\xf0\xfd\x90\x7e\x86\x46\x1c\x3c\xa0\xaf\x23\x99\x6d\x7b\x1a\x01" "\x51\x7f\xcc\x2d\xe4\x40\x07\xc0\x6f\x6d\x95\x1d\xc2\x23\x38\x37\x88" "\x7e\x73\xa9\x48\xbd\xd5\x96\xf5\xad\xbc\x03\x1b\x38\x52\xfc\xc2\xc9" "\xe6\x8b\x70\x13\xec\x84\x71\x54\x90\x39\x1d\x3a\x11\x8a\xd2\x9c\xcf" "\x58\x78\xf3\x8a\x10\x79\x4d\x50\x20\xb9\x09\xd3\x40\x75\x09\x30\xc6" "\x25\x1a\x6a\x0e\x2e\xd8\xc1\xfc\x36\x52\x51\xd2\xac\xe0\x75\x24\x92" "\xf3\x15\x72\x54\xe4\x25\xe8\x1a\x71\xaf\x2e\x86\x97\x66\xe4\xfc\x67" "\xba\xb9\x7d\x68\xd1\xe1\xa9\x93\xfc\xf0\x6d\x91\x0c\xf8\x4e\xbe\x1d" "\xbd\x13\xab\xf5\x16\xd5\x91\x5f\x2f\xf8\x3b\xd1\x7a\x24\x85\x92\x6b" "\x9e\xa1\x39\x4a\x72\xaf\xd7\xac\x0e\x8f\x53\x13\x1d\x90\xb5\x4b\xfe" "\x1c\x5d\xe2\x18\xd0\x43\x23\x2a\xc3\x47\x9c\xf5\xbc\xf6\xcd\xf8\x62" "\x2f\xe2\x0e\x88\x3a\x0d\xf5\x95\x81\x85\x55\xfc\x02\x4c\x20\xb4\xb3" "\xe5\x40\x3d\x3e\x46\x42\xbb\xea\xd0\x0e\x03\x86\x07\xe5\x9a\x33\xcb" "\xa9\xd5\x35\x58\x31\xac\x2f\x66\x34\x46\xc2\x78\xd0\x0b\x0e\x38\x0b" "\xfe\xf8\x9a\x97\x61\xe7\xc9\x3b\x9a\x02\xde\x77\x1f\xe1\x67\x61\xd9" "\x93\x9e\xa0\xa1\x81\xef\xec\x58\x2d\x08\x8c\x07\x25\x95\xc6\xe1\xe8" "\x61\x5e\xde\xd5\xf9\x2c\x88\x7a\x2d\xcc\x49\xbc\xca\x76\xd5\xbb\x4e" "\x45\xb9\x55\x5b\x6c\x52\xb9\x2a\x4f\x6c\x78\x5b\xb8\x82\x97\x58\x50" "\xa6\x0f\x8f\x04\xca\x61\x40\x3a\xe4\x3c\x02\xee\x8a\xd6\x90\xda\x95" "\x78\x4d\xb2\x71\x3c\xcc\xb6\xfe\xc2\x74\x23\x49\x8e\x99\x33\x16\x33" "\x08\xa4\xd7\x01\x5c\x23\xa4\xe0\x1c\x31\xb1\xfa\x7c\x0e\x9b\x66\x46" "\x30\xd8\x59\x60\x7b\x2f\x21\x11\x37\xb4\x4d\x90\xd4\xcf\x14\xec\xc7" "\xc2\x69\x75\x35\x53\xb9\x33\x39\x3d\xf3\x82\x8a\xd7\x3a\xa5\x59\xda" "\x46\x81\x5d\x09\x6b\x95\xfe\x37\x0e\x8b\xee\xdd\x7d\x50\x52\xfa\xd3" "\xc6\xc5\xd8\xf1\xed\x38\x81\xc8\xfb\x34\xf6\xe9\x44\xa3\x77\xd8\x3a" "\x06\x32\xed\x6c\x47\xdc\x26\x93\xfb\x9c\xcf\x87\xf6\xc3\xde\x3e\xce" "\x88\x02\x55\x27\xa6\x31\x6f\x49\x2f\x8f\x6b\x37\x28\x43\x9d\x93\x3d" "\xd8\xd1\xbf\xe0\x55\x12\x5a\x12\x74\x02\xa9\x48\x9e\x7e\x87\x26\xfd" "\x7c\xec\x9d\x9b\xb2\xdf\x33\x11\x62\xf8\x07\xce\xa2\x69\x6f\x3f\x0a" "\x48\x07\x62\xbd\x0e\x53\x16\xc8\xfb\x30\x75\xbf\x4f\xb2\x92\x7a\xcb" "\x0e\x41\xce\xf9\x52\xca\x2f\x30\xec\xa2\xfa\x99\xcd\x26\x08\x39\x7b" "\x66\x0a\xf1\x4a\xad\x57\xe8\xfa\x54\xc4\x3b\x25\x81\xc9\xf6\x0d\xef" "\x44\x46\xa1\x2e\xc9\x9b\x6c\xed\x3a\x93\x2a\xe3\x8a\x2c\x9e\x5e\xa7" "\x48\x77\x2b\x8a\x22\xb7\x6a\xc5\xd0\x1f\xa7\x51\x9f\x92\xc9\x20\x6b" "\xcc\xf7\xc0\xe6\x8d\xa1\xd1\x51\x7a\xae\x97\x16\xe5\xf2\xa7\xc7\x93" "\xf9\x27\x9e\xf8\x63\xd2\x54\x88\xfc\xc0\x72\x47\x79\x7e\x97\xc3\x94" "\xba\x4f\xc1\x14\xa1\x0c\x46\x3d\x4d\x98\x4b\xb3\x4b\xfb\xda\xc8\x4b" "\x87\x38\x98\xc8\xce\x11\x4d\xe3\x34\x6f\xeb\xd5\x0e\x48\x78\x5c\xa9" "\x9c\x59\x5f\x23\xf2\x57\xd4\x6c\x8b\x39\xb5\x4b\x70\x62\xab\xb9\x45" "\x5e\xb7\xd6\xed\x42\x88\xcf\x0f\xc1\xe0\x27\xbd\x36\xf5\x43\xdd\x0b" "\x4c\x13\x16\xf9\xaa\xf6\x0b\xc2\x3e\x04\x65\xbc\x0f\x5e\x0e\x86\x06" "\x12\xc7\x2f\x24\xbf\x99\xae\xd2\x74\x70\xc0\x61\x7a\x0c\x35\x33\x23" "\xf4\x70\x1c\xc7\xd6\xd4\xb8\x07\xb0\x14\x8b\xd2\xf1\xe1\xc0\x06\x65" "\x1e\x81\x64\xbc\xd1\xc2\xa3\x66\x0a\xc3\xc0\xc6\x05\xb1\x2a\x7d\x3d" "\xd3\x0e\x4b\xcc\x94\xed\xb0\xae\x36\xe7\x8b\x73\x6c\x43\xa3\xb9\xb1" "\xb9\x20\xb4\x70\x4d\x62\x67\x33\x59\xb1\x7c\x74\xdb\xad\x94\xaa\x4b" "\x0e\x32\x6b\x92\x41\xef\xbf\xeb\x27\xb9\x9b\x5c\xc9\xaf\x35\x90\x74" "\x88\x5c\xa0\x72\xd0\x03\x53\xea\x47\x74\x79\xee\x0a\xc1\x06\x34\x54" "\x31\x00\x30\x71\x3d\xcd\x21\x73\xd2\xd5\xc7\xf6\x8d\x5f\x62\xf7\x8f" "\x54\x78\xde\x60\xd0\xe4\x30\x3a\xd0\xdf\x57\xb3\x50\x98\x2d\x61\x81" "\x53\x95\x32\x5b\xe8\x6c\x18\xf1\x33\xe1\x0f\x71\xaa\x84\x92\x49\x49" "\x82\xe5\x80\xcc\x00\xf0\xda\x7a\x1d\xc2\xa2\x5a\xa8\xd7\x5d\x6d\xbd" "\xc0\x42\xc9\xee\xe0\xeb\xc8\x11\xb3\x22\x54\x99\xf9\x05\x51\x36\x35" "\x9d\x40\x63\xe8\x34\x46\x6d\x05\x66\xcc\xc8\x3c\x7c\x1e\xd8\x7d\x27" "\x0b\xdd\x94\x44\x5f\xf5\x46\x5f\x42\x1b\x13\x4b\xc4\xbe\x15\x1c\xf5" "\x11\x14\xb6\x98\x61\x66\xd1\x5e\xa9\xf5\xf6\x5b\xc6\xdb\xcd\x44\x39" "\x2f\xf1\xf3\x32\x2a\x5c\xf1\x88\xd1\xd9\x6b\xac\xed\xe7\xb8\x6f\x02" "\x36\x33\xd9\x66\xd8\x0d\x29\x83\xa1\x88\x5c\x87\x24\xe4\x82\x6a\x86" "\xdc\x27\xa9\x5a\xba\x59\x5f\x90\x41\x56\x6d\x66\x18\x73\x3e\xca\x72" "\xfa\x1c\xb8\x73\x47\xbf\xa0\x21\xb7\x5c\xbe\x93\x8c\xcb\x89\x1b\x6a" "\x75\x55\xd7\x47\x01\x8b\xd7\xf5\x52\xae\xc0\xc5\x79\x9f\x31\x10\x01" "\x8d\xdf\xb3\xaf\x0d\x1c\xe9\x5d\xf7\x38\xef\x4b\xfc\xde\x02\xbb\x50" "\x7d\x7d\x7b\x9b\x21\xad\x26\xe7\x2f\xc5\x4d\xd8\x34\x9a\x6f\x15\xe6" "\x87\xe3\x6e\x15\x75\x7a\x4b\xf2\x69\xce\x9b\x76\x6a\xf6\x5f\xa2\xe6" "\x33\x65\x12\x93\x69\x45\x9b\xc4\xdc\x41\x14\xd1\x3e\x94\xc2\x1f\x05" "\xe3\x6a\x40\xda\x90\x46\xa4\x80\xed\x62\x5a\x22\xc1\x91\x67\x27\xb3" "\x4b\x83\xc6\x1f\xfd\xe3\x05\xe5\x18\x3b\x1b\x8a\xd8\xb4\x75\xdd\xf7" "\xa0\x6a\xe0\xd4\x90\x3b\x16\x5b\x43\x13\xd0\x91\x9f\xef\x78\x8c\x36" "\x59\x2c\x2f\x03\x82\x0a\xcf\x52\x3e\x52\x80\xfb\xe2\x71\x30\xdb\x58" "\xed\x07\x05\x33\x07\xdc\x98\x0d\x98\x30\xed\x34\x08\x73\xde\xbe\x0a" "\xc8\xdd\x2e\x0e\xf2\xf7\x0b\x2b\x51\xe9\xe3\xa6\x44\xec\x5d\x0d\x80" "\xc7\x66\x9c\xb2\x59\xd3\xae\x4b\xdd\x41\xb8\x8b\x15\x15\x9c\xe1\xe6" "\x45\x76\x2f\x40\xcb\x76\x0f\x3c\x83\xab\xa2\xb6\x33\x26\x80\x80\x3d" "\x13\x83\x17\x0d\xd6\xc4\xe3\x38\xcc\x1a\xe4\x06\x24\x7d\x44\xa5\x5d" "\xde\xb1\x93\x35\x93\x70\xa5\xd0\xf3\xed\x0f\xb2\xc4\xd0\x49\x2c\x0d" "\xfa\xca\x2c\x7a\x53\x6f\x7d\xd6\x17\xfa\x3a\xca\xe0\xa0\xe1\x83\xc6" "\x61\x81\x17\x15\x4c\x67\x47\xe6\x54\x60\x34\xc6\xd7\x41\xce\x55\xcf" "\x9a\x3c\xb2\x28\x1f\xcd\x7d\x64\x6a\x2c\x6b\x13\x3f\x6d\xfa\xc9\x92" "\x25\x35\x85\x2c\xaf\xad\x7f\x18\xc9\xf0\xcb\xb3\xf6\xb5\xfe\x2c\xe6" "\xa8\x2a\x4a\x78\xd8\x35\x41\x50\xa3\x93\x4c\xd8\x49\x78\x42\x2c\x36" "\xd4\xe4\x14\x49\x7b\xf5\xb9\x08\x07\x80\xfb\xc5\x8b\x5e\x48\x32\x6c" "\x68\x4b\x9e\x99\x8b\x0d\xba\x80\x2d\x81\x0d\xa5\x31\xf4\xfc\xf9\x69" "\xa2\x0a\x6e\xee\xd9\x99\x3f\xce\x95\x4d\xcc\x90\x13\x34\x54\xe7\xae" "\xfa\xf4\x55\x28\x48\x09\x29\x20\x1d\x49\x48\x24\xc3\xa0\x1f\xe9\xc9" "\x03\x7b\xa0\x02\xd9\x49\x00\x5c\xb2\xa0\x49\x10\x4f\x5b\x4f\x90\xac" "\x3d\x1d\x42\xd6\x12\x5f\x8f\xe8\xa5\xc6\x91\x6e\x87\x9e\xa6\x39\xa7" "\x77\xe0\xcf\x61\xf0\x01\x69\xb5\xaf\xe3\x33\x2d\x29\x2a\x6c\x29\x0e" "\x70\xa2\xe1\xba\x75\xfb\x2e\x56\x22\x3a\xae\x76\x4b\x58\xde\x8a\xc2" "\xd1\x0e\x87\xe2\x63\x1f\x10\x08\x42\xd5\xe2\xd7\x54\x74\x89\x68\xb4" "\x84\x80\x89\x7e\xda\x9f\x00\x5f\x56\xa4\x97\x0b\x12\x01\x12\x89\x04" "\x52\x24\x10\xd5\x50\xa7\xbc\x69\x8e\x09\x09\x04\xc4\xd9\x86\xe1\x8e" "\x73\xcc\x28\xd6\x6f\x4a\xcb\x43\xb1\xe4\x3f\x74\xf9\xd1\x94\x14\xad" "\x22\x52\x09\xe9\xee\xb7\x13\x35\xce\x0c\xd0\x37\xfd\x0b\x1a\x34\x2d" "\xdc\xc3\xc0\x53\xb0\x7c\x55\xa2\x48\xec\x97\xf2\xef\x67\x17\x54\x84" "\xeb\x84\xc6\xc7\x82\x1d\x13\x97\x8b\x08\xba\x3d\xad\x13\x6e\x71\x74" "\xa6\x49\x4c\x01\xd5\x96\xc9\xcd\x1c\x2d\xaf\xb6\x4e\x9e\x4f\x8a\x2e" "\xc1\xab\xda\x66\xf7\x3b\xba\x32\xa7\x38\x90\xfc\x53\x6b\x12\xf8\x3f" "\x89\x51\xa8\x95\xd2\x7b\x58\xb7\x5e\x30\x3c\x5e\x22\xaf\x70\x98\x1b" "\x16\xc9\xf2\x9e\xb3\x26\x72\x73\x68\x04\x63\xb2\x17\xf7\xa3\x69\x5c" "\x28\x45\xe6\xbf\xf7\xe3\x7f\x94\x17\x7d\xeb\x2e\x58\x29\xb3\xb3\x53" "\x0f\x9f\x3f\x7d\x43\xed\x1a\x3f\xf1\x74\xc0\x4f\xf4\xba\x9b\x2a\x21" "\xf3\xe1\x9e\x2f\x39\x6c\x82\x51\x7a\x0c\xed\x44\xba\x0a\x65\xc6\x37" "\x8a\x7d\xc6\xe7\x9d\x0b\x8c\x41\x69\x24\xc1\x2a\xce\x94\x0b\x40\xba" "\x49\x87\xfd\x24\xcd\x45\x8d\xcd\x46\x9b\xc6\xe5\xcf\x78\x87\xe2\x0c" "\xcc\xa1\x60\xc5\x35\xe4\x1b\xf2\x79\x73\xb1\x3b\xc4\x5c\x7a\xbc\x70" "\x90\x1d\x8e\x22\xae\xc7\xd3\x09\xd3\x34\x63\xa1\xd3\xef\x30\x20\x7c" "\xfb\x5d\x4f\x61\xbf\x34\x4d\x00\x55\xec\x17\x8a\xcc\x2b\x76\x38\x3b" "\x62\x21\x18\x05\x17\x28\xd5\xe0\x58\x4d\xc6\x25\xb9\x6f\x01\xd5\xe0" "\x24\x32\x8f\x8d\x95\x90\x6e\x47\x5b\x4f\x8c\x0e\x4a\x81\x23\x28\x0b" "\xf1\xbf\xfb\x8c\x6d\x95\x82\x7a\x20\x8d\x91\xf4\xd0\xa1\xfa\x4c\xe8" "\xf5\x90\x54\xb9\xb4\x91\xcf\xd8\x68\xd4\x34\xc7\x38\x77\x40\xe9\xc5" "\xe3\x23\x1f\x63\xfc\x0f\x60\xaa\x6e\xfd\xb1\x75\x18\xcf\xb6\x65\xd6" "\x95\x09\x92\x2e\xc7\x2c\x02\x91\x74\x75\x8d\x5f\x96\x8f\x1d\x3a\x17" "\x0d\x07\xb6\x12\xc2\x3d\x8e\x97\x25\x58\xfa\xcf\x83\x58\x34\x9c\x47" "\xc8\x95\xe1\xbb\x8e\x7f\xd9\x68\x29\x67\x31\x4a\x5b\x42\x41\x1c\x41" "\x92\x69\x96\x8a\x53\x43\xbc\xc9\x0d\x5a\xa9\x22\x02\x3c\x3d\xfc\x2f" "\x48\xc8\xa8\x46\xfd\x3f\xb3\xa6\x9d\x3a\xa7\x2d\xb7\x3f\x58\x35\xb6" "\x2e\xae\x61\xcb\xb1\x46\x12\xb3\x45\x76\x06\x56\xe7\xc5\x79\x53\x9f" "\xd0\xca\x4c\x5b\x35\x6a\x9b\xa0\x76\xbe\x0c\x6f\x24\xc2\xea\x33\x89" "\xc3\x73\xa7\x1b\x6e\x15\x6a\x50\x6e\x65\x84\x90\xe9\x4a\x19\x8a\xbb" "\x55\xcd\xfd\x13\x66\x7e\xf5\x6a\x4d\xc9\x03\x5d\x78\xe2\x9f\x50\xcf" "\xd0\x20\x05\x33\xe8\x3f\x36\x5a\xa7\x7a\x6e\x0b\x19\xb4\xbe\x92\x10" "\x7e\x64\x13\xff\x45\xf3\x61\x77\x2b\xc2\x16\x25\xfb\x6e\x0c\x30\xae" "\x36\x90\x78\x3a\x3f\xc6\x9f\x21\x39\x37\xd8\x88\xf7\xc8\xf6\xe4\x38" "\xff\x34\x3a\xd1\x62\x77\x68\xc3\xbb\xe4\xb8\x41\x92\xcb\x0b\xa1\x03" "\xaa\xf2\x1f\x52\x30\x05\xa1\x94\x7c\x32\x16\x95\x47\xf4\xb1\xd0\x9d" "\x8f\xb1\xfa\xe3\xc2\xbe\x96\x94\xb1\xee\xb6\xc2\x3b\x05\xa0\x16\x59" "\x10\xae\x66\xd1\x48\x3b\x83\x59\x7c\x02\x12\x5f\x98\x6b\xd9\x9f\x53" "\x8d\xa9\x3f\x61\x3a\x97\x63\x00\x9d\x8e\xaa\xbb\x3c\x5a\x50\x71\xea" "\x93\x63\xa9\xfe\xfe\x59\x2f\x7e\xff\x3c\xad\x7e\xba\x08\x1e\xfb\x1e" "\x64\xdc\x2d\x6c\xc3\x48\xbc\x87\x7c\x98\xd9\xa5\xf0\xa4\x8e\x43\xf1" "\xd8\x5c\x37\xb2\xb8\x02\xfa\x0a\x68\x5d\xe4\xd7\xe4\xae\x16\xa3\xf3" "\x6a\x02\xfb\x4f\x7f\x8d\x3b\x07\x12\xb0\x32\xe7\xb6\x09\xe8\xed\x07" "\x31\x86\x65\xbf\xfb\xee\xa5\x35\x63\xb5\x0f\x21\x6c\xb0\xb7\x17\x07" "\xc6\x42\x3e\xb4\x60\x98\x1c\xb3\x97\x1a\x28\x69\x97\x69\xa9\xaa\x2a" "\x6c\x43\x08\xbf\x98\x59\x44\xc2\x79\x21\x19\xd7\x9f\x89\x89\x96\xce" "\xa9\x70\x0d\xee\x87\x26\xcd\xe9\x24\xe9\xf3\x25\x51\x5a\x80\xcf\x8a" "\x3c\x52\x71\x7f\x40\xd6\x84\xf1\x65\x0d\x40\xa5\x95\x96\x7a\xa6\x30" "\x1c\x0a\xa6\x7c\x24\x06\x1d\x2f\x0c\x36\x02\xd0\x6f\x82\x6c\x30\xfd" "\xf3\xc3\x5e\xbe\xd5\x06\xab\x6e\x9a\xc0\x19\xe5\x55\x98\x29\xbc\x19" "\x1d\x1a\x27\xb4\x45\x13\xb2\x2d\x1f\x35\xa1\x29\xd2\xaf\x59\x2d\x50" "\xca\x7d\xfb\xf3\x87\x94\xa6\x74\x84\xac\x52\x92\x90\xa4\x43\x13\x90" "\xd1\xdd\xb2\x50\xd0\xd9\x48\x62\xbf\x27\x27\xf1\x24\x5c\x1d\xa5\x2e" "\x82\xe5\x8f\xbf\x1f\x0f\x61\x3d\xc9\x7d\xd7\xf2\x83\xca\xfa\x66\x34" "\xe4\xfc\xf0\x9b\xb0\xc7\xa5\xae\x81\xc0\xb7\xb5\xad\xfc\x56\xdc\xdf" "\x80\x16\xdd\xc9\x8c\x8f\x4e\xff\x1f\xf9\x89\x95\x74\x4b\x5d\xd8\xaf" "\xb0\x34\xb4\x95\x41\xf8\x10\xf4\xff\xbd\x81\x9f\x89\x14\xc4\xf2\x3f" "\x01\x38\x06\xa6\xb0\x69\x78\x12\xda\x1e\xc2\xba\x6d\xee\x40\x45\x6b" "\x20\x6d\x94\x6f\xc5\x0d\xed\xd2\x97\x2f\xea\x49\xf4\xbd\xbf\xfa\xb0" "\x45\xc0\x1e\x8a\x18\xf5\xbd\x29\x8d\x97\x51\x56\xea\x02\x92\x73\xa6" "\x86\xa0\xab\x67\x1c\x92\xe3\x78\xf5\xd9\x36\x69\xfc\x01\xff\x34\xfd" "\x6e\x28\x0d\x16\x19\x42\x7c\x46\xff\xb6\x1d\x48\x20\x67\x31\xd0\x93" "\x0d\x5d\x17\xaa\x28\x2f\x53\x85\x28\x7d\x1f\xaa\x54\xff\xbc\x4c\x80" "\xd1\x4e\x06\xb6\xf6\x46\x2d\x6c\xb6\xde\x61\xdf\x76\x5f\xe2\xd6\xdc" "\x9a\xb8\xab\x1d\x3b\x30\x75\x42\xf2\xf6\x69\x8b\x94\xe3\x2a\x87\x9e" "\x13\x5e\x14\xcc\x24\x5a\x96\x95\xb9\xb3\x4b\xd5\x3b\x23\x96\x3c", 3042)); syscall(__NR_ioctl, /*fd=*/r[2], /*cmd=*/0x90044802, /*arg=*/0x200000000700ul); break; case 9: // syz_usb_connect$uac1 arguments: [ // speed: usb_device_speed = 0x0 (8 bytes) // dev_len: len = 0xf0 (8 bytes) // dev: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYBLOB: buffer: {12 01 10 03 00 00 00 40 73 2b 29 00 40 00 01 // 02 03 01 09 02 de 00 03 01 05 80 07 09 04 00 00 00 01 01 00 00 // 0a 24 01 00 00 11 00 02 01 02 07 24 04 05 01 c1 a7 09 04 01 00 // 00 01 02 00 00 09 04 01 01 01 01 02 00 00 07 24 01 05 02 01 00 // 0e 24 02 01 06 01 28 08 ed 7c 8d 71 30 3c 09 24 02 01 33 04 0a // 00 2d 0a 24 02 02 a3 5a 03 00 09 1c 11 24 02 01 03 03 02 f8 8f // 58 e5 6f 6e 5f 6b 8b 80 09 05 01 09 00 00 07 01 02 07 25 01 0c // 0a 06 00 09 04 02 00 00 01 02 00 00 09 04 02 01 01 01 02 00 00 // 0a 24 02 02 00 04 03 00 09 00 0f 24 02 02 09 00 95 0c 05 e6 d0 // 16 d9 bf 73 07 24 01 03 09 01 10 07 24 01 01 01 05 00 0c 24 02 // 01 00 04 06 08 08 66 df 49 0b 24 02 01 7b 03 69 80 19 4f 3b 09 // 05 82 09 00 00 40 08 0e 07 25 01 08 07 10 00} (length 0xf0) // } // } // } // conn_descs: ptr[in, vusb_connect_descriptors] { // vusb_connect_descriptors { // qual_len: len = 0xa (4 bytes) // qual: ptr[in, usb_qualifier_descriptor] { // usb_qualifier_descriptor { // bLength: len = 0xa (1 bytes) // bDescriptorType: const = 0x6 (1 bytes) // bcdUSB: usb_versions = 0x300 (2 bytes) // bDeviceClass: int8 = 0x4 (1 bytes) // bDeviceSubClass: int8 = 0xb (1 bytes) // bDeviceProtocol: int8 = 0x4 (1 bytes) // bMaxPacketSize0: usb_device_max_packet_sizes = 0xff (1 bytes) // bNumConfigurations: int8 = 0xff (1 bytes) // bRESERVED: const = 0x0 (1 bytes) // } // } // bos_len: len = 0x9e (4 bytes) // bos: ptr[in, usb_bos_descriptor] { // usb_bos_descriptor { // bLength: const = 0x5 (1 bytes) // bDescriptorType: const = 0xf (1 bytes) // wTotalLength: len = 0x9e (2 bytes) // bNumDeviceCaps: len = 0x2 (1 bytes) // caps: array[usb_dev_cap] { // union usb_dev_cap { // generic: usb_generic_cap_descriptor { // bLength: len = 0x8d (1 bytes) // bDescriptorType: const = 0x10 (1 bytes) // bDevCapabilityType: usb_capability_types = 0x1 (1 bytes) // data: buffer: {6b e5 26 92 56 36 80 ca c3 e2 ea b9 ca 71 // 28 4d e3 29 8b bc b1 b3 9d 41 9b 51 5b f8 a9 f2 a5 a8 03 // f5 23 56 53 cf 04 29 52 62 82 73 11 26 42 b1 15 2e 95 6f // 8d 8f 2a 3b 06 01 90 37 e6 4e 84 7f cd 92 9d 7f 47 9f 21 // 5e 91 50 ab d5 6e 5c 38 3d 6f 41 4c e8 29 71 3c 04 93 b8 // de ed 33 54 69 8b fa e0 f6 3e 11 dc 94 ac ec 88 67 64 d3 // 5e a1 ad c7 ee 83 b4 85 de f8 38 e7 f0 eb a0 3a 98 b4 b2 // 25 19 28 d1 92 db e9 99 ed 10} (length 0x8a) // } // } // union usb_dev_cap { // ssp_cap: usb_ssp_cap_descriptor { // bLength: len = 0xc (1 bytes) // bDescriptorType: const = 0x10 (1 bytes) // bDevCapabilityType: const = 0xa (1 bytes) // bReserved: int8 = 0x0 (1 bytes) // bmAttributesSublinkSpeeds: len = 0x0 (0 bytes) // bmAttributesSpeedIDs: int32 = 0x800 (4 bytes) // wFunctionalitySupport: usb_ssp_cap_funcs = 0xf (2 bytes) // wReserved: int16 = 0x101 (2 bytes) // bmSublinkSpeedAttr: array[usb_ssp_cap_sublink_speeds] { // } // } // } // } // } // } // strs_len: len = 0x2 (4 bytes) // strs: array[vusb_connect_string_descriptor] { // vusb_connect_string_descriptor { // len: len = 0x9d (4 bytes) // str: ptr[in, usb_string_descriptor] { // union usb_string_descriptor { // string: usb_string_descriptor_t[array[int8, 0:256]] { // bLength: len = 0x9d (1 bytes) // bDescriptorType: const = 0x3 (1 bytes) // data: buffer: {d0 32 85 7f 3d d8 af 3d 54 17 3d 12 1e 6d // 43 33 62 e6 3b a0 84 46 3d 28 c0 c5 5c 3c 9b 9e 61 ff 0a // 37 96 f1 f2 56 67 33 ba c7 72 44 fd fd 7c 04 1e dd 3a b9 // a7 13 16 aa 53 0b 2b 51 ca 6b 6f 5a b4 bf 51 48 a9 7a 71 // fc e2 2a 48 bb 97 c4 96 9a bc f6 72 9b 3a ba 36 9b 09 c9 // 08 0f 4e 83 b3 86 79 a9 63 60 39 1d 02 a9 29 87 02 2b 32 // 1d 22 9f 6a 90 72 19 c6 1d 4c 64 b5 56 57 ab 82 0e f5 a9 // 71 3c 8b c1 85 52 bb 6f ff 09 06 9d 7f 2a 72 a8 15 62 1c // 37 92 63 8d 53 cf f1 c1} (length 0x9b) // } // } // } // } // vusb_connect_string_descriptor { // len: len = 0xd7 (4 bytes) // str: ptr[in, usb_string_descriptor] { // union usb_string_descriptor { // string: usb_string_descriptor_t[array[int8, 0:256]] { // bLength: len = 0xd7 (1 bytes) // bDescriptorType: const = 0x3 (1 bytes) // data: buffer: {ed 0a 5d 37 0c aa 93 83 41 3d ce 7d 3f 86 // 14 f2 63 32 20 3a 2d 53 cc a6 9c da cc cd 0a f7 34 f9 da // 90 00 e9 1d f1 6d a7 9f 71 90 1a 39 04 9b 75 e7 3a ef 0d // cf dd 93 dd 11 6d da af 09 08 61 d5 ff 07 87 2a 9d 0e 30 // 77 28 1c 78 d4 fe b9 8d 40 71 85 13 46 32 66 7f 4d f9 03 // 46 2b 01 d9 3f f6 89 3a cd d4 77 a6 92 8d ed ac 1a 77 f3 // fb 57 0e d1 e7 8b af 30 64 63 a4 48 5b 72 11 b1 94 3e 6d // 2a c9 77 a6 41 bb db 30 26 68 eb 1f 54 68 35 23 26 97 52 // bf 33 cc 05 5c a2 5e 34 79 6a 9f 25 6b 40 de 31 43 1f 86 // f5 c2 0b 9c 33 f2 1e 1e a0 b9 be db 6f 3d f9 ca 71 2e ba // 0f 8d c8 58 d1 9a c7 37 89 ce 0c 69 72 d3 85 d6 c0 ce d8 // 5b 4e 82 08 9d f1 b3 f8 20} (length 0xd5) // } // } // } // } // } // } // } // ] // returns fd_usb_uac1 NONFAILING(memcpy( (void*)0x2000000002c0, "\x12\x01\x10\x03\x00\x00\x00\x40\x73\x2b\x29\x00\x40\x00\x01\x02\x03" "\x01\x09\x02\xde\x00\x03\x01\x05\x80\x07\x09\x04\x00\x00\x00\x01\x01" "\x00\x00\x0a\x24\x01\x00\x00\x11\x00\x02\x01\x02\x07\x24\x04\x05\x01" "\xc1\xa7\x09\x04\x01\x00\x00\x01\x02\x00\x00\x09\x04\x01\x01\x01\x01" "\x02\x00\x00\x07\x24\x01\x05\x02\x01\x00\x0e\x24\x02\x01\x06\x01\x28" "\x08\xed\x7c\x8d\x71\x30\x3c\x09\x24\x02\x01\x33\x04\x0a\x00\x2d\x0a" "\x24\x02\x02\xa3\x5a\x03\x00\x09\x1c\x11\x24\x02\x01\x03\x03\x02\xf8" "\x8f\x58\xe5\x6f\x6e\x5f\x6b\x8b\x80\x09\x05\x01\x09\x00\x00\x07\x01" "\x02\x07\x25\x01\x0c\x0a\x06\x00\x09\x04\x02\x00\x00\x01\x02\x00\x00" "\x09\x04\x02\x01\x01\x01\x02\x00\x00\x0a\x24\x02\x02\x00\x04\x03\x00" "\x09\x00\x0f\x24\x02\x02\x09\x00\x95\x0c\x05\xe6\xd0\x16\xd9\xbf\x73" "\x07\x24\x01\x03\x09\x01\x10\x07\x24\x01\x01\x01\x05\x00\x0c\x24\x02" "\x01\x00\x04\x06\x08\x08\x66\xdf\x49\x0b\x24\x02\x01\x7b\x03\x69\x80" "\x19\x4f\x3b\x09\x05\x82\x09\x00\x00\x40\x08\x0e\x07\x25\x01\x08\x07" "\x10\x00", 240)); NONFAILING(*(uint32_t*)0x200000000680 = 0xa); NONFAILING(*(uint64_t*)0x200000000684 = 0x2000000003c0); NONFAILING(*(uint8_t*)0x2000000003c0 = 0xa); NONFAILING(*(uint8_t*)0x2000000003c1 = 6); NONFAILING(*(uint16_t*)0x2000000003c2 = 0x300); NONFAILING(*(uint8_t*)0x2000000003c4 = 4); NONFAILING(*(uint8_t*)0x2000000003c5 = 0xb); NONFAILING(*(uint8_t*)0x2000000003c6 = 4); NONFAILING(*(uint8_t*)0x2000000003c7 = -1); NONFAILING(*(uint8_t*)0x2000000003c8 = -1); NONFAILING(*(uint8_t*)0x2000000003c9 = 0); NONFAILING(*(uint32_t*)0x20000000068c = 0x9e); NONFAILING(*(uint64_t*)0x200000000690 = 0x200000000400); NONFAILING(*(uint8_t*)0x200000000400 = 5); NONFAILING(*(uint8_t*)0x200000000401 = 0xf); NONFAILING(*(uint16_t*)0x200000000402 = 0x9e); NONFAILING(*(uint8_t*)0x200000000404 = 2); NONFAILING(*(uint8_t*)0x200000000405 = 0x8d); NONFAILING(*(uint8_t*)0x200000000406 = 0x10); NONFAILING(*(uint8_t*)0x200000000407 = 1); NONFAILING(memcpy( (void*)0x200000000408, "\x6b\xe5\x26\x92\x56\x36\x80\xca\xc3\xe2\xea\xb9\xca\x71\x28\x4d\xe3" "\x29\x8b\xbc\xb1\xb3\x9d\x41\x9b\x51\x5b\xf8\xa9\xf2\xa5\xa8\x03\xf5" "\x23\x56\x53\xcf\x04\x29\x52\x62\x82\x73\x11\x26\x42\xb1\x15\x2e\x95" "\x6f\x8d\x8f\x2a\x3b\x06\x01\x90\x37\xe6\x4e\x84\x7f\xcd\x92\x9d\x7f" "\x47\x9f\x21\x5e\x91\x50\xab\xd5\x6e\x5c\x38\x3d\x6f\x41\x4c\xe8\x29" "\x71\x3c\x04\x93\xb8\xde\xed\x33\x54\x69\x8b\xfa\xe0\xf6\x3e\x11\xdc" "\x94\xac\xec\x88\x67\x64\xd3\x5e\xa1\xad\xc7\xee\x83\xb4\x85\xde\xf8" "\x38\xe7\xf0\xeb\xa0\x3a\x98\xb4\xb2\x25\x19\x28\xd1\x92\xdb\xe9\x99" "\xed\x10", 138)); NONFAILING(*(uint8_t*)0x200000000492 = 0xc); NONFAILING(*(uint8_t*)0x200000000493 = 0x10); NONFAILING(*(uint8_t*)0x200000000494 = 0xa); NONFAILING(*(uint8_t*)0x200000000495 = 0); NONFAILING(STORE_BY_BITMASK(uint32_t, , 0x200000000496, 0, 0, 5)); NONFAILING(STORE_BY_BITMASK(uint32_t, , 0x200000000496, 0x800, 5, 27)); NONFAILING(*(uint16_t*)0x20000000049a = 0xf); NONFAILING(*(uint16_t*)0x20000000049c = 0x101); NONFAILING(*(uint32_t*)0x200000000698 = 2); NONFAILING(*(uint32_t*)0x20000000069c = 0x9d); NONFAILING(*(uint64_t*)0x2000000006a0 = 0x2000000004c0); NONFAILING(*(uint8_t*)0x2000000004c0 = 0x9d); NONFAILING(*(uint8_t*)0x2000000004c1 = 3); NONFAILING(memcpy( (void*)0x2000000004c2, "\xd0\x32\x85\x7f\x3d\xd8\xaf\x3d\x54\x17\x3d\x12\x1e\x6d\x43\x33\x62" "\xe6\x3b\xa0\x84\x46\x3d\x28\xc0\xc5\x5c\x3c\x9b\x9e\x61\xff\x0a\x37" "\x96\xf1\xf2\x56\x67\x33\xba\xc7\x72\x44\xfd\xfd\x7c\x04\x1e\xdd\x3a" "\xb9\xa7\x13\x16\xaa\x53\x0b\x2b\x51\xca\x6b\x6f\x5a\xb4\xbf\x51\x48" "\xa9\x7a\x71\xfc\xe2\x2a\x48\xbb\x97\xc4\x96\x9a\xbc\xf6\x72\x9b\x3a" "\xba\x36\x9b\x09\xc9\x08\x0f\x4e\x83\xb3\x86\x79\xa9\x63\x60\x39\x1d" "\x02\xa9\x29\x87\x02\x2b\x32\x1d\x22\x9f\x6a\x90\x72\x19\xc6\x1d\x4c" "\x64\xb5\x56\x57\xab\x82\x0e\xf5\xa9\x71\x3c\x8b\xc1\x85\x52\xbb\x6f" "\xff\x09\x06\x9d\x7f\x2a\x72\xa8\x15\x62\x1c\x37\x92\x63\x8d\x53\xcf" "\xf1\xc1", 155)); NONFAILING(*(uint32_t*)0x2000000006a8 = 0xd7); NONFAILING(*(uint64_t*)0x2000000006ac = 0x200000000580); NONFAILING(*(uint8_t*)0x200000000580 = 0xd7); NONFAILING(*(uint8_t*)0x200000000581 = 3); NONFAILING(memcpy( (void*)0x200000000582, "\xed\x0a\x5d\x37\x0c\xaa\x93\x83\x41\x3d\xce\x7d\x3f\x86\x14\xf2\x63" "\x32\x20\x3a\x2d\x53\xcc\xa6\x9c\xda\xcc\xcd\x0a\xf7\x34\xf9\xda\x90" "\x00\xe9\x1d\xf1\x6d\xa7\x9f\x71\x90\x1a\x39\x04\x9b\x75\xe7\x3a\xef" "\x0d\xcf\xdd\x93\xdd\x11\x6d\xda\xaf\x09\x08\x61\xd5\xff\x07\x87\x2a" "\x9d\x0e\x30\x77\x28\x1c\x78\xd4\xfe\xb9\x8d\x40\x71\x85\x13\x46\x32" "\x66\x7f\x4d\xf9\x03\x46\x2b\x01\xd9\x3f\xf6\x89\x3a\xcd\xd4\x77\xa6" "\x92\x8d\xed\xac\x1a\x77\xf3\xfb\x57\x0e\xd1\xe7\x8b\xaf\x30\x64\x63" "\xa4\x48\x5b\x72\x11\xb1\x94\x3e\x6d\x2a\xc9\x77\xa6\x41\xbb\xdb\x30" "\x26\x68\xeb\x1f\x54\x68\x35\x23\x26\x97\x52\xbf\x33\xcc\x05\x5c\xa2" "\x5e\x34\x79\x6a\x9f\x25\x6b\x40\xde\x31\x43\x1f\x86\xf5\xc2\x0b\x9c" "\x33\xf2\x1e\x1e\xa0\xb9\xbe\xdb\x6f\x3d\xf9\xca\x71\x2e\xba\x0f\x8d" "\xc8\x58\xd1\x9a\xc7\x37\x89\xce\x0c\x69\x72\xd3\x85\xd6\xc0\xce\xd8" "\x5b\x4e\x82\x08\x9d\xf1\xb3\xf8\x20", 213)); NONFAILING(syz_usb_connect(/*speed=*/0, /*dev_len=*/0xf0, /*dev=*/0x2000000002c0, /*conn_descs=*/0x200000000680)); break; case 10: // syz_usb_control_io$uac1 arguments: [ // fd: fd_usb_uac1 (resource) // descs: nil // resps: nil // ] NONFAILING(syz_usb_control_io(/*fd=*/r[0], /*descs=*/0, /*resps=*/0)); break; case 11: // syz_usb_ep_write$ath9k_ep1 arguments: [ // fd: fd_usb_ath9k (resource) // ep: const = 0x82 (1 bytes) // len: bytesize = 0x4 (8 bytes) // data: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYBLOB: buffer: {00 00 00 4e 3b 6c b9 37 55 80 dc cd c1 d5 bb // 1a 7a 09 5d aa c4 69 36 43 74 10 8e bb 9f 1d f8 50 20 9a b7 81 // 73 b6 fe d3 b9 a1 be 2d 2f 51 26 33 7b 72 d8 94 85 fb 61 e7 7d // 2f 1c 8f ff 4a dc 69 f3 b4 a7 58 78 84 04 0a d0 6a af fa 65 38 // 80 04 ba 98 85 0b 40 b6 cc a8 c5 3b 34 e5 bf 4a c4 c1 68 33 4a // b1 0a 4c 13 0c a0 63 a6 92 63 43 69 1f 6c 0d fc 65 7b 71 07 58 // 99 9e f7 ef a9 00 55 ba ba e3 84 fd d9 db cc cd 88 e9 82 0c 02 // ae a2 93 35 c8 ad 26 80 37 ab c8 f1 ee 4d 53 9b c0 70 b7 ae 8c // f7 25 6b 41 17 24 33 d1 0a 0c ca 38 ac 52 3a d2 98 78 cd 1a 1f // d3 85 16 93 79 1d 9a 49 2f 5f a3 db 82 19 ce 84 aa 58 53 c5 d4 // c8 87 42 da cf c1 b9 76 87 73 a0 a7 96 48 de 3a bb ed 44 7f 4f // df 2a d8 2e 71 46 48 7f 41 d4 6f 38 6c 61 e2 2b 29 9a 47 f5 b6 // 81 c6 55 33 4a b9 8c 4c 39 f7 16 ca e6 69 81 42 b4 f3 08 f5 f6 // d3 94 b4 57 d7 a8 e1 f2 31 c9 a1 63 d6 b8 84 1c 4b 48 27 e7 64 // 22 00 00 00 00 00 00 00 0f 87 ab 35 cf 27 88 e8 f4 f4 37 df fa // d3 3d 6a 66 10 b5 a6 21 4a de 5a b2 2d 1a 5d 2a 11 df 9d 7e 87 // 92 03 f9 26 27 38 1d 21 0c 1d e9 76 4d 7a 35 f1 86 3c f8 0a 58 // c2 16 c6 f4 3a a9 2d 13} (length 0x167) // } // } // } // ] NONFAILING(memcpy( (void*)0x200000000140, "\x00\x00\x00\x4e\x3b\x6c\xb9\x37\x55\x80\xdc\xcd\xc1\xd5\xbb\x1a\x7a" "\x09\x5d\xaa\xc4\x69\x36\x43\x74\x10\x8e\xbb\x9f\x1d\xf8\x50\x20\x9a" "\xb7\x81\x73\xb6\xfe\xd3\xb9\xa1\xbe\x2d\x2f\x51\x26\x33\x7b\x72\xd8" "\x94\x85\xfb\x61\xe7\x7d\x2f\x1c\x8f\xff\x4a\xdc\x69\xf3\xb4\xa7\x58" "\x78\x84\x04\x0a\xd0\x6a\xaf\xfa\x65\x38\x80\x04\xba\x98\x85\x0b\x40" "\xb6\xcc\xa8\xc5\x3b\x34\xe5\xbf\x4a\xc4\xc1\x68\x33\x4a\xb1\x0a\x4c" "\x13\x0c\xa0\x63\xa6\x92\x63\x43\x69\x1f\x6c\x0d\xfc\x65\x7b\x71\x07" "\x58\x99\x9e\xf7\xef\xa9\x00\x55\xba\xba\xe3\x84\xfd\xd9\xdb\xcc\xcd" "\x88\xe9\x82\x0c\x02\xae\xa2\x93\x35\xc8\xad\x26\x80\x37\xab\xc8\xf1" "\xee\x4d\x53\x9b\xc0\x70\xb7\xae\x8c\xf7\x25\x6b\x41\x17\x24\x33\xd1" "\x0a\x0c\xca\x38\xac\x52\x3a\xd2\x98\x78\xcd\x1a\x1f\xd3\x85\x16\x93" "\x79\x1d\x9a\x49\x2f\x5f\xa3\xdb\x82\x19\xce\x84\xaa\x58\x53\xc5\xd4" "\xc8\x87\x42\xda\xcf\xc1\xb9\x76\x87\x73\xa0\xa7\x96\x48\xde\x3a\xbb" "\xed\x44\x7f\x4f\xdf\x2a\xd8\x2e\x71\x46\x48\x7f\x41\xd4\x6f\x38\x6c" "\x61\xe2\x2b\x29\x9a\x47\xf5\xb6\x81\xc6\x55\x33\x4a\xb9\x8c\x4c\x39" "\xf7\x16\xca\xe6\x69\x81\x42\xb4\xf3\x08\xf5\xf6\xd3\x94\xb4\x57\xd7" "\xa8\xe1\xf2\x31\xc9\xa1\x63\xd6\xb8\x84\x1c\x4b\x48\x27\xe7\x64\x22" "\x00\x00\x00\x00\x00\x00\x00\x0f\x87\xab\x35\xcf\x27\x88\xe8\xf4\xf4" "\x37\xdf\xfa\xd3\x3d\x6a\x66\x10\xb5\xa6\x21\x4a\xde\x5a\xb2\x2d\x1a" "\x5d\x2a\x11\xdf\x9d\x7e\x87\x92\x03\xf9\x26\x27\x38\x1d\x21\x0c\x1d" "\xe9\x76\x4d\x7a\x35\xf1\x86\x3c\xf8\x0a\x58\xc2\x16\xc6\xf4\x3a\xa9" "\x2d\x13", 359)); NONFAILING(syz_usb_ep_write(/*fd=*/r[0], /*ep=*/0x82, /*len=*/4, /*data=*/0x200000000140)); break; case 12: // ioctl$HIDIOCGRDESCSIZE arguments: [ // fd: fd_hidraw (resource) // cmd: const = 0x80044801 (4 bytes) // arg: ptr[out, int32] { // int32 = 0x0 (4 bytes) // } // ] syscall(__NR_ioctl, /*fd=*/(intptr_t)-1, /*cmd=*/0x80044801, /*arg=*/0x200000000100ul); break; case 13: // syz_usb_connect arguments: [ // speed: usb_device_speed = 0x0 (8 bytes) // dev_len: len = 0x39 (8 bytes) // dev: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYBLOB: buffer: {12 01 00 02 00 00 00 40 d1 18 af 1e 00 00 01 // 02 03 01 09 02 27 00 01 01 00 80 fa 09 04 00 00 03 ff ff ff 00 // 07 05 81 02 00 02 00 07 05 82 02 00 02 00 07 05 03 02} (length // 0x36) // } // } // } // conn_descs: nil // ] // returns fd_usb NONFAILING(memcpy((void*)0x200000000000, "\x12\x01\x00\x02\x00\x00\x00\x40\xd1\x18\xaf\x1e\x00\x00" "\x01\x02\x03\x01\x09\x02\x27\x00\x01\x01\x00\x80\xfa\x09" "\x04\x00\x00\x03\xff\xff\xff\x00\x07\x05\x81\x02\x00\x02" "\x00\x07\x05\x82\x02\x00\x02\x00\x07\x05\x03\x02", 54)); NONFAILING(syz_usb_connect(/*speed=*/0, /*dev_len=*/0x39, /*dev=*/0x200000000000, /*conn_descs=*/0)); break; case 14: // syz_usb_ep_write arguments: [ // fd: fd_usb (resource) // ep: int8 = 0x3 (1 bytes) // len: len = 0x8 (8 bytes) // data: ptr[in, buffer] { // buffer: {62 18 81 10 53 79 a0 6b} (length 0x8) // } // ] NONFAILING( memcpy((void*)0x200000000040, "\x62\x18\x81\x10\x53\x79\xa0\x6b", 8)); NONFAILING(syz_usb_ep_write(/*fd=*/r[0], /*ep=*/3, /*len=*/8, /*data=*/0x200000000040)); break; case 15: // syz_usb_connect arguments: [ // speed: usb_device_speed = 0x0 (8 bytes) // dev_len: len = 0x2d (8 bytes) // dev: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYRES64: ANYRES64 (resource) // } // } // } // conn_descs: nil // ] // returns fd_usb NONFAILING(*(uint64_t*)0x200000000040 = r[0]); NONFAILING(syz_usb_connect(/*speed=*/0, /*dev_len=*/0x2d, /*dev=*/0x200000000040, /*conn_descs=*/0)); break; } } int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); setup_sysctl(); setup_cgroups(); const char* reason; (void)reason; if ((reason = setup_binfmt_misc())) printf("the reproducer may not work as expected: binfmt_misc setup failed: " "%s\n", reason); if ((reason = setup_usb())) printf("the reproducer may not work as expected: USB injection setup " "failed: %s\n", reason); if ((reason = setup_swap())) printf("the reproducer may not work as expected: swap setup failed: %s\n", reason); install_segv_handler(); use_temporary_dir(); do_sandbox_none(); return 0; }