// https://syzkaller.appspot.com/bug?id=87ff3bc3ad02b968e5449c39c496d41cd5ceb6b9 // 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 static unsigned long long procid; 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); } 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 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_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 struct nlmsg nlmsg; #define WIFI_INITIAL_DEVICE_COUNT 2 #define WIFI_MAC_BASE {0x08, 0x02, 0x11, 0x00, 0x00, 0x00} #define WIFI_IBSS_BSSID {0x50, 0x50, 0x50, 0x50, 0x50, 0x50} #define WIFI_IBSS_SSID {0x10, 0x10, 0x10, 0x10, 0x10, 0x10} #define WIFI_DEFAULT_FREQUENCY 2412 #define WIFI_DEFAULT_SIGNAL 0 #define WIFI_DEFAULT_RX_RATE 1 #define HWSIM_CMD_REGISTER 1 #define HWSIM_CMD_FRAME 2 #define HWSIM_CMD_NEW_RADIO 4 #define HWSIM_ATTR_SUPPORT_P2P_DEVICE 14 #define HWSIM_ATTR_PERM_ADDR 22 #define IF_OPER_UP 6 struct join_ibss_props { int wiphy_freq; bool wiphy_freq_fixed; uint8_t* mac; uint8_t* ssid; int ssid_len; }; static int set_interface_state(const char* interface_name, int on) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { return -1; } memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, interface_name); int ret = ioctl(sock, SIOCGIFFLAGS, &ifr); if (ret < 0) { close(sock); return -1; } if (on) ifr.ifr_flags |= IFF_UP; else ifr.ifr_flags &= ~IFF_UP; ret = ioctl(sock, SIOCSIFFLAGS, &ifr); close(sock); if (ret < 0) { return -1; } return 0; } static int nl80211_set_interface(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32_t ifindex, uint32_t iftype, bool dofail) { struct genlmsghdr genlhdr; memset(&genlhdr, 0, sizeof(genlhdr)); genlhdr.cmd = NL80211_CMD_SET_INTERFACE; netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex)); netlink_attr(nlmsg, NL80211_ATTR_IFTYPE, &iftype, sizeof(iftype)); int err = netlink_send_ext(nlmsg, sock, 0, NULL, dofail); if (err < 0) { } return err; } static int nl80211_join_ibss(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32_t ifindex, struct join_ibss_props* props, bool dofail) { struct genlmsghdr genlhdr; memset(&genlhdr, 0, sizeof(genlhdr)); genlhdr.cmd = NL80211_CMD_JOIN_IBSS; netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex)); netlink_attr(nlmsg, NL80211_ATTR_SSID, props->ssid, props->ssid_len); netlink_attr(nlmsg, NL80211_ATTR_WIPHY_FREQ, &(props->wiphy_freq), sizeof(props->wiphy_freq)); if (props->mac) netlink_attr(nlmsg, NL80211_ATTR_MAC, props->mac, ETH_ALEN); if (props->wiphy_freq_fixed) netlink_attr(nlmsg, NL80211_ATTR_FREQ_FIXED, NULL, 0); int err = netlink_send_ext(nlmsg, sock, 0, NULL, dofail); if (err < 0) { } return err; } static int get_ifla_operstate(struct nlmsg* nlmsg, int ifindex, bool dofail) { struct ifinfomsg info; memset(&info, 0, sizeof(info)); info.ifi_family = AF_UNSPEC; info.ifi_index = ifindex; int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock == -1) { return -1; } netlink_init(nlmsg, RTM_GETLINK, 0, &info, sizeof(info)); int n; int err = netlink_send_ext(nlmsg, sock, RTM_NEWLINK, &n, dofail); close(sock); if (err) { return -1; } struct rtattr* attr = IFLA_RTA(NLMSG_DATA(nlmsg->buf)); for (; RTA_OK(attr, n); attr = RTA_NEXT(attr, n)) { if (attr->rta_type == IFLA_OPERSTATE) return *((int32_t*)RTA_DATA(attr)); } return -1; } static int await_ifla_operstate(struct nlmsg* nlmsg, char* interface, int operstate, bool dofail) { int ifindex = if_nametoindex(interface); while (true) { usleep(1000); int ret = get_ifla_operstate(nlmsg, ifindex, dofail); if (ret < 0) return ret; if (ret == operstate) return 0; } return 0; } static int nl80211_setup_ibss_interface(struct nlmsg* nlmsg, int sock, int nl80211_family_id, char* interface, struct join_ibss_props* ibss_props, bool dofail) { int ifindex = if_nametoindex(interface); if (ifindex == 0) { return -1; } int ret = nl80211_set_interface(nlmsg, sock, nl80211_family_id, ifindex, NL80211_IFTYPE_ADHOC, dofail); if (ret < 0) { return -1; } ret = set_interface_state(interface, 1); if (ret < 0) { return -1; } ret = nl80211_join_ibss(nlmsg, sock, nl80211_family_id, ifindex, ibss_props, dofail); if (ret < 0) { return -1; } return 0; } static int hwsim80211_create_device(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8_t mac_addr[ETH_ALEN]) { struct genlmsghdr genlhdr; memset(&genlhdr, 0, sizeof(genlhdr)); genlhdr.cmd = HWSIM_CMD_NEW_RADIO; netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(nlmsg, HWSIM_ATTR_SUPPORT_P2P_DEVICE, NULL, 0); netlink_attr(nlmsg, HWSIM_ATTR_PERM_ADDR, mac_addr, ETH_ALEN); int err = netlink_send(nlmsg, sock); if (err < 0) { } return err; } static void initialize_wifi_devices(void) { int rfkill = open("/dev/rfkill", O_RDWR); if (rfkill == -1) exit(1); struct rfkill_event event = {0}; event.type = RFKILL_TYPE_ALL; event.op = RFKILL_OP_CHANGE_ALL; if (write(rfkill, &event, sizeof(event)) != (ssize_t)(sizeof(event))) exit(1); close(rfkill); uint8_t mac_addr[6] = WIFI_MAC_BASE; int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (sock < 0) exit(1); int hwsim_family_id = netlink_query_family_id(&nlmsg, sock, "MAC80211_HWSIM", true); int nl80211_family_id = netlink_query_family_id(&nlmsg, sock, "nl80211", true); if (hwsim_family_id < 0 || nl80211_family_id < 0) exit(1); uint8_t ssid[] = WIFI_IBSS_SSID; uint8_t bssid[] = WIFI_IBSS_BSSID; struct join_ibss_props ibss_props = {.wiphy_freq = WIFI_DEFAULT_FREQUENCY, .wiphy_freq_fixed = true, .mac = bssid, .ssid = ssid, .ssid_len = sizeof(ssid)}; for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) { mac_addr[5] = device_id; int ret = hwsim80211_create_device(&nlmsg, sock, hwsim_family_id, mac_addr); if (ret < 0) exit(1); char interface[6] = "wlan0"; interface[4] += device_id; if (nl80211_setup_ibss_interface(&nlmsg, sock, nl80211_family_id, interface, &ibss_props, true) < 0) exit(1); } for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) { char interface[6] = "wlan0"; interface[4] += device_id; int ret = await_ifla_operstate(&nlmsg, interface, IF_OPER_UP, true); if (ret < 0) exit(1); } 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; } #define BTPROTO_HCI 1 #define ACL_LINK 1 #define SCAN_PAGE 2 typedef struct { uint8_t b[6]; } __attribute__((packed)) bdaddr_t; #define HCI_COMMAND_PKT 1 #define HCI_EVENT_PKT 4 #define HCI_VENDOR_PKT 0xff struct hci_command_hdr { uint16_t opcode; uint8_t plen; } __attribute__((packed)); struct hci_event_hdr { uint8_t evt; uint8_t plen; } __attribute__((packed)); #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { uint8_t status; uint16_t handle; bdaddr_t bdaddr; uint8_t link_type; uint8_t encr_mode; } __attribute__((packed)); #define HCI_EV_CONN_REQUEST 0x04 struct hci_ev_conn_request { bdaddr_t bdaddr; uint8_t dev_class[3]; uint8_t link_type; } __attribute__((packed)); #define HCI_EV_REMOTE_FEATURES 0x0b struct hci_ev_remote_features { uint8_t status; uint16_t handle; uint8_t features[8]; } __attribute__((packed)); #define HCI_EV_CMD_COMPLETE 0x0e struct hci_ev_cmd_complete { uint8_t ncmd; uint16_t opcode; } __attribute__((packed)); #define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a #define HCI_OP_READ_BUFFER_SIZE 0x1005 struct hci_rp_read_buffer_size { uint8_t status; uint16_t acl_mtu; uint8_t sco_mtu; uint16_t acl_max_pkt; uint16_t sco_max_pkt; } __attribute__((packed)); #define HCI_OP_READ_BD_ADDR 0x1009 struct hci_rp_read_bd_addr { uint8_t status; bdaddr_t bdaddr; } __attribute__((packed)); #define HCI_EV_LE_META 0x3e struct hci_ev_le_meta { uint8_t subevent; } __attribute__((packed)); #define HCI_EV_LE_CONN_COMPLETE 0x01 struct hci_ev_le_conn_complete { uint8_t status; uint16_t handle; uint8_t role; uint8_t bdaddr_type; bdaddr_t bdaddr; uint16_t interval; uint16_t latency; uint16_t supervision_timeout; uint8_t clk_accurancy; } __attribute__((packed)); struct hci_dev_req { uint16_t dev_id; uint32_t dev_opt; }; struct vhci_vendor_pkt_request { uint8_t type; uint8_t opcode; } __attribute__((packed)); struct vhci_pkt { uint8_t type; union { struct { uint8_t opcode; uint16_t id; } __attribute__((packed)) vendor_pkt; struct hci_command_hdr command_hdr; }; } __attribute__((packed)); #define HCIDEVUP _IOW('H', 201, int) #define HCISETSCAN _IOW('H', 221, int) static int vhci_fd = -1; static void rfkill_unblock_all() { int fd = open("/dev/rfkill", O_WRONLY); if (fd < 0) exit(1); struct rfkill_event event = {0}; event.idx = 0; event.type = RFKILL_TYPE_ALL; event.op = RFKILL_OP_CHANGE_ALL; event.soft = 0; event.hard = 0; if (write(fd, &event, sizeof(event)) < 0) exit(1); close(fd); } static void hci_send_event_packet(int fd, uint8_t evt, void* data, size_t data_len) { struct iovec iv[3]; struct hci_event_hdr hdr; hdr.evt = evt; hdr.plen = data_len; uint8_t type = HCI_EVENT_PKT; iv[0].iov_base = &type; iv[0].iov_len = sizeof(type); iv[1].iov_base = &hdr; iv[1].iov_len = sizeof(hdr); iv[2].iov_base = data; iv[2].iov_len = data_len; if (writev(fd, iv, sizeof(iv) / sizeof(struct iovec)) < 0) exit(1); } static void hci_send_event_cmd_complete(int fd, uint16_t opcode, void* data, size_t data_len) { struct iovec iv[4]; struct hci_event_hdr hdr; hdr.evt = HCI_EV_CMD_COMPLETE; hdr.plen = sizeof(struct hci_ev_cmd_complete) + data_len; struct hci_ev_cmd_complete evt_hdr; evt_hdr.ncmd = 1; evt_hdr.opcode = opcode; uint8_t type = HCI_EVENT_PKT; iv[0].iov_base = &type; iv[0].iov_len = sizeof(type); iv[1].iov_base = &hdr; iv[1].iov_len = sizeof(hdr); iv[2].iov_base = &evt_hdr; iv[2].iov_len = sizeof(evt_hdr); iv[3].iov_base = data; iv[3].iov_len = data_len; if (writev(fd, iv, sizeof(iv) / sizeof(struct iovec)) < 0) exit(1); } static bool process_command_pkt(int fd, char* buf, ssize_t buf_size) { struct hci_command_hdr* hdr = (struct hci_command_hdr*)buf; if (buf_size < (ssize_t)sizeof(struct hci_command_hdr) || hdr->plen != buf_size - sizeof(struct hci_command_hdr)) exit(1); switch (hdr->opcode) { case HCI_OP_WRITE_SCAN_ENABLE: { uint8_t status = 0; hci_send_event_cmd_complete(fd, hdr->opcode, &status, sizeof(status)); return true; } case HCI_OP_READ_BD_ADDR: { struct hci_rp_read_bd_addr rp = {0}; rp.status = 0; memset(&rp.bdaddr, 0xaa, 6); hci_send_event_cmd_complete(fd, hdr->opcode, &rp, sizeof(rp)); return false; } case HCI_OP_READ_BUFFER_SIZE: { struct hci_rp_read_buffer_size rp = {0}; rp.status = 0; rp.acl_mtu = 1021; rp.sco_mtu = 96; rp.acl_max_pkt = 4; rp.sco_max_pkt = 6; hci_send_event_cmd_complete(fd, hdr->opcode, &rp, sizeof(rp)); return false; } } char dummy[0xf9] = {0}; hci_send_event_cmd_complete(fd, hdr->opcode, dummy, sizeof(dummy)); return false; } static void* event_thread(void* arg) { while (1) { char buf[1024] = {0}; ssize_t buf_size = read(vhci_fd, buf, sizeof(buf)); if (buf_size < 0) exit(1); if (buf_size > 0 && buf[0] == HCI_COMMAND_PKT) { if (process_command_pkt(vhci_fd, buf + 1, buf_size - 1)) break; } } return NULL; } #define HCI_HANDLE_1 200 #define HCI_HANDLE_2 201 #define HCI_PRIMARY 0 #define HCI_OP_RESET 0x0c03 static void initialize_vhci() { int hci_sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (hci_sock < 0) exit(1); vhci_fd = open("/dev/vhci", O_RDWR); if (vhci_fd == -1) exit(1); const int kVhciFd = 202; if (dup2(vhci_fd, kVhciFd) < 0) exit(1); close(vhci_fd); vhci_fd = kVhciFd; struct vhci_vendor_pkt_request vendor_pkt_req = {HCI_VENDOR_PKT, HCI_PRIMARY}; if (write(vhci_fd, &vendor_pkt_req, sizeof(vendor_pkt_req)) != sizeof(vendor_pkt_req)) exit(1); struct vhci_pkt vhci_pkt; if (read(vhci_fd, &vhci_pkt, sizeof(vhci_pkt)) != sizeof(vhci_pkt)) exit(1); if (vhci_pkt.type == HCI_COMMAND_PKT && vhci_pkt.command_hdr.opcode == HCI_OP_RESET) { char response[1] = {0}; hci_send_event_cmd_complete(vhci_fd, HCI_OP_RESET, response, sizeof(response)); if (read(vhci_fd, &vhci_pkt, sizeof(vhci_pkt)) != sizeof(vhci_pkt)) exit(1); } if (vhci_pkt.type != HCI_VENDOR_PKT) exit(1); int dev_id = vhci_pkt.vendor_pkt.id; pthread_t th; if (pthread_create(&th, NULL, event_thread, NULL)) exit(1); int ret = ioctl(hci_sock, HCIDEVUP, dev_id); if (ret) { if (errno == ERFKILL) { rfkill_unblock_all(); ret = ioctl(hci_sock, HCIDEVUP, dev_id); } if (ret && errno != EALREADY) exit(1); } struct hci_dev_req dr = {0}; dr.dev_id = dev_id; dr.dev_opt = SCAN_PAGE; if (ioctl(hci_sock, HCISETSCAN, &dr)) exit(1); struct hci_ev_conn_request request; memset(&request, 0, sizeof(request)); memset(&request.bdaddr, 0xaa, 6); *(uint8_t*)&request.bdaddr.b[5] = 0x10; request.link_type = ACL_LINK; hci_send_event_packet(vhci_fd, HCI_EV_CONN_REQUEST, &request, sizeof(request)); struct hci_ev_conn_complete complete; memset(&complete, 0, sizeof(complete)); complete.status = 0; complete.handle = HCI_HANDLE_1; memset(&complete.bdaddr, 0xaa, 6); *(uint8_t*)&complete.bdaddr.b[5] = 0x10; complete.link_type = ACL_LINK; complete.encr_mode = 0; hci_send_event_packet(vhci_fd, HCI_EV_CONN_COMPLETE, &complete, sizeof(complete)); struct hci_ev_remote_features features; memset(&features, 0, sizeof(features)); features.status = 0; features.handle = HCI_HANDLE_1; hci_send_event_packet(vhci_fd, HCI_EV_REMOTE_FEATURES, &features, sizeof(features)); struct { struct hci_ev_le_meta le_meta; struct hci_ev_le_conn_complete le_conn; } le_conn; memset(&le_conn, 0, sizeof(le_conn)); le_conn.le_meta.subevent = HCI_EV_LE_CONN_COMPLETE; memset(&le_conn.le_conn.bdaddr, 0xaa, 6); *(uint8_t*)&le_conn.le_conn.bdaddr.b[5] = 0x11; le_conn.le_conn.role = 1; le_conn.le_conn.handle = HCI_HANDLE_2; hci_send_event_packet(vhci_fd, HCI_EV_LE_META, &le_conn, sizeof(le_conn)); pthread_join(th, NULL); close(hci_sock); } 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); 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); initialize_vhci(); sandbox_common(); drop_caps(); if (unshare(CLONE_NEWNET)) { } write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535"); initialize_wifi_devices(); 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_test() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); 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_usb() { if (chmod("/dev/raw-gadget", 0666)) return "failed to chmod /dev/raw-gadget"; return NULL; } #define NL802154_CMD_SET_SHORT_ADDR 11 #define NL802154_ATTR_IFINDEX 3 #define NL802154_ATTR_SHORT_ADDR 10 static const char* setup_802154() { const char* error = NULL; int sock_generic = -1; int sock_route = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock_route == -1) { error = "socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) failed"; goto fail; } sock_generic = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (sock_generic == -1) { error = "socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC) failed"; goto fail; } { int nl802154_family_id = netlink_query_family_id(&nlmsg, sock_generic, "nl802154", true); if (nl802154_family_id < 0) { error = "netlink_query_family_id failed"; goto fail; } for (int i = 0; i < 2; i++) { char devname[] = "wpan0"; devname[strlen(devname) - 1] += i; uint64_t hwaddr = 0xaaaaaaaaaaaa0002 + (i << 8); uint16_t shortaddr = 0xaaa0 + i; int ifindex = if_nametoindex(devname); struct genlmsghdr genlhdr; memset(&genlhdr, 0, sizeof(genlhdr)); genlhdr.cmd = NL802154_CMD_SET_SHORT_ADDR; netlink_init(&nlmsg, nl802154_family_id, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(&nlmsg, NL802154_ATTR_IFINDEX, &ifindex, sizeof(ifindex)); netlink_attr(&nlmsg, NL802154_ATTR_SHORT_ADDR, &shortaddr, sizeof(shortaddr)); if (netlink_send(&nlmsg, sock_generic) < 0) { error = "NL802154_CMD_SET_SHORT_ADDR failed"; goto fail; } netlink_device_change(&nlmsg, sock_route, devname, true, 0, &hwaddr, sizeof(hwaddr), 0); if (i == 0) { netlink_add_device_impl(&nlmsg, "lowpan", "lowpan0", false); netlink_done(&nlmsg); netlink_attr(&nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); if (netlink_send(&nlmsg, sock_route) < 0) { error = "netlink: adding device lowpan0 type lowpan link wpan0"; goto fail; } } } } fail: close(sock_route); close(sock_generic); return error; } 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 < 5; 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); event_timedwait(&th->done, 50 + (call == 1 ? 3000 : 0) + (call == 2 ? 300 : 0) + (call == 3 ? 300 : 0) + (call == 4 ? 300 : 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) { int iter = 0; for (;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); 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[1] = {0xffffffffffffffff}; void execute_call(int call) { intptr_t res = 0; switch (call) { case 0: // ioctl$HIDIOCGRDESC arguments: [ // fd: fd_hidraw (resource) // cmd: const = 0x90044802 (4 bytes) // arg: ptr[inout, hidraw_report_descriptor] { // hidraw_report_descriptor { // size: bytesize = 0x97c (4 bytes) // value: buffer: {e2 62 ba d1 00 2c dc 88 4d 08 1d d5 2d 36 90 58 42 // c4 59 ca f4 47 4f 62 78 fd 43 5f f4 33 8d b1 f3 07 69 cf d6 92 9e // b3 33 cc 7f a2 5e 72 67 2d c6 97 74 96 ba 79 8e a6 7f b5 14 2e 76 // 1b 5f 91 81 f0 e7 56 8f 1a 52 1d 70 07 ec ad 00 f4 4a b9 20 41 a5 // c3 a8 0d 46 09 68 2b 99 33 41 d8 25 d3 54 8e 32 19 6c 2b 8e 53 f1 // cd 6a 34 a9 80 5b 49 89 71 43 20 c5 c2 fa 3d 80 36 e8 eb 66 7a 10 // d3 36 35 30 0d 1a e1 73 9b 41 1a eb 56 d6 9d 58 fd 67 56 01 64 26 // 69 fa 36 fd 9c ed 61 f6 3c 73 eb 03 01 97 81 2b 33 3c 4c 93 ad 37 // 69 f9 2e f9 af 73 85 79 92 5a 6f 9a 49 6d b2 36 87 b9 41 c9 52 c1 // b9 c3 70 1c 41 9d ca d7 69 b4 92 2e b7 3e 2e d1 bc 93 38 d9 c6 ca // 52 25 29 99 c7 b5 1d 84 5e d9 2c bf 54 22 1b b6 db 70 bc df 9f ba // f6 c8 1a de dc 85 26 a8 b8 8a a4 b7 03 2f fa 35 52 41 8e 4f b6 05 // 0c a4 fb ff 29 68 23 7b 31 c5 a0 39 a2 56 15 88 41 8b 3c bf d3 87 // b2 f8 99 56 9a b8 01 43 9a 63 37 85 ea 61 5a fe 0d 99 0f 4f 59 15 // a3 e4 a7 78 f5 56 4a 23 1d ba e6 a4 58 72 cf bd 59 53 a6 85 38 25 // 99 dc 55 71 53 db 74 18 69 8b e7 ce eb 07 15 1e 8b 43 21 ac 2c 9e // c6 78 01 34 bc 05 89 2c b3 d7 e5 1b 6f 97 cd c5 7b 6a 1a 2f 33 e9 // e4 17 39 89 2f 4a 11 0d c1 6b 8c bb 98 20 eb 19 16 84 41 60 81 b6 // a7 57 6c 3e 27 23 40 34 f5 e4 b7 b2 90 74 53 e3 03 e8 1e 9a 57 55 // 8e 08 84 ee bd d9 0c 3c c0 e8 f0 da b6 3d ae cf c2 3f c8 2d 1b 26 // c6 c6 be 82 02 41 7c 72 e5 73 1b 6f 88 ca fa 4d 3b e7 46 36 23 fa // 2d f9 71 bf 5f 02 12 7b be 04 bf 40 7f 12 b2 be d2 f9 fc 17 77 e5 // 95 fa 38 bb 39 d4 e1 b3 e4 9a 31 82 d5 db c0 5f c6 17 2e 12 e9 7f // 82 eb c2 6a 8a 9a 52 1d 8f 48 02 71 ea 77 a4 1c c2 26 e3 66 0a 91 // 75 a1 39 32 ee 18 24 af ed e0 3d b6 2a 17 1a be 37 57 54 a5 0c ff // 6f 76 18 91 4f 9a 14 7c f9 60 28 96 65 82 4b b7 ca c9 02 df 33 42 // fb 6f 55 8b 22 b2 33 a5 de 0e 1c 52 6e 25 d1 6f 59 b2 52 b1 94 ee // 80 f9 ef cf 63 8d e4 8a e2 3d 3f 90 b4 39 f2 c3 1f 64 6d 4a 89 bc // 08 41 fb 13 91 2a c9 01 cc fc 08 5a 76 80 5e 54 21 fb 26 48 93 6d // da 2c ba ae f8 cc 22 3a 53 b4 ed cc 27 e2 7e dd 8d 64 ca ff 23 c5 // e7 83 8d ac 3e bb ef 27 35 5c 6c 9b b4 43 83 d1 b6 e5 cc 0e 41 ab // c6 71 53 0a d4 cb 9a 4b a0 48 28 c6 94 81 81 1a 82 c9 50 1b 74 e9 // 7f 87 f4 95 94 56 5f 35 92 f2 55 12 74 d0 ab b1 1b 66 cf 64 f9 fa // 0e 1b 12 fd e1 84 b7 5a e2 18 60 eb cf 32 39 47 ac cb 1f a0 b4 1b // 53 cc a9 29 cf 99 6f 74 4d eb fc 9d e2 a2 ce 17 b1 81 87 92 78 12 // 4f ab 63 c8 ae b0 3d 1d bb cf 7f 6f a2 f3 94 80 17 3f bc 87 ea 7c // d1 13 b6 0c 93 95 9c 92 4b b6 6b 8c f4 a7 dc 94 cc 2e 7d 07 8d 94 // cb ad ed ee 95 83 76 c8 92 a8 4f df 5c a1 bf 3d 16 c1 16 45 1b c3 // 5c 77 76 1f eb 1e 95 0e b2 b8 4e f4 46 18 7b 4e 84 bb 94 43 fa 26 // b0 76 27 5d e1 4c e7 e6 2f 0e 48 a5 d4 70 31 df 8a 0b a5 62 0b e6 // fe 93 fd c1 ba 83 d2 ca 47 44 00 ce 9a 43 22 63 58 67 b5 0a 9e 11 // e4 96 da 0c 5c 81 46 a1 06 ea 7c 14 c3 9b b0 ca b3 49 0b 38 ef 44 // 9d 64 82 e6 d6 9a bc 7c 19 8d 09 c5 d1 d8 97 45 98 88 38 e0 b4 1d // cf 6a 9f a1 ed e1 2d cd ee e8 1d 80 a9 9a 43 9c 80 5c 4d b2 f2 47 // 58 66 36 f2 61 1e e1 ef 54 99 b6 28 7f 78 6e 99 be c2 3c 66 1f 36 // 3b 37 6c b4 86 ba 7d 0f 7e 50 7c 94 b3 88 db 24 98 0a 3c a0 20 c5 // 17 f1 f9 3c 40 73 84 b8 03 72 67 00 7e 5d a1 f4 63 0b c5 08 d9 a3 // 8a bf f2 67 bf 36 62 3a 52 17 d8 7f ef 75 76 fc 9f bd 11 fb e2 87 // 67 af f0 9f 09 b7 d5 26 64 18 4a da 06 c0 8f 0e 51 aa b9 7d 07 b3 // ac 9b d5 4c 41 30 c6 60 8d c8 c4 64 d4 2b 7d ae 83 cb 7c 30 93 41 // 3c f0 bf ec 9c d7 a5 e2 db 8a 8a 60 9e 6e 09 57 79 3d 52 a1 12 d6 // 61 7d bf 6e 32 38 5f bc 4c 93 dc 31 ee 57 ee 20 19 1e 27 6d 55 c1 // 51 6e 95 b4 23 c0 21 43 3e 52 38 09 c1 2a f9 eb 5b 97 df 14 4b 94 // a4 4b f9 bd ea 01 c1 68 db e6 75 0d 4f 58 f0 9b 2d 29 9c b0 b9 a2 // aa cd 1c 21 6f dc a7 49 f7 ef 15 17 d4 56 93 ac 4c 7d 1b ed 4f b4 // 15 d7 d5 4d c2 2a a4 d3 81 3c b5 29 5d f5 22 28 e0 80 12 e7 81 76 // 97 4c f6 f6 dd ab 07 14 42 7f ae c9 5f 3c 4b 9c 9e 4c 65 d9 62 d3 // 2c 5b 65 e6 a4 ba 44 ad 9a 05 37 90 7a 6d 3d 0b bc bd 0c 6b bb e9 // e5 47 bf 4c 4d bf 72 d6 ab e3 00 3b e7 06 e4 d8 c3 d8 3d 02 4c 1f // a5 ca ba f7 8c 47 23 5c 6c db db 66 51 3e bd 56 d0 e6 6e 38 b4 82 // 67 cb 0e 13 8e bc ac fe ed 37 13 ea 99 17 d2 e8 23 45 9c 01 35 e9 // d9 f0 fa 20 dd f2 c5 b3 7f cc 3c 89 67 95 fc 6f 89 5d 61 34 d9 22 // 16 79 4c 66 6e 4b 47 44 c2 c4 83 38 fe eb 83 08 ab 89 3a c8 7d 59 // 3e 89 c7 1b 30 e6 22 29 15 1d 05 aa eb 03 4b 16 c8 e0 29 79 c3 3a // 0e 59 ac 0e c5 04 01 22 f0 ce 76 23 48 ef 6d 0e 31 d4 d6 af d1 53 // d2 49 ca b8 39 9e 52 61 55 ba 90 15 81 46 79 38 87 c7 04 0a 1c 02 // 10 3f 90 73 42 18 fe 3e 5d 3f 10 16 47 1f 53 ce a6 d8 3b fc fd 04 // 65 dc 52 20 ee 4c cd da c0 bb 3a e1 33 c0 bd a1 95 3c c0 87 f3 a5 // 3a 23 f7 7b c3 35 4a d9 de 4d 56 95 08 c1 41 e1 21 9e 00 f5 6b 66 // 26 c8 b0 62 e8 16 a3 15 1c 38 93 55 2b 41 1e c6 93 70 9f f3 0c 94 // fb 47 d0 8e 95 a4 b1 54 72 1d 28 73 6a 1c 2a 11 78 98 c4 2d 09 d6 // ee 02 58 6c 72 81 9f cc 7c f3 7d ad 3e e5 ae 59 4f ce f9 bd 56 a5 // d8 73 7e 50 5f dc d2 73 44 a3 31 2e 49 c9 f4 19 b3 74 f1 91 f9 17 // 67 4e 7c d7 ce 77 25 cd f3 15 91 1b e6 f4 e3 bf ef bf 3f c0 42 6b // 07 63 70 08 ba 03 28 3c 2d dc 82 25 09 f8 0b 3a ab 82 fa e5 73 50 // 02 5b 87 9a fe b1 c4 1d 17 4f 85 aa a2 98 96 12 c8 1e d5 da d0 4f // 1c 95 f1 cf a1 b8 87 14 e4 c7 d7 b3 c1 72 a0 d7 6f 31 ff 3c 84 d6 // b7 32 72 05 ff 53 5e 55 1f 4f 7a 5d f9 75 8f 12 4d f1 91 36 f8 5c // d1 03 98 26 35 0e 62 96 3f 63 e0 a2 49 a4 96 be ac 8f 77 70 d3 93 // b2 2f 00 95 30 29 1d 17 22 8c 4a a8 e2 3f bb 62 8e e4 7b 5b 24 71 // 13 f6 aa 56 66 ba 73 4f 3c 19 38 43 0f 67 80 44 97 c8 4e 18 fd e4 // a8 b6 ef 70 f7 f0 90 98 90 c3 78 6a 04 92 e3 bf 37 8b 14 3b 9f 22 // 30 34 dd 68 c6 33 a0 59 12 16 34 20 43 ab 7b 86 a1 34 48 cc 47 ec // 59 df 3a d5 8e e7 56 e9 56 00 e9 d9 e3 0a cd 96 c3 59 9e 84 c1 80 // 64 5d 23 af 0a 45 59 f4 f2 3d 4d e1 23 8c 37 38 59 e8 5e 76 dc e3 // cf 2b a9 2d e1 2f 9c b6 d5 74 ba 37 c1 b4 bf e4 1a 40 d4 03 f2 91 // d7 e4 fb d7 c5 23 98 05 43 44 66 bc 28 60 cd e3 33 b9 23 a6 82 76 // d4 e6 a0 fc c0 b8 3c 43 36 71 94 3c 1c 66 7c d3 30 a5 0b 31 a9 90 // cf aa fc 62 35 a7 c2 f4 95 b8 97 26 b8 7a a9 82 35 c1 ba 9d 67 40 // 3e dc 60 d7 c7 fb ac 0d 33 19 67 4c 28 16 cd aa bb 8d 9b c2 a2 bc // 3a 13 4a 4b dd 14 3f a3 e6 0c cb 15 7f 73 97 2a b1 6f 4a 02 cb 5e // c1 9b 68 98 93 c3 86 9c 74 db a9 c3 cf 3e 83 c9 25 e8 91 4c ca d3 // 0e 32 86 d7 d4 e9 69 56 46 e9 a5 7b aa 39 03 3e 07 76 b7 8a a4 64 // 22 10 59 19 0f c7 50 85 ab ad c1 0b 72 08 30 20 0c d2 db 77 a8 62 // d1 f4 d6 7e aa 68 0a 45 fb 6c 31 db 6c 2b 10 f2 7a 00 63 01 fa 03 // 66 b5 68 d5 f5 06 6e dc 28 19 67 2e 7b c8 0a 4e 65 19 35 33 b3 c1 // 57 24 2b cc 1b df 66 e2 1f 64 52 8f 15 30 0d 09 56 db 54 f0 f6 3f // c4 cb 8d 84 29 7d 3c 70 53 6f 1f b6 c2 dd 76 6d 44 6a 18 6b 8b 33 // d1 e7 58 84 5d fe 15 6a 29 9c 11 04 ad b4 25 f1 72 b6 c5 05 88 a4 // 54 4b 90 71 9f d1 00 d2 44 ce a4 f7 a2 98 2c bb 93 95 4d 66 af 60 // 0a ae 02 7a 6f 00 4b 5c 04 c1 3b f6 79 9d f5 3e cb 63 30 bc f3 ac // 90 3a 9d 1b b6 9e 5c 57 00 7e 9d a3 42 ce 5f 1c 16 ed 1c 90 88 55 // f2 4f d0 c5 86 a7 fc 4e 3e 35 f9 bd 9c e0 70 c7 3e e5 bd 90 33 97 // c3 1d d5 54 08 e0 15 94 7c 96 76 38 e7 af 59 78 6b 15 94 31 d8 b4 // 05 5b 7d e7 5a 31 23 3a 05 0d 6e 0a ad 8b 1c dc 5b 45 3d 03 d1 c9 // 89 7e 9b 01 eb 47 9d f2 56 b3 47 52 76 e1 ca e8 ab e1 bb 24 a1 b1 // 6c 11 c3 55 76 72 35 55 f2 49 64 a9 12 5d 97 0a db 2b 96 4e f2 8e // b8 5b 9a 5c 3f 1e 64 89 e7 e2 11 8c 47 08 fc 18 32 8f d4 da 7d b8 // e1 43 91 75 81 b6 77 4b 89 a5 3c 28 b0 c4 96 55 53 17 55 e2 27 a5 // f4 86 74 5b 6e 38 b0 2e cb d8 07 2d a6 5a b1 1a d8 1a a3 bf 0f d4 // f4 ab 8e 87 15 93 f2 2d 68 19 b4 9f 71} (length 0x97c) // } // } // ] *(uint32_t*)0x2000000008c0 = 0x97c; memcpy( (void*)0x2000000008c4, "\xe2\x62\xba\xd1\x00\x2c\xdc\x88\x4d\x08\x1d\xd5\x2d\x36\x90\x58\x42" "\xc4\x59\xca\xf4\x47\x4f\x62\x78\xfd\x43\x5f\xf4\x33\x8d\xb1\xf3\x07" "\x69\xcf\xd6\x92\x9e\xb3\x33\xcc\x7f\xa2\x5e\x72\x67\x2d\xc6\x97\x74" "\x96\xba\x79\x8e\xa6\x7f\xb5\x14\x2e\x76\x1b\x5f\x91\x81\xf0\xe7\x56" "\x8f\x1a\x52\x1d\x70\x07\xec\xad\x00\xf4\x4a\xb9\x20\x41\xa5\xc3\xa8" "\x0d\x46\x09\x68\x2b\x99\x33\x41\xd8\x25\xd3\x54\x8e\x32\x19\x6c\x2b" "\x8e\x53\xf1\xcd\x6a\x34\xa9\x80\x5b\x49\x89\x71\x43\x20\xc5\xc2\xfa" "\x3d\x80\x36\xe8\xeb\x66\x7a\x10\xd3\x36\x35\x30\x0d\x1a\xe1\x73\x9b" "\x41\x1a\xeb\x56\xd6\x9d\x58\xfd\x67\x56\x01\x64\x26\x69\xfa\x36\xfd" "\x9c\xed\x61\xf6\x3c\x73\xeb\x03\x01\x97\x81\x2b\x33\x3c\x4c\x93\xad" "\x37\x69\xf9\x2e\xf9\xaf\x73\x85\x79\x92\x5a\x6f\x9a\x49\x6d\xb2\x36" "\x87\xb9\x41\xc9\x52\xc1\xb9\xc3\x70\x1c\x41\x9d\xca\xd7\x69\xb4\x92" "\x2e\xb7\x3e\x2e\xd1\xbc\x93\x38\xd9\xc6\xca\x52\x25\x29\x99\xc7\xb5" "\x1d\x84\x5e\xd9\x2c\xbf\x54\x22\x1b\xb6\xdb\x70\xbc\xdf\x9f\xba\xf6" "\xc8\x1a\xde\xdc\x85\x26\xa8\xb8\x8a\xa4\xb7\x03\x2f\xfa\x35\x52\x41" "\x8e\x4f\xb6\x05\x0c\xa4\xfb\xff\x29\x68\x23\x7b\x31\xc5\xa0\x39\xa2" "\x56\x15\x88\x41\x8b\x3c\xbf\xd3\x87\xb2\xf8\x99\x56\x9a\xb8\x01\x43" "\x9a\x63\x37\x85\xea\x61\x5a\xfe\x0d\x99\x0f\x4f\x59\x15\xa3\xe4\xa7" "\x78\xf5\x56\x4a\x23\x1d\xba\xe6\xa4\x58\x72\xcf\xbd\x59\x53\xa6\x85" "\x38\x25\x99\xdc\x55\x71\x53\xdb\x74\x18\x69\x8b\xe7\xce\xeb\x07\x15" "\x1e\x8b\x43\x21\xac\x2c\x9e\xc6\x78\x01\x34\xbc\x05\x89\x2c\xb3\xd7" "\xe5\x1b\x6f\x97\xcd\xc5\x7b\x6a\x1a\x2f\x33\xe9\xe4\x17\x39\x89\x2f" "\x4a\x11\x0d\xc1\x6b\x8c\xbb\x98\x20\xeb\x19\x16\x84\x41\x60\x81\xb6" "\xa7\x57\x6c\x3e\x27\x23\x40\x34\xf5\xe4\xb7\xb2\x90\x74\x53\xe3\x03" "\xe8\x1e\x9a\x57\x55\x8e\x08\x84\xee\xbd\xd9\x0c\x3c\xc0\xe8\xf0\xda" "\xb6\x3d\xae\xcf\xc2\x3f\xc8\x2d\x1b\x26\xc6\xc6\xbe\x82\x02\x41\x7c" "\x72\xe5\x73\x1b\x6f\x88\xca\xfa\x4d\x3b\xe7\x46\x36\x23\xfa\x2d\xf9" "\x71\xbf\x5f\x02\x12\x7b\xbe\x04\xbf\x40\x7f\x12\xb2\xbe\xd2\xf9\xfc" "\x17\x77\xe5\x95\xfa\x38\xbb\x39\xd4\xe1\xb3\xe4\x9a\x31\x82\xd5\xdb" "\xc0\x5f\xc6\x17\x2e\x12\xe9\x7f\x82\xeb\xc2\x6a\x8a\x9a\x52\x1d\x8f" "\x48\x02\x71\xea\x77\xa4\x1c\xc2\x26\xe3\x66\x0a\x91\x75\xa1\x39\x32" "\xee\x18\x24\xaf\xed\xe0\x3d\xb6\x2a\x17\x1a\xbe\x37\x57\x54\xa5\x0c" "\xff\x6f\x76\x18\x91\x4f\x9a\x14\x7c\xf9\x60\x28\x96\x65\x82\x4b\xb7" "\xca\xc9\x02\xdf\x33\x42\xfb\x6f\x55\x8b\x22\xb2\x33\xa5\xde\x0e\x1c" "\x52\x6e\x25\xd1\x6f\x59\xb2\x52\xb1\x94\xee\x80\xf9\xef\xcf\x63\x8d" "\xe4\x8a\xe2\x3d\x3f\x90\xb4\x39\xf2\xc3\x1f\x64\x6d\x4a\x89\xbc\x08" "\x41\xfb\x13\x91\x2a\xc9\x01\xcc\xfc\x08\x5a\x76\x80\x5e\x54\x21\xfb" "\x26\x48\x93\x6d\xda\x2c\xba\xae\xf8\xcc\x22\x3a\x53\xb4\xed\xcc\x27" "\xe2\x7e\xdd\x8d\x64\xca\xff\x23\xc5\xe7\x83\x8d\xac\x3e\xbb\xef\x27" "\x35\x5c\x6c\x9b\xb4\x43\x83\xd1\xb6\xe5\xcc\x0e\x41\xab\xc6\x71\x53" "\x0a\xd4\xcb\x9a\x4b\xa0\x48\x28\xc6\x94\x81\x81\x1a\x82\xc9\x50\x1b" "\x74\xe9\x7f\x87\xf4\x95\x94\x56\x5f\x35\x92\xf2\x55\x12\x74\xd0\xab" "\xb1\x1b\x66\xcf\x64\xf9\xfa\x0e\x1b\x12\xfd\xe1\x84\xb7\x5a\xe2\x18" "\x60\xeb\xcf\x32\x39\x47\xac\xcb\x1f\xa0\xb4\x1b\x53\xcc\xa9\x29\xcf" "\x99\x6f\x74\x4d\xeb\xfc\x9d\xe2\xa2\xce\x17\xb1\x81\x87\x92\x78\x12" "\x4f\xab\x63\xc8\xae\xb0\x3d\x1d\xbb\xcf\x7f\x6f\xa2\xf3\x94\x80\x17" "\x3f\xbc\x87\xea\x7c\xd1\x13\xb6\x0c\x93\x95\x9c\x92\x4b\xb6\x6b\x8c" "\xf4\xa7\xdc\x94\xcc\x2e\x7d\x07\x8d\x94\xcb\xad\xed\xee\x95\x83\x76" "\xc8\x92\xa8\x4f\xdf\x5c\xa1\xbf\x3d\x16\xc1\x16\x45\x1b\xc3\x5c\x77" "\x76\x1f\xeb\x1e\x95\x0e\xb2\xb8\x4e\xf4\x46\x18\x7b\x4e\x84\xbb\x94" "\x43\xfa\x26\xb0\x76\x27\x5d\xe1\x4c\xe7\xe6\x2f\x0e\x48\xa5\xd4\x70" "\x31\xdf\x8a\x0b\xa5\x62\x0b\xe6\xfe\x93\xfd\xc1\xba\x83\xd2\xca\x47" "\x44\x00\xce\x9a\x43\x22\x63\x58\x67\xb5\x0a\x9e\x11\xe4\x96\xda\x0c" "\x5c\x81\x46\xa1\x06\xea\x7c\x14\xc3\x9b\xb0\xca\xb3\x49\x0b\x38\xef" "\x44\x9d\x64\x82\xe6\xd6\x9a\xbc\x7c\x19\x8d\x09\xc5\xd1\xd8\x97\x45" "\x98\x88\x38\xe0\xb4\x1d\xcf\x6a\x9f\xa1\xed\xe1\x2d\xcd\xee\xe8\x1d" "\x80\xa9\x9a\x43\x9c\x80\x5c\x4d\xb2\xf2\x47\x58\x66\x36\xf2\x61\x1e" "\xe1\xef\x54\x99\xb6\x28\x7f\x78\x6e\x99\xbe\xc2\x3c\x66\x1f\x36\x3b" "\x37\x6c\xb4\x86\xba\x7d\x0f\x7e\x50\x7c\x94\xb3\x88\xdb\x24\x98\x0a" "\x3c\xa0\x20\xc5\x17\xf1\xf9\x3c\x40\x73\x84\xb8\x03\x72\x67\x00\x7e" "\x5d\xa1\xf4\x63\x0b\xc5\x08\xd9\xa3\x8a\xbf\xf2\x67\xbf\x36\x62\x3a" "\x52\x17\xd8\x7f\xef\x75\x76\xfc\x9f\xbd\x11\xfb\xe2\x87\x67\xaf\xf0" "\x9f\x09\xb7\xd5\x26\x64\x18\x4a\xda\x06\xc0\x8f\x0e\x51\xaa\xb9\x7d" "\x07\xb3\xac\x9b\xd5\x4c\x41\x30\xc6\x60\x8d\xc8\xc4\x64\xd4\x2b\x7d" "\xae\x83\xcb\x7c\x30\x93\x41\x3c\xf0\xbf\xec\x9c\xd7\xa5\xe2\xdb\x8a" "\x8a\x60\x9e\x6e\x09\x57\x79\x3d\x52\xa1\x12\xd6\x61\x7d\xbf\x6e\x32" "\x38\x5f\xbc\x4c\x93\xdc\x31\xee\x57\xee\x20\x19\x1e\x27\x6d\x55\xc1" "\x51\x6e\x95\xb4\x23\xc0\x21\x43\x3e\x52\x38\x09\xc1\x2a\xf9\xeb\x5b" "\x97\xdf\x14\x4b\x94\xa4\x4b\xf9\xbd\xea\x01\xc1\x68\xdb\xe6\x75\x0d" "\x4f\x58\xf0\x9b\x2d\x29\x9c\xb0\xb9\xa2\xaa\xcd\x1c\x21\x6f\xdc\xa7" "\x49\xf7\xef\x15\x17\xd4\x56\x93\xac\x4c\x7d\x1b\xed\x4f\xb4\x15\xd7" "\xd5\x4d\xc2\x2a\xa4\xd3\x81\x3c\xb5\x29\x5d\xf5\x22\x28\xe0\x80\x12" "\xe7\x81\x76\x97\x4c\xf6\xf6\xdd\xab\x07\x14\x42\x7f\xae\xc9\x5f\x3c" "\x4b\x9c\x9e\x4c\x65\xd9\x62\xd3\x2c\x5b\x65\xe6\xa4\xba\x44\xad\x9a" "\x05\x37\x90\x7a\x6d\x3d\x0b\xbc\xbd\x0c\x6b\xbb\xe9\xe5\x47\xbf\x4c" "\x4d\xbf\x72\xd6\xab\xe3\x00\x3b\xe7\x06\xe4\xd8\xc3\xd8\x3d\x02\x4c" "\x1f\xa5\xca\xba\xf7\x8c\x47\x23\x5c\x6c\xdb\xdb\x66\x51\x3e\xbd\x56" "\xd0\xe6\x6e\x38\xb4\x82\x67\xcb\x0e\x13\x8e\xbc\xac\xfe\xed\x37\x13" "\xea\x99\x17\xd2\xe8\x23\x45\x9c\x01\x35\xe9\xd9\xf0\xfa\x20\xdd\xf2" "\xc5\xb3\x7f\xcc\x3c\x89\x67\x95\xfc\x6f\x89\x5d\x61\x34\xd9\x22\x16" "\x79\x4c\x66\x6e\x4b\x47\x44\xc2\xc4\x83\x38\xfe\xeb\x83\x08\xab\x89" "\x3a\xc8\x7d\x59\x3e\x89\xc7\x1b\x30\xe6\x22\x29\x15\x1d\x05\xaa\xeb" "\x03\x4b\x16\xc8\xe0\x29\x79\xc3\x3a\x0e\x59\xac\x0e\xc5\x04\x01\x22" "\xf0\xce\x76\x23\x48\xef\x6d\x0e\x31\xd4\xd6\xaf\xd1\x53\xd2\x49\xca" "\xb8\x39\x9e\x52\x61\x55\xba\x90\x15\x81\x46\x79\x38\x87\xc7\x04\x0a" "\x1c\x02\x10\x3f\x90\x73\x42\x18\xfe\x3e\x5d\x3f\x10\x16\x47\x1f\x53" "\xce\xa6\xd8\x3b\xfc\xfd\x04\x65\xdc\x52\x20\xee\x4c\xcd\xda\xc0\xbb" "\x3a\xe1\x33\xc0\xbd\xa1\x95\x3c\xc0\x87\xf3\xa5\x3a\x23\xf7\x7b\xc3" "\x35\x4a\xd9\xde\x4d\x56\x95\x08\xc1\x41\xe1\x21\x9e\x00\xf5\x6b\x66" "\x26\xc8\xb0\x62\xe8\x16\xa3\x15\x1c\x38\x93\x55\x2b\x41\x1e\xc6\x93" "\x70\x9f\xf3\x0c\x94\xfb\x47\xd0\x8e\x95\xa4\xb1\x54\x72\x1d\x28\x73" "\x6a\x1c\x2a\x11\x78\x98\xc4\x2d\x09\xd6\xee\x02\x58\x6c\x72\x81\x9f" "\xcc\x7c\xf3\x7d\xad\x3e\xe5\xae\x59\x4f\xce\xf9\xbd\x56\xa5\xd8\x73" "\x7e\x50\x5f\xdc\xd2\x73\x44\xa3\x31\x2e\x49\xc9\xf4\x19\xb3\x74\xf1" "\x91\xf9\x17\x67\x4e\x7c\xd7\xce\x77\x25\xcd\xf3\x15\x91\x1b\xe6\xf4" "\xe3\xbf\xef\xbf\x3f\xc0\x42\x6b\x07\x63\x70\x08\xba\x03\x28\x3c\x2d" "\xdc\x82\x25\x09\xf8\x0b\x3a\xab\x82\xfa\xe5\x73\x50\x02\x5b\x87\x9a" "\xfe\xb1\xc4\x1d\x17\x4f\x85\xaa\xa2\x98\x96\x12\xc8\x1e\xd5\xda\xd0" "\x4f\x1c\x95\xf1\xcf\xa1\xb8\x87\x14\xe4\xc7\xd7\xb3\xc1\x72\xa0\xd7" "\x6f\x31\xff\x3c\x84\xd6\xb7\x32\x72\x05\xff\x53\x5e\x55\x1f\x4f\x7a" "\x5d\xf9\x75\x8f\x12\x4d\xf1\x91\x36\xf8\x5c\xd1\x03\x98\x26\x35\x0e" "\x62\x96\x3f\x63\xe0\xa2\x49\xa4\x96\xbe\xac\x8f\x77\x70\xd3\x93\xb2" "\x2f\x00\x95\x30\x29\x1d\x17\x22\x8c\x4a\xa8\xe2\x3f\xbb\x62\x8e\xe4" "\x7b\x5b\x24\x71\x13\xf6\xaa\x56\x66\xba\x73\x4f\x3c\x19\x38\x43\x0f" "\x67\x80\x44\x97\xc8\x4e\x18\xfd\xe4\xa8\xb6\xef\x70\xf7\xf0\x90\x98" "\x90\xc3\x78\x6a\x04\x92\xe3\xbf\x37\x8b\x14\x3b\x9f\x22\x30\x34\xdd" "\x68\xc6\x33\xa0\x59\x12\x16\x34\x20\x43\xab\x7b\x86\xa1\x34\x48\xcc" "\x47\xec\x59\xdf\x3a\xd5\x8e\xe7\x56\xe9\x56\x00\xe9\xd9\xe3\x0a\xcd" "\x96\xc3\x59\x9e\x84\xc1\x80\x64\x5d\x23\xaf\x0a\x45\x59\xf4\xf2\x3d" "\x4d\xe1\x23\x8c\x37\x38\x59\xe8\x5e\x76\xdc\xe3\xcf\x2b\xa9\x2d\xe1" "\x2f\x9c\xb6\xd5\x74\xba\x37\xc1\xb4\xbf\xe4\x1a\x40\xd4\x03\xf2\x91" "\xd7\xe4\xfb\xd7\xc5\x23\x98\x05\x43\x44\x66\xbc\x28\x60\xcd\xe3\x33" "\xb9\x23\xa6\x82\x76\xd4\xe6\xa0\xfc\xc0\xb8\x3c\x43\x36\x71\x94\x3c" "\x1c\x66\x7c\xd3\x30\xa5\x0b\x31\xa9\x90\xcf\xaa\xfc\x62\x35\xa7\xc2" "\xf4\x95\xb8\x97\x26\xb8\x7a\xa9\x82\x35\xc1\xba\x9d\x67\x40\x3e\xdc" "\x60\xd7\xc7\xfb\xac\x0d\x33\x19\x67\x4c\x28\x16\xcd\xaa\xbb\x8d\x9b" "\xc2\xa2\xbc\x3a\x13\x4a\x4b\xdd\x14\x3f\xa3\xe6\x0c\xcb\x15\x7f\x73" "\x97\x2a\xb1\x6f\x4a\x02\xcb\x5e\xc1\x9b\x68\x98\x93\xc3\x86\x9c\x74" "\xdb\xa9\xc3\xcf\x3e\x83\xc9\x25\xe8\x91\x4c\xca\xd3\x0e\x32\x86\xd7" "\xd4\xe9\x69\x56\x46\xe9\xa5\x7b\xaa\x39\x03\x3e\x07\x76\xb7\x8a\xa4" "\x64\x22\x10\x59\x19\x0f\xc7\x50\x85\xab\xad\xc1\x0b\x72\x08\x30\x20" "\x0c\xd2\xdb\x77\xa8\x62\xd1\xf4\xd6\x7e\xaa\x68\x0a\x45\xfb\x6c\x31" "\xdb\x6c\x2b\x10\xf2\x7a\x00\x63\x01\xfa\x03\x66\xb5\x68\xd5\xf5\x06" "\x6e\xdc\x28\x19\x67\x2e\x7b\xc8\x0a\x4e\x65\x19\x35\x33\xb3\xc1\x57" "\x24\x2b\xcc\x1b\xdf\x66\xe2\x1f\x64\x52\x8f\x15\x30\x0d\x09\x56\xdb" "\x54\xf0\xf6\x3f\xc4\xcb\x8d\x84\x29\x7d\x3c\x70\x53\x6f\x1f\xb6\xc2" "\xdd\x76\x6d\x44\x6a\x18\x6b\x8b\x33\xd1\xe7\x58\x84\x5d\xfe\x15\x6a" "\x29\x9c\x11\x04\xad\xb4\x25\xf1\x72\xb6\xc5\x05\x88\xa4\x54\x4b\x90" "\x71\x9f\xd1\x00\xd2\x44\xce\xa4\xf7\xa2\x98\x2c\xbb\x93\x95\x4d\x66" "\xaf\x60\x0a\xae\x02\x7a\x6f\x00\x4b\x5c\x04\xc1\x3b\xf6\x79\x9d\xf5" "\x3e\xcb\x63\x30\xbc\xf3\xac\x90\x3a\x9d\x1b\xb6\x9e\x5c\x57\x00\x7e" "\x9d\xa3\x42\xce\x5f\x1c\x16\xed\x1c\x90\x88\x55\xf2\x4f\xd0\xc5\x86" "\xa7\xfc\x4e\x3e\x35\xf9\xbd\x9c\xe0\x70\xc7\x3e\xe5\xbd\x90\x33\x97" "\xc3\x1d\xd5\x54\x08\xe0\x15\x94\x7c\x96\x76\x38\xe7\xaf\x59\x78\x6b" "\x15\x94\x31\xd8\xb4\x05\x5b\x7d\xe7\x5a\x31\x23\x3a\x05\x0d\x6e\x0a" "\xad\x8b\x1c\xdc\x5b\x45\x3d\x03\xd1\xc9\x89\x7e\x9b\x01\xeb\x47\x9d" "\xf2\x56\xb3\x47\x52\x76\xe1\xca\xe8\xab\xe1\xbb\x24\xa1\xb1\x6c\x11" "\xc3\x55\x76\x72\x35\x55\xf2\x49\x64\xa9\x12\x5d\x97\x0a\xdb\x2b\x96" "\x4e\xf2\x8e\xb8\x5b\x9a\x5c\x3f\x1e\x64\x89\xe7\xe2\x11\x8c\x47\x08" "\xfc\x18\x32\x8f\xd4\xda\x7d\xb8\xe1\x43\x91\x75\x81\xb6\x77\x4b\x89" "\xa5\x3c\x28\xb0\xc4\x96\x55\x53\x17\x55\xe2\x27\xa5\xf4\x86\x74\x5b" "\x6e\x38\xb0\x2e\xcb\xd8\x07\x2d\xa6\x5a\xb1\x1a\xd8\x1a\xa3\xbf\x0f" "\xd4\xf4\xab\x8e\x87\x15\x93\xf2\x2d\x68\x19\xb4\x9f\x71", 2428); syscall(__NR_ioctl, /*fd=*/(intptr_t)-1, /*cmd=*/0x90044802, /*arg=*/0x2000000008c0ul); break; case 1: // syz_usb_connect$hid arguments: [ // speed: usb_device_speed = 0x0 (8 bytes) // dev_len: len = 0x36 (8 bytes) // dev: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYBLOB: buffer: {12 01 00 00 00 00 00 40 26 09 33 33 40 00 00 // 00 00 01 09 02 24 00 01 00 00 00 00 09 04 00 00 01 03 01 00 00 // 09 21 00 00 00 01 22 01 00 09 05 81 03 08} (length 0x32) // } // } // } // conn_descs: nil // ] // returns fd_usb_hid memcpy( (void*)0x200000000000, "\x12\x01\x00\x00\x00\x00\x00\x40\x26\x09\x33\x33\x40\x00\x00\x00\x00" "\x01\x09\x02\x24\x00\x01\x00\x00\x00\x00\x09\x04\x00\x00\x01\x03\x01" "\x00\x00\x09\x21\x00\x00\x00\x01\x22\x01\x00\x09\x05\x81\x03\x08", 50); res = -1; res = syz_usb_connect(/*speed=*/0, /*dev_len=*/0x36, /*dev=*/0x200000000000, /*conn_descs=*/0); if (res != -1) r[0] = res; break; case 2: // syz_usb_control_io$hid arguments: [ // fd: fd_usb_hid (resource) // descs: nil // resps: nil // ] syz_usb_control_io(/*fd=*/r[0], /*descs=*/0, /*resps=*/0); break; case 3: // syz_usb_control_io arguments: [ // fd: fd_usb (resource) // descs: ptr[in, vusb_descriptors] { // vusb_descriptors { // len: len = 0x2c (4 bytes) // generic: ptr[inout, array[ANYUNION]] { // array[ANYUNION] { // union ANYUNION { // ANYBLOB: buffer: {00 00 02} (length 0x3) // } // } // } // string: nil // bos: nil // hub_hs: nil // hub_ss: nil // } // } // resps: nil // ] *(uint32_t*)0x200000000080 = 0x2c; *(uint64_t*)0x200000000084 = 0x200000000100; memcpy((void*)0x200000000100, "\x00\x00\x02", 3); *(uint64_t*)0x20000000008c = 0; *(uint64_t*)0x200000000094 = 0; *(uint64_t*)0x20000000009c = 0; *(uint64_t*)0x2000000000a4 = 0; syz_usb_control_io(/*fd=*/r[0], /*descs=*/0x200000000080, /*resps=*/0); break; case 4: // syz_usb_ep_write arguments: [ // fd: fd_usb (resource) // ep: int8 = 0x81 (1 bytes) // len: len = 0xffffff75 (8 bytes) // data: ptr[in, buffer] { // buffer: {b9 42 5b 44 65 1d d2 32 41 96 35 99 00 00 00 11 00 00 00 4a // 16 94 1f f5 f4 b4 f1 f0 ad d7 fc f2 b8 77 fc ea ff ff ff ff ff f1 ff // df 4c d9 f5 d3 96 98 90 52 2c 77 15 7d 88 01 00 00 00 3a 5b d5 53 1d // 45 9d ff ff 03 00 00 00 00 00 91 ff 00 00 00 e8 f5 b3 37 1d a3 63 5b // 8b 4f a6 37 13 58 00 00 1f 65 e4 b4 36 aa 9e 50 bc 0f 19 b7 d3 37 2f // f9 eb ce de 1f b5 e9 42 8f 54 d5 d1 f0 cc 75 2c f2 46 a5 d2 da 34 a5 // aa 97 dc 14 a4 69 c3 dd 3e 26 b4 1c 35 64 84 e4 6f d6 6e 3f 2c 78 07 // e8 77 3e ed 7b 94 fa 09 9a b8 4f ea de c2 ea 95 f6 5b ba 45 2e ae 5b // 09 00 f9 8a 97 9a 88 c5 17 a2 dc 36 0a 00 23 77 23 e2 f4 67 af 70 6e // a1 72 26 29 6b 3a 10 a3 51 cb 47 ab a2 c6 b8 36 c9 06 79 b4 dd 85 9d // dc 9e 48 00 44 8a ab 00 00 00 00 00 00 0d 75 f3 4b b5 0d 8d 70 84} // (length 0xf9) // } // ] memcpy( (void*)0x2000000002c0, "\xb9\x42\x5b\x44\x65\x1d\xd2\x32\x41\x96\x35\x99\x00\x00\x00\x11\x00" "\x00\x00\x4a\x16\x94\x1f\xf5\xf4\xb4\xf1\xf0\xad\xd7\xfc\xf2\xb8\x77" "\xfc\xea\xff\xff\xff\xff\xff\xf1\xff\xdf\x4c\xd9\xf5\xd3\x96\x98\x90" "\x52\x2c\x77\x15\x7d\x88\x01\x00\x00\x00\x3a\x5b\xd5\x53\x1d\x45\x9d" "\xff\xff\x03\x00\x00\x00\x00\x00\x91\xff\x00\x00\x00\xe8\xf5\xb3\x37" "\x1d\xa3\x63\x5b\x8b\x4f\xa6\x37\x13\x58\x00\x00\x1f\x65\xe4\xb4\x36" "\xaa\x9e\x50\xbc\x0f\x19\xb7\xd3\x37\x2f\xf9\xeb\xce\xde\x1f\xb5\xe9" "\x42\x8f\x54\xd5\xd1\xf0\xcc\x75\x2c\xf2\x46\xa5\xd2\xda\x34\xa5\xaa" "\x97\xdc\x14\xa4\x69\xc3\xdd\x3e\x26\xb4\x1c\x35\x64\x84\xe4\x6f\xd6" "\x6e\x3f\x2c\x78\x07\xe8\x77\x3e\xed\x7b\x94\xfa\x09\x9a\xb8\x4f\xea" "\xde\xc2\xea\x95\xf6\x5b\xba\x45\x2e\xae\x5b\x09\x00\xf9\x8a\x97\x9a" "\x88\xc5\x17\xa2\xdc\x36\x0a\x00\x23\x77\x23\xe2\xf4\x67\xaf\x70\x6e" "\xa1\x72\x26\x29\x6b\x3a\x10\xa3\x51\xcb\x47\xab\xa2\xc6\xb8\x36\xc9" "\x06\x79\xb4\xdd\x85\x9d\xdc\x9e\x48\x00\x44\x8a\xab\x00\x00\x00\x00" "\x00\x00\x0d\x75\xf3\x4b\xb5\x0d\x8d\x70\x84", 249); syz_usb_ep_write(/*fd=*/r[0], /*ep=*/0x81, /*len=*/0xffffff75, /*data=*/0x2000000002c0); 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); const char* reason; (void)reason; if ((reason = setup_usb())) { fprintf(stderr, "reproducer setup failed: USB injection: %s\n", reason); exit(1); } if ((reason = setup_802154())) { fprintf(stderr, "reproducer setup failed: 802154 injection: %s\n", reason); exit(1); } for (procid = 0; procid < 5; procid++) { if (fork() == 0) { use_temporary_dir(); do_sandbox_none(); } } sleep(1000000); return 0; }