// https://syzkaller.appspot.com/bug?id=09f9deef3f5b37009a62ed8feaef6e47761f9718 // 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 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 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 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 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); } static int runcmdline(char* cmdline) { int ret = system(cmdline); if (ret) { } return ret; } #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); } #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; } 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(); close_fds(); 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_one(void) { intptr_t res = 0; if (write(1, "executing program\n", sizeof("executing program\n") - 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; // 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); // syz_usb_control_io$uac1 arguments: [ // fd: fd_usb_uac1 (resource) // descs: nil // resps: nil // ] syz_usb_control_io(/*fd=*/-1, /*descs=*/0, /*resps=*/0); // syz_usb_control_io arguments: [ // fd: fd_usb (resource) // descs: nil // resps: nil // ] syz_usb_control_io(/*fd=*/-1, /*descs=*/0, /*resps=*/0); // 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); // syz_usb_connect arguments: [ // speed: usb_device_speed = 0x5 (8 bytes) // dev_len: len = 0x0 (8 bytes) // dev: nil // conn_descs: nil // ] // returns fd_usb syz_usb_connect(/*speed=USB_SPEED_SUPER*/ 5, /*dev_len=*/0, /*dev=*/0, /*conn_descs=*/0); // syz_usb_control_io$uac1 arguments: [ // fd: fd_usb_uac1 (resource) // descs: nil // resps: nil // ] syz_usb_control_io(/*fd=*/-1, /*descs=*/0, /*resps=*/0); // syz_usb_ep_write$ath9k_ep1 arguments: [ // fd: fd_usb_ath9k (resource) // ep: const = 0x82 (1 bytes) // len: bytesize = 0x804 (8 bytes) // data: ptr[in, ath9k_bulk_frame] { // ath9k_bulk_frame { // packets: array[ath9k_bulk_packet] { // ath9k_bulk_packet { // pkt_len: len = 0x7fd (2 bytes) // pkt_tag: const = 0x4e00 (2 bytes) // data: buffer: {03 bb 08 37 f5 50 96 ad ec ba a4 f3 8c a6 6b f1 // b8 b1 a8 87 1c 1e ad f3 17 0d 87 0e c0 ce 31 98 06 5d 89 86 72 // 65 c1 2f 77 99 cd 9e 55 c1 c3 bb ff f5 b5 06 5f 81 0f 73 4b 6e // 49 53 4d c3 8b b0 4e 7e 02 a1 b3 7c f0 5c 24 b2 75 b4 12 27 ab // b7 6f 08 4c 4c 27 07 89 49 39 56 29 37 ab 80 6d ff c8 d6 03 6a // a0 d4 c8 79 7b bc a0 f4 34 1f 16 60 9d a2 fd 96 8e b5 e1 08 ee // 38 48 99 e3 64 d7 47 f4 8f e4 90 96 72 02 f8 35 e5 0d 40 2e 6d // e0 af 83 05 93 b0 34 f1 c4 29 7e dd 1c b7 a7 18 74 56 aa bc 1d // 1c ba 3a 36 c3 7f e0 15 12 89 08 3a 3a 45 42 f2 39 25 36 68 7b // 29 9d 7d e7 2b 62 2b 2b 48 ea b0 a3 46 1a 96 1b 9c 0f c3 30 df // 84 7d 57 e8 2e 73 c0 e9 88 20 23 3a 4f 0f ac 68 3e ef aa f4 97 // d6 b3 42 52 5a eb a5 53 0f f1 99 3a 9a 59 7e 2a a0 c9 a2 fa 05 // 4c ac d4 ed d0 30 a6 18 3f 51 5b d7 fe 99 12 6b 36 5c 14 23 1d // 36 87 4b b9 00 9d 80 c8 7f 78 d8 3c d1 08 ba 3e f7 70 44 79 2f // f3 9b 07 d8 3e 7d c3 e4 f3 1c 00 6e 32 1d f1 11 e4 e9 80 f4 2f // 49 5d de 5a 00 fe 3f bf 7d e9 4a bb 88 9e 82 72 db f9 ee 11 17 // f1 b4 d9 c7 05 a1 93 5e 8a d3 d8 85 76 4d dd 8c 25 81 b4 34 b7 // fe 37 87 36 0f 6a 3d 5d 2a d6 39 8b 3f 9f c7 97 d4 76 73 31 62 // 33 75 0c 02 f8 1b e4 5b b6 64 ea a5 b5 8f 87 ff c3 1e f3 6d 27 // 68 21 07 03 a0 0b b4 f9 e1 c8 ce f8 58 63 8c c4 1b 6d 7c d4 d4 // a1 3f 22 e6 fc e0 0a e9 44 2e 03 1e 88 f6 67 c0 ed 3e f3 7b 2f // a1 c0 ff 8d ff d5 89 37 1c 1a 00 35 af ea c5 91 96 81 d5 08 63 // aa 6c e5 5e 92 3d e0 2b a8 49 2e d1 5b 0b 51 12 1a 4b cc 31 52 // da 46 91 db fb 7a 0e b9 e5 ed 66 b4 01 b4 1b da 10 16 dc 36 36 // ed 34 ac 51 11 32 11 d5 eb c6 99 70 61 4b 63 7e da b2 96 3a 5c // 3d a2 1c af 7a 9a 1f 84 48 37 d0 f3 8f e6 fb b2 c1 53 b7 26 cc // c9 40 3b 9a 01 22 6c 6f a0 d2 a5 ff 25 70 94 22 97 26 9f 06 19 // 75 2e 0e 5c 7b 4e e6 42 be d5 0b 52 2f 7b 60 37 ba 9a fc 0b 7b // f2 b2 0e 3c 5a 31 33 6e 91 94 f2 81 7e 2e af 72 29 4c 5e a1 97 // 88 bf fa ca c0 aa ca 54 da 6a 86 71 31 f2 d0 18 cc ed a5 ed 69 // a6 bf a4 54 bc 5e 55 6b b1 e5 f9 5a 70 37 cd f4 5e fd e6 97 23 // 63 ed a5 d0 97 71 a6 1e 71 64 df 5a bc ee 09 0f 36 69 62 b6 7a // b5 e4 93 b3 ef 89 b7 9b 94 44 be 55 7c 15 01 79 2e 95 27 8b 44 // aa 8b 6f 0e 04 6a 54 23 9b 58 3a ca 09 63 66 89 c4 42 5e 1c 04 // 69 39 7b 4a a0 c9 bd 56 32 7a 9e d8 ad 80 54 47 77 8a c4 41 ab // 43 4f 4a 36 da 31 6f 10 39 e0 a0 d4 53 40 36 1f 5a 79 39 12 02 // 5d 4b 25 8b 30 6b d3 e2 64 cb 83 6b a8 cc 90 31 ba d2 f9 53 f1 // 28 6b 6f d1 f2 48 23 5e f4 00 d4 b6 a3 3d 9c a4 11 1a 11 63 fa // ba 8a 47 11 a5 c5 67 6f f9 da 17 0e 25 02 98 c1 84 84 97 aa 4a // 21 29 6a 0e c2 0b f4 8f c3 0d f4 0e d2 d8 d2 11 42 1b 36 dc cc // b8 80 69 48 21 a2 f5 33 58 10 a6 ac ae a6 01 00 5c 94 02 57 28 // c7 a0 de 6d 00 49 72 c0 ed 6b f1 1a 90 9a e6 cf 3d 6f 7b d8 1f // d4 78 fa 67 40 73 49 cc b3 a6 57 79 ec 31 c7 89 10 67 d5 e0 05 // ae 97 e3 d2 7f 42 48 87 b2 54 2b 77 62 49 b2 de de f1 16 e0 81 // 42 47 a6 cf d6 30 23 07 bc 1f 68 f9 3f 60 e4 08 24 7a 7a a8 2f // 8f ac 98 55 82 e8 42 6e 6d c9 35 a3 59 a2 27 fa e2 ca df 8a 7c // 32 c2 7e 78 42 c8 7e f9 d4 e3 7a 69 d1 fb 3b 00 37 73 c1 4f 79 // 76 3c 73 66 85 25 74 bb 1c 20 54 67 34 80 17 65 6b f7 eb aa cc // 4a 53 eb 41 8f 2b 50 d8 07 d8 f9 37 e0 05 52 8d d7 4e 0e b4 42 // 80 32 22 6b 3b 55 17 11 67 ea 0c 61 10 8d 7d 6f ae 4e 29 f4 b1 // 27 f9 6f a6 7b 7f 40 79 f5 36 83 a0 69 cf 32 25 e7 23 74 0d 66 // a0 e8 da 4f 86 f1 10 b9 27 ac 72 19 77 14 b3 0c 50 b6 ea 84 90 // b3 04 65 88 d0 c4 da 7d 2a c1 f6 c2 ed b2 e3 28 1f 52 6d ca 01 // 64 d2 7a 7a 32 77 e1 fa f2 81 08 f7 11 25 dc b3 f2 cf 5f 95 cb // e3 4f 59 07 1f ce bb f7 bd 5f 80 01 8c 4d a8 23 f5 96 47 a1 5f // 0f 12 fc 8a ad e2 ea 9f 58 a5 7c e9 80 53 5f af b0 6d ee 55 33 // bc f4 5e 21 65 84 07 5d be a6 5a f3 c3 80 6c 78 db fc 92 d3 33 // 50 84 00 00 09 9e b5 9c ae a0 e6 28 ef d3 0e 55 82 1c 12 31 ee // 89 77 59 ff 4c 3c 1c d8 f4 3b 66 95 2a bb f4 e8 88 b7 48 31 3b // d6 17 3b d6 98 33 30 df cd 3d ea a0 9e ef 99 fd 1e 0b e5 b3 67 // 1c 0d 0a d7 2b 44 e6 1f fc 7b 10 55 3d 8f 4d ce ce ae 66 5f b1 // de 06 da cb 47 c6 e5 1d c5 2e 76 4d e2 7e 80 22 ff da 52 5e ce // ef 40 26 d5 8f 78 b2 69 a2 b4 15 c5 77 17 41 b2 0d 6a 2d 5e ea // a2 43 10 70 39 d6 72 f4 93 0e 30 20 bd 16 aa af ac 64 1f 50 b6 // eb 1f b4 80 f5 01 49 99 c8 80 c6 5a ae 34 0d 86 8a c8 ec e2 db // d8 8f 96 f4 a3 a7 3e 48 ae 2c 9e 8f 7e e4 9e fa 19 a5 5e f2 6c // d4 a3 6c c3 55 d6 d6 fb c6 37 ac 34 ad c9 ed ce 03 32 59 50 55 // 2a 61 fe cc 87 3d b4 d2 d5 6e a6 03 24 0e 2d a7 8d 40 92 c2 88 // 79 20 be 95 a1 72 ae ac 4c b4 4e c2 53 64 a2 cb e7 4a bb 0e b4 // 25 3c 80 c3 5b b8 5f 6e 65 53 09 99 c4 81 c8 0c dd 54 bb 9a d3 // 2f f1 01 49 7c 5e a2 08 a0 bb 77 c2 d5 a2 4b c5 fe f4 31 06 67 // 84 de 9a 73 96 09 cf 7f 4b b4 52 c7 f2 44 04 4f 5d 98 4d df d2 // ba e9 bb 19 e0 ba e2 33 f8 b5 4d ea 50 ce 78 ef 34 eb 66 f6 ae // c2 dc e0 07 4f 4c a3 3e 64 74 50 b6 22 98 72 49 49 57 96 ef 5e // 77 5b 5c b3 89 34 53 e7 fb d1 cf ef 0a 79 62 ec de 65 ce 90 90 // 6e b9 69 9e 0d 72 87 4c 1c 1d e6 c0 b3 17 79 25 ce ba a7 d4 27 // 15 a9 96 95 ad 91 8f 15 e8 75 65 a0 d4 7b 15 a7 98 0e ec 9b 09 // d6 61 44 ab 46 da 50 72 c1 b8 a6 5f 00 c1 e5 d5 99 7c 2f 62 0e // fa fb d1 4a bb b8 a6 32 ba 8e af 1d fb 53 4c 49 42 99 0f 19 65 // 44 4a e8 42 95 50 cb 31 49 d7 15 04 e0 ef d5 f1 78 40 c0 f1 3e // 04 b0 84 be 97 f7 db 7e 47 87 1d 17 d8 1b 7e 5d 77 c5 22 76 8d // df a9 8e 5a 7c ef d9 6d 42 77 3c 75 36 8d c1 1d 54 15 bc 72 87 // a0 b7 b2 3b 3d b3 51 ef 6d 4a 1b be a0 34 bb db 3c e9 86 7d 23 // 88 f8 21 18 37 56 60 68 20 bd 03 10 7d c5 41 5b 46 95 91 16 79 // 80 68 47 56 81 a9 28 25 c8 9e d3 1a 51 f4 b4 bd 4c ee 80 9b c6 // 19 0a 21 9e e8 18 a1 da 53 a8 10 6a bd 46 53 ec c6 bf 99 47 32 // c3 dc ea a6 05 e8 52 df 4b 9c 3f 89 30 ed f4 65 5b 89 85 79 d5 // d0 5b a9 f0 a5 0d 47 22 61 67 fa aa fe 62 eb a4 27 96 09 67 a8 // a9 8f 01 d1 3e 51 54 8a 07 be 85 b0 4d 15 97 30 b3 6d 0e f0 34 // 1f 81 c2 da 93 b1 8c 90 f9 cb a3 30 21 4a e4 56 ff 6e 9e 7a 0f // b0 2c 8b 72 2c f7 16 a0 37 05 89 de 80 e4 e4 af eb db fd 51 4f // 21 d1 60 c2 6e 22 49 e7 d0 53 26 35 3d 05 59 b3 70 f7 fa bc a8 // 55 ba 21 19 08 44 5f 40 7a f8 d2 1a 8a 9f 81 56 98 91 76 dc 5e // b9 31 7a bf e1 90 a3 ff 0d e2 cb 4c e5 a2 09 26 64 a7 fe 4e 1d // 75 9e 32 01 ba 38 87 99 e1 06 ba 59 d4 87 db c2 b3 07 28 46 2b // 0d 7a 08 11 13 ae 18 27 19 7f c9 88 8e 02 be 0e 96 39 dc a8 84 // 87 c5 a8 56 eb 29 35 d6 c6 c0 28 1f ab 6d cf 9b d8 58 1a 8f 9a // 3e fe e9 c8 30 55 75 d9 17 60 26 7f f4} (length 0x7fd) // } // } // } // } // ] *(uint16_t*)0x200000000640 = 0x7fd; *(uint16_t*)0x200000000642 = 0x4e00; memcpy( (void*)0x200000000644, "\x03\xbb\x08\x37\xf5\x50\x96\xad\xec\xba\xa4\xf3\x8c\xa6\x6b\xf1\xb8\xb1" "\xa8\x87\x1c\x1e\xad\xf3\x17\x0d\x87\x0e\xc0\xce\x31\x98\x06\x5d\x89\x86" "\x72\x65\xc1\x2f\x77\x99\xcd\x9e\x55\xc1\xc3\xbb\xff\xf5\xb5\x06\x5f\x81" "\x0f\x73\x4b\x6e\x49\x53\x4d\xc3\x8b\xb0\x4e\x7e\x02\xa1\xb3\x7c\xf0\x5c" "\x24\xb2\x75\xb4\x12\x27\xab\xb7\x6f\x08\x4c\x4c\x27\x07\x89\x49\x39\x56" "\x29\x37\xab\x80\x6d\xff\xc8\xd6\x03\x6a\xa0\xd4\xc8\x79\x7b\xbc\xa0\xf4" "\x34\x1f\x16\x60\x9d\xa2\xfd\x96\x8e\xb5\xe1\x08\xee\x38\x48\x99\xe3\x64" "\xd7\x47\xf4\x8f\xe4\x90\x96\x72\x02\xf8\x35\xe5\x0d\x40\x2e\x6d\xe0\xaf" "\x83\x05\x93\xb0\x34\xf1\xc4\x29\x7e\xdd\x1c\xb7\xa7\x18\x74\x56\xaa\xbc" "\x1d\x1c\xba\x3a\x36\xc3\x7f\xe0\x15\x12\x89\x08\x3a\x3a\x45\x42\xf2\x39" "\x25\x36\x68\x7b\x29\x9d\x7d\xe7\x2b\x62\x2b\x2b\x48\xea\xb0\xa3\x46\x1a" "\x96\x1b\x9c\x0f\xc3\x30\xdf\x84\x7d\x57\xe8\x2e\x73\xc0\xe9\x88\x20\x23" "\x3a\x4f\x0f\xac\x68\x3e\xef\xaa\xf4\x97\xd6\xb3\x42\x52\x5a\xeb\xa5\x53" "\x0f\xf1\x99\x3a\x9a\x59\x7e\x2a\xa0\xc9\xa2\xfa\x05\x4c\xac\xd4\xed\xd0" "\x30\xa6\x18\x3f\x51\x5b\xd7\xfe\x99\x12\x6b\x36\x5c\x14\x23\x1d\x36\x87" "\x4b\xb9\x00\x9d\x80\xc8\x7f\x78\xd8\x3c\xd1\x08\xba\x3e\xf7\x70\x44\x79" "\x2f\xf3\x9b\x07\xd8\x3e\x7d\xc3\xe4\xf3\x1c\x00\x6e\x32\x1d\xf1\x11\xe4" "\xe9\x80\xf4\x2f\x49\x5d\xde\x5a\x00\xfe\x3f\xbf\x7d\xe9\x4a\xbb\x88\x9e" "\x82\x72\xdb\xf9\xee\x11\x17\xf1\xb4\xd9\xc7\x05\xa1\x93\x5e\x8a\xd3\xd8" "\x85\x76\x4d\xdd\x8c\x25\x81\xb4\x34\xb7\xfe\x37\x87\x36\x0f\x6a\x3d\x5d" "\x2a\xd6\x39\x8b\x3f\x9f\xc7\x97\xd4\x76\x73\x31\x62\x33\x75\x0c\x02\xf8" "\x1b\xe4\x5b\xb6\x64\xea\xa5\xb5\x8f\x87\xff\xc3\x1e\xf3\x6d\x27\x68\x21" "\x07\x03\xa0\x0b\xb4\xf9\xe1\xc8\xce\xf8\x58\x63\x8c\xc4\x1b\x6d\x7c\xd4" "\xd4\xa1\x3f\x22\xe6\xfc\xe0\x0a\xe9\x44\x2e\x03\x1e\x88\xf6\x67\xc0\xed" "\x3e\xf3\x7b\x2f\xa1\xc0\xff\x8d\xff\xd5\x89\x37\x1c\x1a\x00\x35\xaf\xea" "\xc5\x91\x96\x81\xd5\x08\x63\xaa\x6c\xe5\x5e\x92\x3d\xe0\x2b\xa8\x49\x2e" "\xd1\x5b\x0b\x51\x12\x1a\x4b\xcc\x31\x52\xda\x46\x91\xdb\xfb\x7a\x0e\xb9" "\xe5\xed\x66\xb4\x01\xb4\x1b\xda\x10\x16\xdc\x36\x36\xed\x34\xac\x51\x11" "\x32\x11\xd5\xeb\xc6\x99\x70\x61\x4b\x63\x7e\xda\xb2\x96\x3a\x5c\x3d\xa2" "\x1c\xaf\x7a\x9a\x1f\x84\x48\x37\xd0\xf3\x8f\xe6\xfb\xb2\xc1\x53\xb7\x26" "\xcc\xc9\x40\x3b\x9a\x01\x22\x6c\x6f\xa0\xd2\xa5\xff\x25\x70\x94\x22\x97" "\x26\x9f\x06\x19\x75\x2e\x0e\x5c\x7b\x4e\xe6\x42\xbe\xd5\x0b\x52\x2f\x7b" "\x60\x37\xba\x9a\xfc\x0b\x7b\xf2\xb2\x0e\x3c\x5a\x31\x33\x6e\x91\x94\xf2" "\x81\x7e\x2e\xaf\x72\x29\x4c\x5e\xa1\x97\x88\xbf\xfa\xca\xc0\xaa\xca\x54" "\xda\x6a\x86\x71\x31\xf2\xd0\x18\xcc\xed\xa5\xed\x69\xa6\xbf\xa4\x54\xbc" "\x5e\x55\x6b\xb1\xe5\xf9\x5a\x70\x37\xcd\xf4\x5e\xfd\xe6\x97\x23\x63\xed" "\xa5\xd0\x97\x71\xa6\x1e\x71\x64\xdf\x5a\xbc\xee\x09\x0f\x36\x69\x62\xb6" "\x7a\xb5\xe4\x93\xb3\xef\x89\xb7\x9b\x94\x44\xbe\x55\x7c\x15\x01\x79\x2e" "\x95\x27\x8b\x44\xaa\x8b\x6f\x0e\x04\x6a\x54\x23\x9b\x58\x3a\xca\x09\x63" "\x66\x89\xc4\x42\x5e\x1c\x04\x69\x39\x7b\x4a\xa0\xc9\xbd\x56\x32\x7a\x9e" "\xd8\xad\x80\x54\x47\x77\x8a\xc4\x41\xab\x43\x4f\x4a\x36\xda\x31\x6f\x10" "\x39\xe0\xa0\xd4\x53\x40\x36\x1f\x5a\x79\x39\x12\x02\x5d\x4b\x25\x8b\x30" "\x6b\xd3\xe2\x64\xcb\x83\x6b\xa8\xcc\x90\x31\xba\xd2\xf9\x53\xf1\x28\x6b" "\x6f\xd1\xf2\x48\x23\x5e\xf4\x00\xd4\xb6\xa3\x3d\x9c\xa4\x11\x1a\x11\x63" "\xfa\xba\x8a\x47\x11\xa5\xc5\x67\x6f\xf9\xda\x17\x0e\x25\x02\x98\xc1\x84" "\x84\x97\xaa\x4a\x21\x29\x6a\x0e\xc2\x0b\xf4\x8f\xc3\x0d\xf4\x0e\xd2\xd8" "\xd2\x11\x42\x1b\x36\xdc\xcc\xb8\x80\x69\x48\x21\xa2\xf5\x33\x58\x10\xa6" "\xac\xae\xa6\x01\x00\x5c\x94\x02\x57\x28\xc7\xa0\xde\x6d\x00\x49\x72\xc0" "\xed\x6b\xf1\x1a\x90\x9a\xe6\xcf\x3d\x6f\x7b\xd8\x1f\xd4\x78\xfa\x67\x40" "\x73\x49\xcc\xb3\xa6\x57\x79\xec\x31\xc7\x89\x10\x67\xd5\xe0\x05\xae\x97" "\xe3\xd2\x7f\x42\x48\x87\xb2\x54\x2b\x77\x62\x49\xb2\xde\xde\xf1\x16\xe0" "\x81\x42\x47\xa6\xcf\xd6\x30\x23\x07\xbc\x1f\x68\xf9\x3f\x60\xe4\x08\x24" "\x7a\x7a\xa8\x2f\x8f\xac\x98\x55\x82\xe8\x42\x6e\x6d\xc9\x35\xa3\x59\xa2" "\x27\xfa\xe2\xca\xdf\x8a\x7c\x32\xc2\x7e\x78\x42\xc8\x7e\xf9\xd4\xe3\x7a" "\x69\xd1\xfb\x3b\x00\x37\x73\xc1\x4f\x79\x76\x3c\x73\x66\x85\x25\x74\xbb" "\x1c\x20\x54\x67\x34\x80\x17\x65\x6b\xf7\xeb\xaa\xcc\x4a\x53\xeb\x41\x8f" "\x2b\x50\xd8\x07\xd8\xf9\x37\xe0\x05\x52\x8d\xd7\x4e\x0e\xb4\x42\x80\x32" "\x22\x6b\x3b\x55\x17\x11\x67\xea\x0c\x61\x10\x8d\x7d\x6f\xae\x4e\x29\xf4" "\xb1\x27\xf9\x6f\xa6\x7b\x7f\x40\x79\xf5\x36\x83\xa0\x69\xcf\x32\x25\xe7" "\x23\x74\x0d\x66\xa0\xe8\xda\x4f\x86\xf1\x10\xb9\x27\xac\x72\x19\x77\x14" "\xb3\x0c\x50\xb6\xea\x84\x90\xb3\x04\x65\x88\xd0\xc4\xda\x7d\x2a\xc1\xf6" "\xc2\xed\xb2\xe3\x28\x1f\x52\x6d\xca\x01\x64\xd2\x7a\x7a\x32\x77\xe1\xfa" "\xf2\x81\x08\xf7\x11\x25\xdc\xb3\xf2\xcf\x5f\x95\xcb\xe3\x4f\x59\x07\x1f" "\xce\xbb\xf7\xbd\x5f\x80\x01\x8c\x4d\xa8\x23\xf5\x96\x47\xa1\x5f\x0f\x12" "\xfc\x8a\xad\xe2\xea\x9f\x58\xa5\x7c\xe9\x80\x53\x5f\xaf\xb0\x6d\xee\x55" "\x33\xbc\xf4\x5e\x21\x65\x84\x07\x5d\xbe\xa6\x5a\xf3\xc3\x80\x6c\x78\xdb" "\xfc\x92\xd3\x33\x50\x84\x00\x00\x09\x9e\xb5\x9c\xae\xa0\xe6\x28\xef\xd3" "\x0e\x55\x82\x1c\x12\x31\xee\x89\x77\x59\xff\x4c\x3c\x1c\xd8\xf4\x3b\x66" "\x95\x2a\xbb\xf4\xe8\x88\xb7\x48\x31\x3b\xd6\x17\x3b\xd6\x98\x33\x30\xdf" "\xcd\x3d\xea\xa0\x9e\xef\x99\xfd\x1e\x0b\xe5\xb3\x67\x1c\x0d\x0a\xd7\x2b" "\x44\xe6\x1f\xfc\x7b\x10\x55\x3d\x8f\x4d\xce\xce\xae\x66\x5f\xb1\xde\x06" "\xda\xcb\x47\xc6\xe5\x1d\xc5\x2e\x76\x4d\xe2\x7e\x80\x22\xff\xda\x52\x5e" "\xce\xef\x40\x26\xd5\x8f\x78\xb2\x69\xa2\xb4\x15\xc5\x77\x17\x41\xb2\x0d" "\x6a\x2d\x5e\xea\xa2\x43\x10\x70\x39\xd6\x72\xf4\x93\x0e\x30\x20\xbd\x16" "\xaa\xaf\xac\x64\x1f\x50\xb6\xeb\x1f\xb4\x80\xf5\x01\x49\x99\xc8\x80\xc6" "\x5a\xae\x34\x0d\x86\x8a\xc8\xec\xe2\xdb\xd8\x8f\x96\xf4\xa3\xa7\x3e\x48" "\xae\x2c\x9e\x8f\x7e\xe4\x9e\xfa\x19\xa5\x5e\xf2\x6c\xd4\xa3\x6c\xc3\x55" "\xd6\xd6\xfb\xc6\x37\xac\x34\xad\xc9\xed\xce\x03\x32\x59\x50\x55\x2a\x61" "\xfe\xcc\x87\x3d\xb4\xd2\xd5\x6e\xa6\x03\x24\x0e\x2d\xa7\x8d\x40\x92\xc2" "\x88\x79\x20\xbe\x95\xa1\x72\xae\xac\x4c\xb4\x4e\xc2\x53\x64\xa2\xcb\xe7" "\x4a\xbb\x0e\xb4\x25\x3c\x80\xc3\x5b\xb8\x5f\x6e\x65\x53\x09\x99\xc4\x81" "\xc8\x0c\xdd\x54\xbb\x9a\xd3\x2f\xf1\x01\x49\x7c\x5e\xa2\x08\xa0\xbb\x77" "\xc2\xd5\xa2\x4b\xc5\xfe\xf4\x31\x06\x67\x84\xde\x9a\x73\x96\x09\xcf\x7f" "\x4b\xb4\x52\xc7\xf2\x44\x04\x4f\x5d\x98\x4d\xdf\xd2\xba\xe9\xbb\x19\xe0" "\xba\xe2\x33\xf8\xb5\x4d\xea\x50\xce\x78\xef\x34\xeb\x66\xf6\xae\xc2\xdc" "\xe0\x07\x4f\x4c\xa3\x3e\x64\x74\x50\xb6\x22\x98\x72\x49\x49\x57\x96\xef" "\x5e\x77\x5b\x5c\xb3\x89\x34\x53\xe7\xfb\xd1\xcf\xef\x0a\x79\x62\xec\xde" "\x65\xce\x90\x90\x6e\xb9\x69\x9e\x0d\x72\x87\x4c\x1c\x1d\xe6\xc0\xb3\x17" "\x79\x25\xce\xba\xa7\xd4\x27\x15\xa9\x96\x95\xad\x91\x8f\x15\xe8\x75\x65" "\xa0\xd4\x7b\x15\xa7\x98\x0e\xec\x9b\x09\xd6\x61\x44\xab\x46\xda\x50\x72" "\xc1\xb8\xa6\x5f\x00\xc1\xe5\xd5\x99\x7c\x2f\x62\x0e\xfa\xfb\xd1\x4a\xbb" "\xb8\xa6\x32\xba\x8e\xaf\x1d\xfb\x53\x4c\x49\x42\x99\x0f\x19\x65\x44\x4a" "\xe8\x42\x95\x50\xcb\x31\x49\xd7\x15\x04\xe0\xef\xd5\xf1\x78\x40\xc0\xf1" "\x3e\x04\xb0\x84\xbe\x97\xf7\xdb\x7e\x47\x87\x1d\x17\xd8\x1b\x7e\x5d\x77" "\xc5\x22\x76\x8d\xdf\xa9\x8e\x5a\x7c\xef\xd9\x6d\x42\x77\x3c\x75\x36\x8d" "\xc1\x1d\x54\x15\xbc\x72\x87\xa0\xb7\xb2\x3b\x3d\xb3\x51\xef\x6d\x4a\x1b" "\xbe\xa0\x34\xbb\xdb\x3c\xe9\x86\x7d\x23\x88\xf8\x21\x18\x37\x56\x60\x68" "\x20\xbd\x03\x10\x7d\xc5\x41\x5b\x46\x95\x91\x16\x79\x80\x68\x47\x56\x81" "\xa9\x28\x25\xc8\x9e\xd3\x1a\x51\xf4\xb4\xbd\x4c\xee\x80\x9b\xc6\x19\x0a" "\x21\x9e\xe8\x18\xa1\xda\x53\xa8\x10\x6a\xbd\x46\x53\xec\xc6\xbf\x99\x47" "\x32\xc3\xdc\xea\xa6\x05\xe8\x52\xdf\x4b\x9c\x3f\x89\x30\xed\xf4\x65\x5b" "\x89\x85\x79\xd5\xd0\x5b\xa9\xf0\xa5\x0d\x47\x22\x61\x67\xfa\xaa\xfe\x62" "\xeb\xa4\x27\x96\x09\x67\xa8\xa9\x8f\x01\xd1\x3e\x51\x54\x8a\x07\xbe\x85" "\xb0\x4d\x15\x97\x30\xb3\x6d\x0e\xf0\x34\x1f\x81\xc2\xda\x93\xb1\x8c\x90" "\xf9\xcb\xa3\x30\x21\x4a\xe4\x56\xff\x6e\x9e\x7a\x0f\xb0\x2c\x8b\x72\x2c" "\xf7\x16\xa0\x37\x05\x89\xde\x80\xe4\xe4\xaf\xeb\xdb\xfd\x51\x4f\x21\xd1" "\x60\xc2\x6e\x22\x49\xe7\xd0\x53\x26\x35\x3d\x05\x59\xb3\x70\xf7\xfa\xbc" "\xa8\x55\xba\x21\x19\x08\x44\x5f\x40\x7a\xf8\xd2\x1a\x8a\x9f\x81\x56\x98" "\x91\x76\xdc\x5e\xb9\x31\x7a\xbf\xe1\x90\xa3\xff\x0d\xe2\xcb\x4c\xe5\xa2" "\x09\x26\x64\xa7\xfe\x4e\x1d\x75\x9e\x32\x01\xba\x38\x87\x99\xe1\x06\xba" "\x59\xd4\x87\xdb\xc2\xb3\x07\x28\x46\x2b\x0d\x7a\x08\x11\x13\xae\x18\x27" "\x19\x7f\xc9\x88\x8e\x02\xbe\x0e\x96\x39\xdc\xa8\x84\x87\xc5\xa8\x56\xeb" "\x29\x35\xd6\xc6\xc0\x28\x1f\xab\x6d\xcf\x9b\xd8\x58\x1a\x8f\x9a\x3e\xfe" "\xe9\xc8\x30\x55\x75\xd9\x17\x60\x26\x7f\xf4", 2045); syz_usb_ep_write(/*fd=*/-1, /*ep=*/0x82, /*len=*/0x804, /*data=*/0x200000000640); // syz_usb_control_io arguments: [ // fd: fd_usb (resource) // descs: nil // resps: nil // ] syz_usb_control_io(/*fd=*/-1, /*descs=*/0, /*resps=*/0); // 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); } int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*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=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); const char* reason; (void)reason; if ((reason = setup_swap())) printf("the reproducer may not work as expected: swap setup failed: %s\n", reason); for (procid = 0; procid < 5; procid++) { if (fork() == 0) { use_temporary_dir(); do_sandbox_none(); } } sleep(1000000); return 0; }