diff --git a/executor/common.h b/executor/common.h index e7e02ffb22c0..4f2e0f90d302 100644 --- a/executor/common.h +++ b/executor/common.h @@ -66,9 +66,9 @@ NORETURN void doexit_thread(int status) #endif #endif -#if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS || \ - SYZ_NET_DEVICES || __NR_syz_mount_image || __NR_syz_read_part_table || \ - __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usbip_server_init || \ +#if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS || \ + SYZ_NET_DEVICES || __NR_syz_mount_image || __NR_syz_read_part_table || \ + __NR_syz_usb_connect || __NR_syz_usbip_server_init || \ (GOOS_freebsd || GOOS_darwin || GOOS_openbsd || GOOS_netbsd) && SYZ_NET_INJECTION static unsigned long long procid; #endif @@ -178,7 +178,7 @@ static void kill_and_wait(int pid, int* status) #if !GOOS_windows #if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER || \ - __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_sleep_ms || \ + __NR_syz_usb_connect || __NR_syz_usb_finish_probe || __NR_syz_sleep_ms || \ __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write || \ __NR_syz_usb_disconnect static void sleep_ms(uint64 ms) diff --git a/executor/common_linux.h b/executor/common_linux.h index 5d477a16a812..ff980c4db15a 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -73,7 +73,7 @@ static int event_timedwait(event_t* ev, uint64 timeout) #if SYZ_EXECUTOR || SYZ_REPEAT || SYZ_NET_INJECTION || SYZ_FAULT || SYZ_SANDBOX_NONE || \ SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID || \ SYZ_FAULT || SYZ_LEAK || SYZ_BINFMT_MISC || SYZ_SYSCTL || \ - ((__NR_syz_usb_connect || __NR_syz_usb_connect_ath9k) && USB_DEBUG) || \ + (__NR_syz_usb_connect && USB_DEBUG) || \ __NR_syz_usbip_server_init #include #include @@ -2376,11 +2376,11 @@ static long syz_extract_tcp_res(volatile long a0, volatile long a1, volatile lon } #endif -#if SYZ_EXECUTOR || SYZ_CLOSE_FDS || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#if SYZ_EXECUTOR || SYZ_CLOSE_FDS || __NR_syz_usb_connect #define MAX_FDS 30 #endif -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \ +#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || \ __NR_syz_usb_ep_write || __NR_syz_usb_ep_read || __NR_syz_usb_control_io || \ __NR_syz_usb_disconnect #include diff --git a/executor/common_usb.h b/executor/common_usb.h index fb3e4dce66b5..1d3ade4fd406 100644 --- a/executor/common_usb.h +++ b/executor/common_usb.h @@ -47,7 +47,7 @@ struct usb_info { struct usb_device_index index; }; -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \ +#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || \ __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write static struct usb_info usb_devices[USB_MAX_FDS]; @@ -61,7 +61,7 @@ static struct usb_device_index* lookup_usb_index(int fd) } #endif -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#if SYZ_EXECUTOR || __NR_syz_usb_connect static int usb_devices_num; static bool parse_usb_descriptor(const char* buffer, size_t length, struct usb_device_index* index) @@ -128,7 +128,7 @@ static struct usb_device_index* add_usb_index(int fd, const char* dev, size_t de return &usb_devices[i].index; } -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect #if USB_DEBUG @@ -567,7 +567,39 @@ struct vusb_connect_descriptors { struct vusb_connect_string_descriptor strs[0]; } __attribute__((packed)); -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_control_io || __NR_syz_usb_finish_probe + +struct vusb_descriptor { + uint8 req_type; + uint8 desc_type; + uint32 len; + char data[0]; +} __attribute__((packed)); + +struct vusb_descriptors { + uint32 len; + struct vusb_descriptor* generic; + struct vusb_descriptor* descs[0]; +} __attribute__((packed)); + +struct vusb_response { + uint8 type; + uint8 req; + uint32 len; + // Number of times this request *should* be processed. 0 by default. + uint32 expected; + char data[0]; +} __attribute__((packed)); + +struct vusb_responses { + uint32 len; + struct vusb_response* generic; + struct vusb_response* resps[0]; +} __attribute__((packed)); + +#endif // SYZ_EXECUTOR || __NR_syz_usb_control_io || __NR_syz_usb_finish_probe + +#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe static const char default_string[] = { 8, USB_DT_STRING, @@ -580,24 +612,32 @@ static const char default_lang_id[] = { }; // lookup_connect_response_in() is a helper function that returns a response to a USB IN request -// based on syzkaller-generated arguments provided to syz_usb_connect* pseudo-syscalls. The data -// and its length to be used as a response are returned in *response_data and *response_length. -// The return value of this function lookup_connect_response_inindicates whether the request is known to syzkaller. +// based on syzkaller-generated arguments provided to syz_usb_connect* and syz_usb_finish_probe* +// pseudo-syscalls. The data and its length to be used as a response are returned in *response_data +// and *response_length. The return value of this function lookup_connect_response_in indicates +// whether the request is known to syzkaller. + +// Use *done counter (for instance, in syz_usb_finish_probe variants) to keep track of requests +// which remain to be processed. static bool lookup_connect_response_in(int fd, const struct vusb_connect_descriptors* descs, + const struct vusb_responses* resps, const struct usb_ctrlrequest* ctrl, struct usb_qualifier_descriptor* qual, - char** response_data, uint32* response_length) + char** response_data, uint32* response_length, int* done) { struct usb_device_index* index = lookup_usb_index(fd); uint8 str_idx; + int resps_num = 0; + uint8 req = ctrl->bRequest; + uint8 req_type = ctrl->bRequestType; if (!index) return false; - switch (ctrl->bRequestType & USB_TYPE_MASK) { + switch (req_type & USB_TYPE_MASK) { case USB_TYPE_STANDARD: - switch (ctrl->bRequest) { + switch (req) { case USB_REQ_GET_DESCRIPTOR: switch (ctrl->wValue >> 8) { case USB_DT_DEVICE: @@ -655,107 +695,95 @@ static bool lookup_connect_response_in(int fd, const struct vusb_connect_descrip } break; default: - break; - } + if (!resps || !done) + break; - debug("lookup_connect_response_in: unknown request"); - return false; -} + resps_num = (resps->len - offsetof(struct vusb_responses, resps)) / sizeof(resps->resps[0]); -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k + int i; + for (i = 0; i < resps_num; i++) { + struct vusb_response* resp = resps->resps[i]; + if (!resp) + continue; -// lookup_connect_response_out() functions process a USB OUT request and return in *done -// whether this is the last request that must be handled by syz_usb_connect* pseudo-syscalls. + if (resp->type == req_type && resp->req == req) { + *response_length = resp->len; -typedef bool (*lookup_connect_out_response_t)(int fd, const struct vusb_connect_descriptors* descs, - const struct usb_ctrlrequest* ctrl, bool* done); + if (*response_length != 0) + *response_data = &resp->data[0]; + else + *response_data = NULL; -#if SYZ_EXECUTOR || __NR_syz_usb_connect -static bool lookup_connect_response_out_generic(int fd, const struct vusb_connect_descriptors* descs, - const struct usb_ctrlrequest* ctrl, bool* done) -{ - switch (ctrl->bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - switch (ctrl->bRequest) { - case USB_REQ_SET_CONFIGURATION: - *done = true; + if (resp->expected != 0) + *done -= 1; + + return true; + } + } + + if (resps->generic) { + *response_data = &resps->generic->data[0]; + *response_length = resps->generic->len; return true; - default: - break; } break; } - debug("lookup_connect_response_out: unknown request"); + debug("lookup_connect_response_in: unknown request"); return false; } -#endif // SYZ_EXECUTOR || __NR_syz_usb_connect - -#if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k) -// drivers/net/wireless/ath/ath9k/hif_usb.h -#define ATH9K_FIRMWARE_DOWNLOAD 0x30 -#define ATH9K_FIRMWARE_DOWNLOAD_COMP 0x31 +// lookup_connect_response_out() functions process a USB OUT request and return in *done +// whether the number of requests left to be handled by syz_usb_connect* or syz_usb_finish_probe* +// pseudo-syscalls. -static bool lookup_connect_response_out_ath9k(int fd, const struct vusb_connect_descriptors* descs, - const struct usb_ctrlrequest* ctrl, bool* done) +static bool lookup_connect_response_out(int fd, const struct vusb_connect_descriptors* descs, + const struct vusb_responses* resps, const struct usb_ctrlrequest* ctrl, int* done) { - switch (ctrl->bRequestType & USB_TYPE_MASK) { + uint8 req = ctrl->bRequest; + uint8 req_type = ctrl->bRequestType; + int resps_num = 0; + + switch (req_type & USB_TYPE_MASK) { case USB_TYPE_STANDARD: - switch (ctrl->bRequest) { + switch (req) { case USB_REQ_SET_CONFIGURATION: + *done -= 1; return true; default: break; } - break; - case USB_TYPE_VENDOR: - switch (ctrl->bRequest) { - case ATH9K_FIRMWARE_DOWNLOAD: - return true; - case ATH9K_FIRMWARE_DOWNLOAD_COMP: - *done = true; - return true; - default: + + default: + if (!resps) break; + + resps_num = (resps->len - offsetof(struct vusb_responses, resps)) / sizeof(resps->resps[0]); + + 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) { + if (resp->expected != 0) + *done -= 1; + + return true; + } } break; } - debug("lookup_connect_response_out_ath9k: unknown request"); + debug("lookup_connect_response_out: unknown request"); return false; } -#endif // SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe #if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_control_io) -struct vusb_descriptor { - uint8 req_type; - uint8 desc_type; - uint32 len; - char data[0]; -} __attribute__((packed)); - -struct vusb_descriptors { - uint32 len; - struct vusb_descriptor* generic; - struct vusb_descriptor* descs[0]; -} __attribute__((packed)); - -struct vusb_response { - uint8 type; - uint8 req; - uint32 len; - char data[0]; -} __attribute__((packed)); - -struct vusb_responses { - uint32 len; - struct vusb_response* generic; - struct vusb_response* resps[0]; -} __attribute__((packed)); - // lookup_control_response() is a helper function that returns a response to a USB IN request based // on syzkaller-generated arguments provided to syz_usb_control_io* pseudo-syscalls. The data and its // length to be used as a response are returned in *response_data and *response_length. The return diff --git a/executor/common_usb_linux.h b/executor/common_usb_linux.h index b706663f8720..957b74e95162 100644 --- a/executor/common_usb_linux.h +++ b/executor/common_usb_linux.h @@ -81,7 +81,7 @@ struct usb_raw_eps_info { #define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32) #define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32) -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#if SYZ_EXECUTOR || __NR_syz_usb_connect static int usb_raw_open() { return open("/dev/raw-gadget", O_RDWR); @@ -100,7 +100,7 @@ static int usb_raw_run(int fd) { return ioctl(fd, USB_RAW_IOCTL_RUN, 0); } -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect #if SYZ_EXECUTOR || __NR_syz_usb_ep_write static int usb_raw_ep_write(int fd, struct usb_raw_ep_io* io) @@ -116,7 +116,7 @@ static int usb_raw_ep_read(int fd, struct usb_raw_ep_io* io) } #endif // SYZ_EXECUTOR || __NR_syz_usb_ep_read -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#if SYZ_EXECUTOR || __NR_syz_usb_connect static int usb_raw_configure(int fd) { @@ -128,9 +128,9 @@ static int usb_raw_vbus_draw(int fd, uint32 power) return ioctl(fd, USB_RAW_IOCTL_VBUS_DRAW, power); } -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io +#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || __NR_syz_usb_control_io static int usb_raw_ep0_write(int fd, struct usb_raw_ep_io* io) { return ioctl(fd, USB_RAW_IOCTL_EP0_WRITE, io); @@ -160,9 +160,9 @@ static int usb_raw_ep0_stall(int fd) { return ioctl(fd, USB_RAW_IOCTL_EP0_STALL, 0); } -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || __NR_syz_usb_control_io -#if SYZ_EXECUTOR || __NR_syz_usb_control_io +#if SYZ_EXECUTOR || __NR_syz_usb_control_io || __NR_syz_usb_finish_probe static int lookup_interface(int fd, uint8 bInterfaceNumber, uint8 bAlternateSetting) { struct usb_device_index* index = lookup_usb_index(fd); @@ -176,7 +176,7 @@ static int lookup_interface(int fd, uint8 bInterfaceNumber, uint8 bAlternateSett } return -1; } -#endif // SYZ_EXECUTOR || __NR_syz_usb_control_io +#endif // SYZ_EXECUTOR || __NR_syz_usb_control_io || __NR_syz_usb_finish_probe #if SYZ_EXECUTOR || __NR_syz_usb_ep_write || __NR_syz_usb_ep_read static int lookup_endpoint(int fd, uint8 bEndpointAddress) @@ -207,7 +207,7 @@ struct usb_raw_ep_io_data { char data[USB_MAX_PACKET_SIZE]; }; -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io +#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || __NR_syz_usb_control_io static void set_interface(int fd, int n) { struct usb_device_index* index = lookup_usb_index(fd); @@ -241,9 +241,9 @@ static void set_interface(int fd, int n) index->iface_cur = n; } } -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || __NR_syz_usb_control_io -#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#if SYZ_EXECUTOR || __NR_syz_usb_connect static int configure_device(int fd) { struct usb_device_index* index = lookup_usb_index(fd); @@ -266,8 +266,7 @@ static int configure_device(int fd) } static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const char* dev, - const struct vusb_connect_descriptors* descs, - lookup_connect_out_response_t lookup_connect_response_out) + const struct vusb_connect_descriptors* descs) { debug("syz_usb_connect: dev: %p\n", dev); if (!dev) { @@ -319,8 +318,8 @@ static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const ch } debug("syz_usb_connect: usb_raw_run success\n"); - bool done = false; - while (!done) { + int done = 1; + while (done > 0) { struct usb_raw_control_event event; event.inner.type = 0; event.inner.length = sizeof(event.ctrl); @@ -345,13 +344,14 @@ static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const ch 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)) { + if (!lookup_connect_response_in(fd, descs, NULL, &event.ctrl, &qual, + &response_data, &response_length, NULL)) { debug("syz_usb_connect: unknown request, stalling\n"); usb_raw_ep0_stall(fd); continue; } } else { - if (!lookup_connect_response_out(fd, descs, &event.ctrl, &done)) { + if (!lookup_connect_response_out(fd, descs, NULL, &event.ctrl, &done)) { debug("syz_usb_connect: unknown request, stalling\n"); usb_raw_ep0_stall(fd); continue; @@ -403,7 +403,7 @@ static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const ch return fd; } -#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k +#endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect #if SYZ_EXECUTOR || __NR_syz_usb_connect static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatile long a2, volatile long a3) @@ -413,21 +413,124 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil 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); + return syz_usb_connect_impl(speed, dev_len, dev, descs); } #endif // SYZ_EXECUTOR || __NR_syz_usb_connect -#if SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k -static volatile long syz_usb_connect_ath9k(volatile long a0, volatile long a1, volatile long a2, volatile long a3) +// syz_usb_finish_probe pseudo-syscall should be used to achieve better code coverage in those select usb drivers +// that require a multitude of IN/OUT control requests during probe. Provided necessary syzlang +// descriptions of vusb_responses are prepared, this call will run after initial steps are +// performed by syz_usb_connect. During such run, syz_usb_finish_probe will attempt to satisfy +// driver-specific requests until, ideally, driver probe finishes well. + +#if SYZ_EXECUTOR || __NR_syz_usb_finish_probe +static volatile long syz_usb_finish_probe(volatile long a0, volatile long a1, volatile long a2) { - uint64 speed = a0; - uint64 dev_len = a1; - const char* dev = (const char*)a2; - const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a3; + int fd = a0; + const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a1; + const struct vusb_responses* resps = (const struct vusb_responses*)a2; + + // Calculate the total number of expected CTRL requests to process during probe to properly finish it. + // Start with 0, as universally required SET_CONFIGURATION request should have been processed already. + int done = 0; + if (resps) { + int resps_num = (resps->len - offsetof(struct vusb_responses, resps)) / sizeof(resps->resps[0]); + for (int i = 0; i < resps_num; i++) { + struct vusb_response* resp = resps->resps[i]; + if (resp->expected != 0) + done += resp->expected; + } + } + debug("syz_usb_finish_probe: total number of control requests to process: %d", done); - return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_ath9k); + while (done > 0) { + struct usb_raw_control_event event; + event.inner.type = 0; + event.inner.length = USB_MAX_PACKET_SIZE; + + int rv = usb_raw_event_fetch(fd, (struct usb_raw_event*)&event); + if (rv < 0) { + debug("syz_usb_finish_probe: usb_raw_event_fetch failed with %d\n", rv); + return rv; + } + if (event.inner.type != USB_RAW_EVENT_CONTROL) + continue; + + debug("syz_usb_finish_probe: bReqType: 0x%x (%s), bReq: 0x%x, wVal: 0x%x, wIdx: 0x%x, wLen: %d\n", + event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT", + event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength); + +#if USB_DEBUG + analyze_control_request(fd, &event.ctrl); +#endif + + char* response_data = NULL; + uint32 response_length = 0; + struct usb_qualifier_descriptor qual; + + if (event.ctrl.bRequestType & USB_DIR_IN) { + if (!lookup_connect_response_in(fd, descs, resps, &event.ctrl, &qual, + &response_data, &response_length, &done)) { + debug("syz_usb_finish_probe: unknown request (IN), stalling\n"); + usb_raw_ep0_stall(fd); + continue; + } + } else { + if (!lookup_connect_response_out(fd, descs, resps, &event.ctrl, &done)) { + debug("syz_usb_finish_probe: unknown request (OUT), stalling\n"); + usb_raw_ep0_stall(fd); + continue; + } + response_data = NULL; + response_length = event.ctrl.wLength; + } + + if ((event.ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD && + event.ctrl.bRequest == USB_REQ_SET_INTERFACE) { + int iface_num = event.ctrl.wIndex; + int alt_set = event.ctrl.wValue; + debug("syz_usb_finish_probe: setting interface (%d, %d)\n", iface_num, alt_set); + int iface_index = lookup_interface(fd, iface_num, alt_set); + if (iface_index < 0) { + debug("syz_usb_finish_probe: interface (%d, %d) not found\n", iface_num, alt_set); + } else { + set_interface(fd, iface_index); + debug("syz_usb_finish_probe: interface (%d, %d) set\n", iface_num, alt_set); + } + } + + struct usb_raw_ep_io_data response; + response.inner.ep = 0; + response.inner.flags = 0; + if (response_length > sizeof(response.data)) + response_length = 0; + if (event.ctrl.wLength < response_length) + response_length = event.ctrl.wLength; + response.inner.length = response_length; + if (response_data) + memcpy(&response.data[0], response_data, response_length); + else + memset(&response.data[0], 0, response_length); + + if (event.ctrl.bRequestType & USB_DIR_IN) { + debug("syz_usb_finish_probe: writing %d bytes\n", response.inner.length); + rv = usb_raw_ep0_write(fd, (struct usb_raw_ep_io*)&response); + } else { + rv = usb_raw_ep0_read(fd, (struct usb_raw_ep_io*)&response); + debug("syz_usb_finish_probe: read %d bytes\n", response.inner.length); + debug_dump_data(&event.data[0], response.inner.length); + } + if (rv < 0) { + debug("syz_usb_finish_probe: usb_raw_ep0_read/write failed with %d\n", rv); + return rv; + } + } + + sleep_ms(200); + + return 0; } -#endif // SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k +#endif // SYZ_EXECUTOR || __NR_syz_usb_finish_probe || __NR_syz_usb_connect #if SYZ_EXECUTOR || __NR_syz_usb_control_io static volatile long syz_usb_control_io(volatile long a0, volatile long a1, volatile long a2) diff --git a/executor/common_usb_netbsd.h b/executor/common_usb_netbsd.h index 562d78278030..d98fd5dc6976 100644 --- a/executor/common_usb_netbsd.h +++ b/executor/common_usb_netbsd.h @@ -9,6 +9,7 @@ #include #include #include +#include #include // Redefinitions to match the linux types used in common_usb.h. @@ -205,8 +206,7 @@ static int vhci_usb_send(int fd, void* buf, size_t size) } static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len, - const char* dev, const struct vusb_connect_descriptors* descs, - lookup_connect_out_response_t lookup_connect_response_out) + const char* dev, const struct vusb_connect_descriptors* descs) { struct usb_device_index* index = add_usb_index(fd, dev, dev_len); if (!index) { @@ -228,8 +228,8 @@ static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len, } debug("syz_usb_connect: vhci_usb_attach success\n"); - bool done = false; - while (!done) { + int done = 1; + while (done > 0) { vhci_request_t req; if (vhci_usb_recv(fd, &req, sizeof(req))) { @@ -255,12 +255,13 @@ static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len, char data[4096]; if (req.u.ctrl.bmRequestType & UE_DIR_IN) { - if (!lookup_connect_response_in(fd, descs, (const struct usb_ctrlrequest*)&req.u.ctrl, &qual, &response_data, &response_length)) { + if (!lookup_connect_response_in(fd, descs, NULL, (const struct usb_ctrlrequest*)&req.u.ctrl, &qual, + &response_data, &response_length, NULL)) { debug("syz_usb_connect: unknown control IN request\n"); return -1; } } else { - if (!lookup_connect_response_out(fd, descs, (const struct usb_ctrlrequest*)&req.u.ctrl, &done)) { + if (!lookup_connect_response_out(fd, descs, NULL, (const struct usb_ctrlrequest*)&req.u.ctrl, &done)) { debug("syz_usb_connect: unknown control OUT request\n"); return -1; } @@ -328,7 +329,7 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, int fd = vhci_open(); if (fd < 0) fail("syz_usb_connect: vhci_open failed"); - long res = syz_usb_connect_impl(fd, speed, dev_len, dev, descs, &lookup_connect_response_out_generic); + long res = syz_usb_connect_impl(fd, speed, dev_len, dev, descs); close(fd); return res; } diff --git a/pkg/vminfo/linux_syscalls.go b/pkg/vminfo/linux_syscalls.go index 605b939d255b..cf45c7d39cf4 100644 --- a/pkg/vminfo/linux_syscalls.go +++ b/pkg/vminfo/linux_syscalls.go @@ -74,7 +74,7 @@ var linuxSyscallChecks = map[string]func(*checkContext, *prog.Syscall) string{ "syz_emit_ethernet": linuxNetInjectionSupported, "syz_extract_tcp_res": linuxNetInjectionSupported, "syz_usb_connect": linuxCheckUSBEmulation, - "syz_usb_connect_ath9k": linuxCheckUSBEmulation, + "syz_usb_finish_probe": linuxCheckUSBEmulation, "syz_usb_disconnect": linuxCheckUSBEmulation, "syz_usb_control_io": linuxCheckUSBEmulation, "syz_usb_ep_write": linuxCheckUSBEmulation, diff --git a/sys/linux/test/vusb_ath9k b/sys/linux/test/vusb_ath9k index a728664f006d..f678f06752b3 100644 --- a/sys/linux/test/vusb_ath9k +++ b/sys/linux/test/vusb_ath9k @@ -1,4 +1,3 @@ -# requires: -repeat - -r0 = syz_usb_connect_ath9k(0x3, 0x5a, &(0x7f0000000080)={{0x12, 0x1, 0x200, 0xff, 0xff, 0xff, 0x40, 0xcf3, 0x9271, 0x108, 0x1, 0x2, 0x3, 0x1, [{{0x9, 0x2, 0x48, 0x1, 0x1, 0x0, 0x80, 0xfa, {{0x9, 0x4, 0x0, 0x0, 0x6, 0xff, 0x0, 0x0, 0x0, "", {{0x9, 0x5, 0x1, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x82, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x83, 0x3, 0x40, 0x1, 0x0, 0x0, ""}, {0x9, 0x5, 0x4, 0x3, 0x40, 0x1, 0x0, 0x0, ""}, {0x9, 0x5, 0x5, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x6, 0x2, 0x200, 0x0, 0x0, 0x0, ""}}}}}}]}}, 0x0) -syz_usb_ep_write$ath9k_ep2(r0, 0x83, 0x10, &(0x7f0000000000)=@ready={0x0, 0x0, 0x8, 'BBBB', {0x1, 0x0, 0x0, 0x0, 0x0}}) +r0 = syz_usb_connect$ath9k(0x3, 0x5a, &(0x7f0000000000)={{0x12, 0x1, 0x200, 0xff, 0xff, 0xff, 0x40, 0xcf3, 0x9271, 0x108, 0x1, 0x2, 0x3, 0x1, [{{0x9, 0x2, 0x48, 0x1, 0x1, 0x0, 0x80, 0xfa, {{0x9, 0x4, 0x0, 0x0, 0x6, 0xff, 0x0, 0x0, 0x0, "", {{0x9, 0x5, 0x1, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x82, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x83, 0x3, 0x40, 0x1, 0x0, 0x0, ""}, {0x9, 0x5, 0x4, 0x3, 0x40, 0x1, 0x0, 0x0, ""}, {0x9, 0x5, 0x5, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x6, 0x2, 0x200, 0x0, 0x0, 0x0, ""}}}}}}]}}, 0x0) +syz_usb_finish_probe$ath9k(r0, 0x0, &(0x7f0000000380)={0x2c, 0x0, &(0x7f0000000280)={0x0, 0xa, 0x1, 0x0, 0xd}, &(0x7f00000002c0)={0x0, 0x8, 0x1, 0x0, 0x4}, &(0x7f0000000300)={0x40, 0x30, 0x1, 0x0, 0x3}, 0x0}) +syz_usb_finish_probe$ath9k(r0, &(0x7f00000035c0)={0x14, &(0x7f00000034c0)={0x20, 0x22, 0x94, {0x94, 0x11, "a2a13e09168575e6c1e3ef43030e87b9cd863287d915f2d5e760ab9dcee9c61081e78317d32d1ac866fee42eda8b290e19888fbe3a812a332ef5fbf599a14cd83be9bbc95c75f0616759edaff87a32a51af9e55301d43a0512faf3de6cecd873783848de421d45126c9e1d002ab6685732f1000c9c5d36216f34a57c0fbd9a71675924a0a7bdda1a6302b70cb5a2b9828e94"}}, &(0x7f0000003580)={0x0, 0x3, 0x4, @lang_id={0x4, 0x3, 0x804}}}, &(0x7f0000003740)={0x2c, &(0x7f0000003600)={0x40, 0x8, 0x18, 0x0, "d6722ee2ed76787bde297f418de0725b92e0db0da0ac8fe8"}, 0x0, 0x0, &(0x7f00000036c0)={0x40, 0x30, 0x1, 0x0, 0x4c}, &(0x7f0000003700)={0x40, 0x31, 0x1, 0x1, 0x4}}) diff --git a/sys/linux/test/vusb_cdc_ncm b/sys/linux/test/vusb_cdc_ncm index 4ffdb5efab6e..b9d0e26ff56d 100644 --- a/sys/linux/test/vusb_cdc_ncm +++ b/sys/linux/test/vusb_cdc_ncm @@ -3,7 +3,7 @@ r0 = syz_usb_connect$cdc_ncm(0x0, 0x6e, &(0x7f0000000480)={{0x12, 0x1, 0x0, 0x2, 0x0, 0x0, 0x40, 0x525, 0xa4a1, 0x40, 0x1, 0x2, 0x3, 0x1, [{{0x9, 0x2, 0x5c, 0x2, 0x1, 0x0, 0x0, 0x0, {{0x9, 0x4, 0x0, 0x0, 0x1, 0x2, 0xd, 0x0, 0x0, {{0x5, 0x24, 0x6, 0x0, 0x1, ""}, {0x5, 0x24, 0x0, 0x0}, {0xd, 0x24, 0xf, 0x1, 0x0, 0x0, 0x0, 0x0}, {0x6, 0x24, 0x1a, 0x0, 0x0}, []}, {{0x9, 0x5, 0x81, 0x3, 0x200, 0x0, 0x0, 0x0, ""}}}, {0x9, 0x4, 0x1, 0x0, 0x0, 0x2, 0xd, 0x0, 0x0, "", ""}, {0x9, 0x4, 0x1, 0x1, 0x2, 0x2, 0xd, 0x0, 0x0, "", {{{0x9, 0x5, 0x82, 0x2, 0x200, 0x0, 0x0, 0x0, ""}}, {{0x9, 0x5, 0x3, 0x2, 0x200, 0x0, 0x0, 0x0, ""}}}}}}}]}}, 0x0) syz_usb_control_io$cdc_ncm(r0, 0x0, 0x0) syz_usb_control_io$cdc_ncm(r0, 0x0, 0x0) -syz_usb_control_io$cdc_ncm(r0, 0x0, &(0x7f0000000340)={0x44, 0x0, 0x0, 0x0, &(0x7f0000000200)={0x20, 0x80, 0x1c, {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$cdc_ncm(r0, 0x0, &(0x7f0000000340)={0x44, 0x0, 0x0, 0x0, &(0x7f0000000200)={0x20, 0x80, 0x1c, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, 0x0, 0x0, 0x0, 0x0}) syz_usb_control_io$cdc_ncm(r0, 0x0, 0x0) syz_usb_control_io$cdc_ncm(r0, &(0x7f0000000080)={0x14, 0x0, &(0x7f0000000040)={0x0, 0x3, 0x1a, {0x1a, 0x3, {0x3400320034003200, 0x3400320034003200, 0x3400320034003200}}}}, 0x0) syz_usb_ep_write(r0, 0x82, 0x5, &(0x7f0000002340)='hello') diff --git a/sys/linux/test/vusb_lan78xx b/sys/linux/test/vusb_lan78xx index 461ff482567a..4d628a45becb 100644 --- a/sys/linux/test/vusb_lan78xx +++ b/sys/linux/test/vusb_lan78xx @@ -16,11 +16,11 @@ r0 = syz_usb_connect$lan78xx(0x5, 0x3f, &(0x7f0000000000)={{0x12, 0x1, 0x200, 0x # Write to INT_EP_CTL register in lan78xx_setup_irq_domain(). -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f00000003c0)={0x34, &(0x7f0000000140)={0x20, 0x11, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f00000003c0)={0x34, &(0x7f0000000140)={0x20, 0x11, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) # Write to HW_CFG register in lan78xx_reset(). -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000000780)={0x34, &(0x7f0000000600)={0x40, 0x11, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000000780)={0x34, &(0x7f0000000600)={0x40, 0x11, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) # Read from HW_CFG register. @@ -28,12 +28,12 @@ syz_usb_control_io$lan78xx(r0, 0x0, 0x0) # Write to HW_CFG register. -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000000f00)={0x34, &(0x7f0000000cc0)={0x40, 0x10, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000000f00)={0x34, &(0x7f0000000cc0)={0x40, 0x10, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) # Write to RX_ADDRL and RX_ADDRH registers in lan78xx_init_mac_address(). -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000001240)={0x34, &(0x7f0000001080)={0x0, 0x6, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000001700)={0x34, &(0x7f0000001500)={0x20, 0x18, 0x1, ')'}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000001240)={0x34, &(0x7f0000001080)={0x0, 0x6, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000001700)={0x34, &(0x7f0000001500)={0x20, 0x18, 0x1, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) # Read from MAF_LO(0) and MAF_HI(0) registers. @@ -46,12 +46,12 @@ syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000002180)={0x34, &(0x7f0000000400)=A # Write and read to/from USB_CFG0 register. -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f00000006c0)={0x34, &(0x7f0000000500)={0x0, 0x7, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f00000006c0)={0x34, &(0x7f0000000500)={0x0, 0x7, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) syz_usb_control_io$lan78xx(r0, 0x0, 0x0) # Write to USB_CFG1 register in lan78xx_init_ltm(). -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000002540)={0x34, &(0x7f0000002340)={0x0, 0xf, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000002540)={0x34, &(0x7f0000002340)={0x0, 0xf, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) # Read from 6 registers (LTM_BELT_IDLE0 etc.) in a row. @@ -69,4 +69,4 @@ syz_usb_control_io$lan78xx(r0, 0x0, 0x0) # Write to HW_CFG register. -syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000000380)={0x34, &(0x7f0000000840)={0x0, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) +syz_usb_control_io$lan78xx(r0, 0x0, &(0x7f0000000380)={0x34, &(0x7f0000000840)={0x0, 0x0, 0x0, 0x0, ""}, 0x0, 0x0, 0x0, 0x0, 0x0}) diff --git a/sys/linux/test/vusb_legousbtower b/sys/linux/test/vusb_legousbtower new file mode 100644 index 000000000000..cc854aeb96e0 --- /dev/null +++ b/sys/linux/test/vusb_legousbtower @@ -0,0 +1,2 @@ +r0 = syz_usb_connect$legousbtower(0x5, 0x36, &(0x7f0000000000)={{0x12, 0x1, 0x200, 0xff, 0xff, 0xff, 0x40, 0x694, 0x1, 0x0, 0x1, 0x2, 0x3, 0x1, [{{0x9, 0x2, 0x24, 0x1, 0x1, 0x0, 0x80, 0xfa, {{0x9, 0x4, 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, "", {{0x9, 0x5, 0x83, 0x3, 0x1e0, 0x1, 0x0, 0x0, ""}, {0x9, 0x5, 0x3, 0x3, 0x1e0, 0x1, 0x0, 0x0, ""}}}}}}]}}, 0x0) +syz_usb_finish_probe$legousbtower(r0, 0x0, &(0x7f00000002c0)={0x24, 0x0, &(0x7f0000000200)={0x0, 0xa, 0x1, 0x0, 0x3}, &(0x7f0000000240)={0x0, 0x8, 0x1, 0x0, 0x8}, &(0x7f0000000280)={0xc0, 0xfd, 0x8, 0x1, "44f50842208d9f75"}}) diff --git a/sys/linux/test/vusb_printer b/sys/linux/test/vusb_printer index 59a9048f79aa..78d35b736b7e 100644 --- a/sys/linux/test/vusb_printer +++ b/sys/linux/test/vusb_printer @@ -2,4 +2,4 @@ r0 = syz_usb_connect$printer(0x0, 0x36, &(0x7f0000000000)={{0x12, 0x1, 0x0, 0x0, 0x0, 0x0, 0x20, 0x3f0, 0x6c17, 0x40, 0x0, 0x0, 0x0, 0x1, [{{0x9, 0x2, 0x24, 0x1, 0x0, 0x0, 0x0, 0x0, [{{0x9, 0x4, 0x0, 0x0, 0x12, 0x7, 0x1, 0x3, 0x0, "", {{{0x9, 0x5, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, ""}}, [{{0x9, 0x5, 0x82, 0x2, 0x0, 0x0, 0x0, 0x0, ""}}]}}}]}}]}}, 0x0) syz_usb_control_io$printer(r0, 0x0, 0x0) -syz_usb_control_io$printer(r0, 0x0, &(0x7f0000000400)={0x34, 0x0, 0x0, 0x0, 0x0, 0x0, &(0x7f00000003c0)={0x20, 0x0, 0x1, 0x0}}) +syz_usb_control_io$printer(r0, 0x0, &(0x7f0000000400)={0x34, 0x0, 0x0, 0x0, 0x0, 0x0, &(0x7f00000003c0)={0x20, 0x0, 0x1, 0x0, 0x0}}) diff --git a/sys/linux/test/vusb_r8152 b/sys/linux/test/vusb_r8152 new file mode 100644 index 000000000000..8d6ab4e81c3e --- /dev/null +++ b/sys/linux/test/vusb_r8152 @@ -0,0 +1,3 @@ +r0 = syz_usb_connect$r8152(0x5, 0x3f, &(0x7f0000000680)={{0x12, 0x1, 0x200, 0xff, 0xff, 0xff, 0x40, 0xbda, 0x8050, 0x0, 0x1, 0x2, 0x3, 0x1, [{{0x9, 0x2, 0x2d, 0x1, 0x1, 0x0, 0x80, 0xfa, {{0x9, 0x4, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, "", {{0x9, 0x5, 0x81, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x2, 0x2, 0x200, 0x0, 0x0, 0x0, ""}, {0x9, 0x5, 0x83, 0x3, 0x40, 0x1, 0x0, 0x0, ""}}}}}}]}}, 0x0) +syz_usb_finish_probe$r8152(r0, 0x0, &(0x7f0000001100)={0x34, 0x0, &(0x7f0000000fc0)={0x0, 0xa, 0x1, 0x0, 0x2}, &(0x7f0000001000)={0x0, 0x8, 0x1, 0x0, 0x2}, &(0x7f0000001040)={0xc0, 0x5, 0x4, 0x2, 0x60000000}, &(0x7f0000001080)={0xc0, 0x5, 0x0, 0x0, ""}, &(0x7f00000010c0)={0x40, 0x5, 0x2, 0x0, ""/2}}) +syz_usb_finish_probe$r8152(r0, 0x0, &(0x7f0000001700)={0x34, 0x0, &(0x7f00000015c0)={0x0, 0xa, 0x1, 0x0, 0x4}, &(0x7f0000001600)={0x0, 0x8, 0x1, 0x0, 0xe}, &(0x7f0000001640)={0xc0, 0x5, 0x4, 0x2, 0x10740000}, &(0x7f0000001680)={0xc0, 0x5, 0x0, 0x0, ""}, &(0x7f00000016c0)={0x40, 0x5, 0x4, 0x0, ""/4}}) diff --git a/sys/linux/test/vusb_rtl8150 b/sys/linux/test/vusb_rtl8150 index 6f8accf7c329..27de529b3023 100644 --- a/sys/linux/test/vusb_rtl8150 +++ b/sys/linux/test/vusb_rtl8150 @@ -22,4 +22,4 @@ syz_usb_control_io$rtl8150(r0, 0x0, 0x0) # Send a request via get_registers(). Sent data should make the while{} loop in rtl8150_reset() stop early. -syz_usb_control_io$rtl8150(r0, 0x0, &(0x7f0000004280)={0x2c, 0x0, 0x0, 0x0, 0x0, &(0x7f0000004240)={0x40, 0x5, 0x2, "2bd8"}}) +syz_usb_control_io$rtl8150(r0, 0x0, &(0x7f0000004280)={0x2c, 0x0, 0x0, 0x0, 0x0, &(0x7f0000004240)={0x40, 0x5, 0x2, 0x0, ""}}) diff --git a/sys/linux/test/vusb_usbdux b/sys/linux/test/vusb_usbdux new file mode 100644 index 000000000000..debe19b83695 --- /dev/null +++ b/sys/linux/test/vusb_usbdux @@ -0,0 +1,2 @@ +r0 = syz_usb_connect$usbdux(0x3, 0x5a, &(0x7f0000000280)={{0x12, 0x1, 0x200, 0xff, 0xff, 0xff, 0x40, 0x13d8, 0x1, 0x0, 0x1, 0x2, 0x3, 0x1, [{{0x9, 0x2, 0x48, 0x1, 0x1, 0x0, 0x80, 0xfa, {{0x9, 0x4, 0x0, 0x0, 0x2, 0xff, 0x0, 0x0, 0x0, "", []}, {0x9, 0x4, 0x0, 0x1, 0x2, 0xff, 0x0, 0x0, 0x0, "", [{{0x9, 0x5, 0xc6c9e1590b4e87ba, 0x4, 0x8, 0x7, 0xe, 0x52, []}}, {{0x9, 0x5, 0xa, 0x0, 0x10, 0xc, 0x2, 0x5, []}}]}, {0x9, 0x4, 0x0, 0x2, 0x2, 0xff, 0x0, 0x0, 0x0, "", []}, {0x9, 0x4, 0x0, 0x3, 0x2, 0xff, 0x0, 0x0, 0x0, "", [{{0x9, 0x5, 0x6, 0x0, 0x0, 0x5, 0x9, 0x2, []}}]}}}}]}}, 0x0) +syz_usb_finish_probe$usbdux(r0, 0x0, &(0x7f0000000900)={0x2c, 0x0, &(0x7f0000000800)={0x0, 0xa, 0x1, 0x0, 0x1}, &(0x7f0000000840)={0x0, 0x8, 0x1, 0x0, 0x5}, &(0x7f0000000880)={0x1, 0xb, 0x1, 0x1, 0x15}, &(0x7f00000008c0)={0x40, 0xa0, 0x1, 0x3, 0x1}}) diff --git a/sys/linux/vusb.txt b/sys/linux/vusb.txt index 217552ac7237..ba39851c179d 100644 --- a/sys/linux/vusb.txt +++ b/sys/linux/vusb.txt @@ -228,19 +228,30 @@ vusb_responses { } [packed] vusb_response_generic { - type flags[usb_request_types, int8] - req flags[usb_requests, int8] - len bytesize[data, int32] - data array[int8, 0:256] + type flags[usb_request_types, int8] + req flags[usb_requests, int8] + len bytesize[data, int32] + expected const[0, int32] + data array[int8, 0:256] } [packed] usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM type vusb_response_t[CLASS, REQ, DATA] { - type const[CLASS, int8] - req const[REQ, int8] - len bytesize[data, int32] - data DATA + type const[CLASS, int8] + req const[REQ, int8] + len bytesize[data, int32] + expected const[0, int32] + data DATA +} [packed] + +# Response of this type MUST be processed EXP number of times to finish syz_usb_connect_scripted(). +type vusb_response_expected_t[CLASS, REQ, EXP, DATA] { + type const[CLASS, int8] + req const[REQ, int8] + len bytesize[data, int32] + expected const[EXP, int32] + data DATA } [packed] # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -1329,7 +1340,49 @@ vusb_responses_uac1 { # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Assorted driver-specific descriptions of generic syz_* calls' variants. + +# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough +# (in theory) to emulate a proper device and finish driver probes without a hitch. +# However, there are cases when syzkaller fails to come up with correct inputs to achieve it. +# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality. + +# It is important to note that, one way or another, drivers in question require multiple control requests +# between a driver and a device processed during probe(). Descriptions below do not deal with specific +# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on +# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX. + +# Another approach for dealing with multiple post-enumeration, post-SET_CONFIGURATION control requests +# would be to use pseudo-call syz_usb_finish_probe. Provided necessary CTRL-requests are described in +# vusb_responses_XXX structs (as well as the number of times each request is supposed to be dealt with, +# see struct vusb_response_expected_t), this call will run after initial usb device setup is done in +# syz_usb_connect. Then, it will attempt to respond to all expected requests to ensure that driver probe is +# successful. + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# Common constants for endpoint descriptors. +define USB_ENDPOINT_BULK_ATTR (USB_ENDPOINT_XFER_BULK) +define USB_ENDPOINT_INT_ATTR (USB_ENDPOINT_XFER_INT) + +define USB_FIXED_ENDPOINT_BULK_IN_ADDR (1 | USB_DIR_IN) +define USB_FIXED_ENDPOINT_BULK_OUT_ADDR (2) +define USB_FIXED_ENDPOINT_INT_IN_ADDR (3 | USB_DIR_IN) +define USB_FIXED_ENDPOINT_INT_OUT_ADDR (3) + +define USB_RECIP_DEVICE 0x00 + +vusb_descriptors_common { + len len[parent, int32] + generic ptr[in, vusb_descriptor_generic] + + USB_DT_STRING ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]] +} [packed] + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # ath9k driver specific descriptions. +# Use syz_usb_finish_probe to facilitate ath9k-related firmware setup. include include @@ -1343,7 +1396,9 @@ define USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS (6) resource fd_usb_ath9k[fd_usb] -syz_usb_connect_ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover) +syz_usb_connect$ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover) +syz_usb_finish_probe$ath9k(fd fd_usb_ath9k, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_ath9k]) (timeout[3000], prog_timeout[3000], remote_cover) + syz_usb_ep_write$ath9k_ep1(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS], len bytesize[data], data ptr[in, ath9k_bulk_frame]) (timeout[300], remote_cover) syz_usb_ep_write$ath9k_ep2(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS], len bytesize[data], data ptr[in, htc_frame]) (timeout[300], remote_cover) @@ -1371,6 +1426,21 @@ usb_endpoint_descriptors_ath9k { define USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES (USB_ENDPOINT_XFER_BULK) define USB_ENDPOINT_ATH9K_INT_ATTRIBUTES (USB_ENDPOINT_XFER_INT) +vusb_responses_ath9k { + len len[parent, int32] + generic ptr[in, vusb_response_generic] + + USB_REQ_GET_INTERFACE ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]] + USB_REQ_GET_CONFIGURATION ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]] +# Ensure that syzkaller deals with ath9k-firmware download, otherwise probe fails. + FIRMWARE_DOWNLOAD ptr[in, vusb_response_t[ATH9K_REQ_TYPE, FIRMWARE_DOWNLOAD, int8]] + FIRMWARE_DOWNLOAD_COMP ptr[in, vusb_response_expected_t[ATH9K_REQ_TYPE, FIRMWARE_DOWNLOAD_COMP, 1, int8]] +} [packed] + +define ATH9K_REQ_TYPE 0x40 +define FIRMWARE_DOWNLOAD 0x30 +define FIRMWARE_DOWNLOAD_COMP 0x31 + ath9k_bulk_frame { packets array[ath9k_bulk_packet] } [packed] @@ -1435,32 +1505,6 @@ htc_generic_frame { htc_frame_flags = HTC_FLAGS_RECV_TRAILER -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - -# Assorted driver-specific descriptions of generic syz_* calls' variants. - -# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough -# (in theory) to emulate a proper device and finish driver probes without a hitch. -# However, there are cases when syzkaller fails to come up with correct inputs to achieve it. -# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality. - -# It is important to note that, one way or another, drivers in question require multiple control requests -# between a driver and a device processed during probe(). Descriptions below do not deal with specific -# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on -# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX. - -# Common constants for endpoint descriptors. -define USB_ENDPOINT_BULK_ATTR (USB_ENDPOINT_XFER_BULK) -define USB_ENDPOINT_INT_ATTR (USB_ENDPOINT_XFER_INT) - -define USB_FIXED_ENDPOINT_BULK_IN_ADDR (1 | USB_DIR_IN) -define USB_FIXED_ENDPOINT_BULK_OUT_ADDR (2) -define USB_FIXED_ENDPOINT_INT_IN_ADDR (3 | USB_DIR_IN) - -define USB_RECIP_DEVICE 0x00 - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # rtl8150 driver specific descriptions. @@ -1610,3 +1654,149 @@ vusb_responses_lan78xx { define LAN78XX_REG_TYPE_IN (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) define LAN78XX_REG_TYPE_OUT (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# rtl8152 driver (drivers/net/usb/r8152.c) specific descriptions. +# Use pseudo-syscall 'syz_usb_finish_probe' to get past USB control requests. + +include + +resource fd_usb_r8152[fd_usb] + +syz_usb_connect$r8152(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_r8152], conn_descs const[0]) fd_usb_r8152 (timeout[3000], prog_timeout[3000], remote_cover) +syz_usb_finish_probe$r8152(fd fd_usb_r8152, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_r8152]) (timeout[3000], prog_timeout[3000], remote_cover) + +syz_usb_control_io$r8152(fd fd_usb_r8152, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_r8152]) (timeout[300], remote_cover) + +usb_device_descriptor_r8152 { + inner usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xbda, 0x8050, 0, array[usb_config_descriptor_r8152, 1]] +} [packed] + +usb_config_descriptor_r8152 { + inner usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_r8152] +} [packed] + +usb_interface_descriptor_r8152 { + iface usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_r8152] +} [packed] + +usb_endpoint_descriptors_r8152 { + bulk_out usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void] + bulk_in usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void] + int_in usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void] +} [packed] + +# While these responses to CTRL requests are enough to finish probing, there are numerous +# other requests expected during rtl_ops.init() stage, see: https://elixir.bootlin.com/linux/v6.17-rc5/source/drivers/net/usb/r8152.c#L9920. +# TODO: Figure out the way to account for them too. +vusb_responses_r8152 { + len len[parent, int32] + generic ptr[in, vusb_response_generic] + + USB_REQ_GET_INTERFACE ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]] + USB_REQ_GET_CONFIGURATION ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]] + +# This is the minimal required CTRL request that needs to be processed 2 times, +# most importantly, here: https://elixir.bootlin.com/linux/v6.17-rc6/source/drivers/net/usb/r8152.c#L9662 +# Mix up correct and incorrect version values to access different error paths along the way. + RTL8152_GET_VERSION ptr[in, vusb_response_expected_t[RTL8152_REQT_READ, RTL8152_REQ_GET_REGS, 2, int32[r8152_versions]]] + + RTL8152_REQ_GET_REGS ptr[in, vusb_response_t[RTL8152_REQT_READ, RTL8152_REQ_GET_REGS, array[int8, 0:4]]] + RTL8152_REQ_SET_REGS ptr[out, vusb_response_t[RTL8152_REQT_WRITE, RTL8152_REQ_SET_REGS, array[int8, 0:4]]] +} [packed] + +# r8152 encapsulates multiple subdrivers depending on hardware. Try all of them to increase coverage. +r8152_versions = 0x4c000000, 0x104c0000, 0x5c000000, 0x105c0000, 0x205c0000, 0x305c0000, 0x48000000, 0x60000000, 0x10600000, 0x10700000, 0x20700000, 0x30700000, 0x74000000, 0x10740000, 0x64000000, 0x20740000, 0x0 + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# legousbtower driver (drivers/usb/misc/legousbtower.c) specific descriptions +# Use pseudo-syscall 'syz_usb_finish_probe' to get past USB control requests. + +resource fd_usb_legousbtower[fd_usb] + +syz_usb_connect$legousbtower(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_legousbtower], conn_descs const[0]) fd_usb_legousbtower (timeout[3000], prog_timeout[3000], remote_cover) +syz_usb_finish_probe$legousbtower(fd fd_usb_legousbtower, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_legousbtower]) (timeout[3000], prog_timeout[3000], remote_cover) + +syz_usb_control_io$legousbtower(fd fd_usb_legousbtower, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_legousbtower]) (timeout[300], remote_cover) + +usb_device_descriptor_legousbtower { + inner usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x694, 0x1, 0, array[usb_config_descriptor_legousbtower, 1]] +} [packed] + +usb_config_descriptor_legousbtower { + inner usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_legousbtower] +} [packed] + +usb_interface_descriptor_legousbtower { + iface usb_interface_descriptor_fixed_t[0, 0, 2, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_legousbtower] +} [packed] + +usb_endpoint_descriptors_legousbtower { + int_in usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 480, 1, void] + int_out usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_OUT_ADDR, USB_ENDPOINT_INT_ATTR, 480, 1, void] +} [packed] + +vusb_responses_legousbtower { + len len[parent, int32] + generic ptr[in, vusb_response_generic] + + USB_REQ_GET_INTERFACE ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]] + USB_REQ_GET_CONFIGURATION ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]] + +# This request needs to be processed at least 1 time, +# see https://elixir.bootlin.com/linux/v6.17-rc6/source/drivers/usb/misc/legousbtower.c#L792 + LEGO_USB_TOWER_REQUEST_GET_VERSION ptr[in, vusb_response_expected_t[LEGO_USB_TOWER_REQ_TYPE, LEGO_USB_TOWER_REQUEST_GET_VERSION, 1, array[int8, 8]]] +} [packed] + +define LEGO_USB_TOWER_REQ_TYPE (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE) +define LEGO_USB_TOWER_REQUEST_GET_VERSION 0xfd + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +# usbdux driver (drivers/comedi/drivers/usbdux.c) specific descriptions +# Use pseudo-syscall 'syz_usb_finish_probe' to get past USB control requests. + +# Note: this driver requires specific firmware that is a part of 'linux-firmware' package. + +resource fd_usb_usbdux[fd_usb] + +syz_usb_connect$usbdux(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_usbdux], conn_descs const[0]) fd_usb_usbdux (timeout[3000], prog_timeout[3000], remote_cover) +syz_usb_finish_probe$usbdux(fd fd_usb_usbdux, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_usbdux]) (timeout[3000], prog_timeout[3000], remote_cover) + +syz_usb_control_io$usbdux(fd fd_usb_usbdux, descs ptr[in, vusb_descriptors_common], resps ptr[in, vusb_responses_usbdux]) (timeout[300], remote_cover) + +usb_device_descriptor_usbdux { + inner usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x13d8, 0x1, 0, array[usb_config_descriptor_usbdux, 1]] +} [packed] + +usb_config_descriptor_usbdux { + inner usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_usbdux] +} [packed] + +# probe() expects a successful switch to 3rd interface altsetting. Give that, and more, to syzkaller to try breaking something. +usb_interface_descriptor_usbdux { + alt0 usb_interface_descriptor_fixed_t[0, 0, 2, USB_CLASS_VENDOR_SPEC, 0, 0, void, array[usb_endpoint_descriptor, 0:2]] + alt1 usb_interface_descriptor_fixed_t[0, 1, 2, USB_CLASS_VENDOR_SPEC, 0, 0, void, array[usb_endpoint_descriptor, 0:2]] + alt2 usb_interface_descriptor_fixed_t[0, 2, 2, USB_CLASS_VENDOR_SPEC, 0, 0, void, array[usb_endpoint_descriptor, 0:2]] + alt3 usb_interface_descriptor_fixed_t[0, 3, 2, USB_CLASS_VENDOR_SPEC, 0, 0, void, array[usb_endpoint_descriptor, 0:2]] +} [packed] + +vusb_responses_usbdux { + len len[parent, int32] + generic ptr[in, vusb_response_generic] + + USB_REQ_GET_INTERFACE ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]] + USB_REQ_GET_CONFIGURATION ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]] + +# Required switch to a different intf altsetting, +# see https://elixir.bootlin.com/linux/v6.17-rc5/source/drivers/comedi/drivers/usbdux.c#L1587 + USB_REQ_SET_INTERFACE ptr[in, vusb_response_expected_t[USB_RECIP_INTERFACE, USB_REQ_SET_INTERFACE, 1, int8]] +# 3 firmware related commands during usbdux_firmware_upload(), +# see https://elixir.bootlin.com/linux/v6.17-rc5/source/drivers/comedi/drivers/usbdux.c#L1396 + USBDUX_FIRMWARE_CMD ptr[in, vusb_response_expected_t[USBDUX_VENDOR_DIR_OUT, USBDUX_FIRMWARE_CMD, 3, int8]] +} [packed] + +define USBDUX_FIRMWARE_CMD 0xa0 +define USBDUX_VENDOR_DIR_OUT 0x40 diff --git a/sys/linux/vusb.txt.const b/sys/linux/vusb.txt.const index b707e8dc4272..70b41f16a19d 100644 --- a/sys/linux/vusb.txt.const +++ b/sys/linux/vusb.txt.const @@ -1,5 +1,6 @@ # Code generated by syz-sysgen. DO NOT EDIT. arches = 386, amd64, arm, arm64, mips64le, ppc64le, riscv64, s390x +ATH9K_REQ_TYPE = 64 ATH_USB_RX_STREAM_MODE_TAG = 19968 AX88172_CMD_READ_NODE_ID = 23 AX_CMD_READ_EEPROM = 11 @@ -15,6 +16,8 @@ AX_CMD_SW_PHY_STATUS = 33 CDC_NCM_COMM_ALTSETTING_NCM = 0 CDC_NCM_DATA_ALTSETTING_NCM = 1 CONTAINER_ID_TYPE = 4 +FIRMWARE_DOWNLOAD = 48 +FIRMWARE_DOWNLOAD_COMP = 49 F_AUDIO_NUM_INTERFACES = 2 HID_DT_HID = 33 HID_DT_PHYSICAL = 35 @@ -75,10 +78,16 @@ HUB_STATUS_LOCAL_POWER = 1 HUB_STATUS_OVERCURRENT = 2 LAN78XX_REG_TYPE_IN = 192 LAN78XX_REG_TYPE_OUT = 64 +LEGO_USB_TOWER_REQUEST_GET_VERSION = 253 +LEGO_USB_TOWER_REQ_TYPE = 192 RTL8150_REQT_READ = 192 RTL8150_REQT_WRITE = 64 RTL8150_REQ_GET_REGS = 5 RTL8150_REQ_SET_REGS = 5 +RTL8152_REQT_READ = 192 +RTL8152_REQT_WRITE = 64 +RTL8152_REQ_GET_REGS = 5 +RTL8152_REQ_SET_REGS = 5 SIERRA_CMD_TYPE_IN = 161 SIERRA_CMD_TYPE_OUT = 33 UAC1_EXTENSION_UNIT = 8 @@ -146,6 +155,8 @@ UAC_SELECTOR_UNIT = 5 UAC_TERMINAL_STREAMING = 257 UAC_TERMINAL_UNDEFINED = 256 UAC_TERMINAL_VENDOR_SPEC = 511 +USBDUX_FIRMWARE_CMD = 160 +USBDUX_VENDOR_DIR_OUT = 64 USBLP_FIRST_PROTOCOL = 1 USBLP_LAST_PROTOCOL = 3 USBLP_REQ_GET_ID = 0 @@ -280,6 +291,7 @@ USB_EXT_PORT_STAT_TX_SPEED_ID = 240 USB_FIXED_ENDPOINT_BULK_IN_ADDR = 129 USB_FIXED_ENDPOINT_BULK_OUT_ADDR = 2 USB_FIXED_ENDPOINT_INT_IN_ADDR = 131 +USB_FIXED_ENDPOINT_INT_OUT_ADDR = 3 USB_FULL_SPEED_OPERATION = 2 USB_HIGH_SPEED_OPERATION = 4 USB_HUB_PORTS_BITS = 4 @@ -313,6 +325,7 @@ USB_PORT_STAT_SUSPEND = 4 USB_PORT_STAT_TEST = 2048 USB_PTM_CAP_TYPE = 11 USB_RECIP_DEVICE = 0 +USB_RECIP_INTERFACE = 1 USB_REQ_CLEAR_FEATURE = 1 USB_REQ_GET_BATTERY_STATUS = 21 USB_REQ_GET_CONFIGURATION = 8 diff --git a/tools/create-image.sh b/tools/create-image.sh index 1d99f0d13d96..e9f76b336b8e 100755 --- a/tools/create-image.sh +++ b/tools/create-image.sh @@ -7,7 +7,7 @@ set -eux # Create a minimal Debian distribution in a directory. -PREINSTALL_PKGS=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default,firmware-atheros,debian-ports-archive-keyring +PREINSTALL_PKGS=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default,firmware-atheros,firmware-linux,debian-ports-archive-keyring # If ADD_PACKAGE is not defined as an external environment variable, use our default packages if [ -z ${ADD_PACKAGE+x} ]; then