diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_usb.h | 110 |
1 files changed, 68 insertions, 42 deletions
diff --git a/executor/common_usb.h b/executor/common_usb.h index e6d5e7b80..6da4e4e17 100644 --- a/executor/common_usb.h +++ b/executor/common_usb.h @@ -80,13 +80,14 @@ struct usb_fuzzer_ep_io { #define USB_FUZZER_IOCTL_INIT _IOW('U', 0, struct usb_fuzzer_init) #define USB_FUZZER_IOCTL_RUN _IO('U', 1) -#define USB_FUZZER_IOCTL_EP0_READ _IOWR('U', 2, struct usb_fuzzer_event) +#define USB_FUZZER_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_fuzzer_event) #define USB_FUZZER_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_fuzzer_ep_io) -#define USB_FUZZER_IOCTL_EP_ENABLE _IOW('U', 4, struct usb_endpoint_descriptor) -#define USB_FUZZER_IOCTL_EP_WRITE _IOW('U', 6, struct usb_fuzzer_ep_io) -#define USB_FUZZER_IOCTL_EP_READ _IOWR('U', 7, struct usb_fuzzer_ep_io) -#define USB_FUZZER_IOCTL_CONFIGURE _IO('U', 8) -#define USB_FUZZER_IOCTL_VBUS_DRAW _IOW('U', 9, uint32) +#define USB_FUZZER_IOCTL_EP0_READ _IOWR('U', 4, struct usb_fuzzer_ep_io) +#define USB_FUZZER_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) +#define USB_FUZZER_IOCTL_EP_WRITE _IOW('U', 7, struct usb_fuzzer_ep_io) +#define USB_FUZZER_IOCTL_EP_READ _IOWR('U', 8, struct usb_fuzzer_ep_io) +#define USB_FUZZER_IOCTL_CONFIGURE _IO('U', 9) +#define USB_FUZZER_IOCTL_VBUS_DRAW _IOW('U', 10, uint32) int usb_fuzzer_open() { @@ -107,9 +108,9 @@ int usb_fuzzer_run(int fd) return ioctl(fd, USB_FUZZER_IOCTL_RUN, 0); } -int usb_fuzzer_ep0_read(int fd, struct usb_fuzzer_event* event) +int usb_fuzzer_event_fetch(int fd, struct usb_fuzzer_event* event) { - return ioctl(fd, USB_FUZZER_IOCTL_EP0_READ, event); + return ioctl(fd, USB_FUZZER_IOCTL_EVENT_FETCH, event); } int usb_fuzzer_ep0_write(int fd, struct usb_fuzzer_ep_io* io) @@ -117,6 +118,11 @@ int usb_fuzzer_ep0_write(int fd, struct usb_fuzzer_ep_io* io) return ioctl(fd, USB_FUZZER_IOCTL_EP0_WRITE, io); } +int usb_fuzzer_ep0_read(int fd, struct usb_fuzzer_ep_io* io) +{ + return ioctl(fd, USB_FUZZER_IOCTL_EP0_READ, io); +} + int usb_fuzzer_ep_write(int fd, struct usb_fuzzer_ep_io* io) { return ioctl(fd, USB_FUZZER_IOCTL_EP_WRITE, io); @@ -170,7 +176,7 @@ struct vusb_connect_descriptors { } __attribute__((packed)); static bool lookup_connect_response(struct vusb_connect_descriptors* descs, struct usb_device_index* index, - struct usb_ctrlrequest* ctrl, char** response_data, uint32* response_length, bool* done) + struct usb_ctrlrequest* ctrl, char** response_data, uint32* response_length) { uint8 str_idx; @@ -209,11 +215,6 @@ static bool lookup_connect_response(struct vusb_connect_descriptors* descs, stru return false; } break; - case USB_REQ_SET_CONFIGURATION: - *response_length = 0; - *response_data = NULL; - *done = true; - return true; default: fail("syz_usb_connect: no response"); return false; @@ -229,8 +230,8 @@ static bool lookup_connect_response(struct vusb_connect_descriptors* descs, stru static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatile long a2, volatile long a3) { - int64_t speed = a0; - int64_t dev_len = a1; + uint64 speed = a0; + uint64 dev_len = a1; char* dev = (char*)a2; struct vusb_connect_descriptors* descs = (struct vusb_connect_descriptors*)a3; @@ -281,9 +282,9 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil struct usb_fuzzer_control_event event; event.inner.type = 0; event.inner.length = sizeof(event.ctrl); - rv = usb_fuzzer_ep0_read(fd, (struct usb_fuzzer_event*)&event); + rv = usb_fuzzer_event_fetch(fd, (struct usb_fuzzer_event*)&event); if (rv < 0) { - debug("syz_usb_connect: usb_fuzzer_ep0_read failed with %d\n", rv); + debug("syz_usb_connect: usb_fuzzer_event_fetch failed with %d\n", rv); return rv; } if (event.inner.type != USB_FUZZER_EVENT_CONTROL) @@ -296,10 +297,20 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil bool response_found = false; char* response_data = NULL; uint32 response_length = 0; - NONFAILING(response_found = lookup_connect_response(descs, &index, &event.ctrl, &response_data, &response_length, &done)); - if (!response_found) { - debug("syz_usb_connect: no response found\n"); - return -1; + + if (event.ctrl.bRequestType & USB_DIR_IN) { + NONFAILING(response_found = lookup_connect_response(descs, &index, &event.ctrl, &response_data, &response_length)); + if (!response_found) { + debug("syz_usb_connect: unknown IN request\n"); + return -1; + } + } else { + if ((event.ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD || + event.ctrl.bRequest != USB_REQ_SET_CONFIGURATION) { + fail("syz_usb_connect: unknown OUT request"); + return -1; + } + done = true; } if (done) { @@ -329,15 +340,21 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil 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); - if (event.ctrl.wLength < response.inner.length) - response.inner.length = event.ctrl.wLength; + else + memset(&response.data[0], 0, response_length); + debug("syz_usb_connect: reply length = %d\n", response.inner.length); - rv = usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + if (event.ctrl.bRequestType & USB_DIR_IN) + rv = usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + else + rv = usb_fuzzer_ep0_read(fd, (struct usb_fuzzer_ep_io*)&response); if (rv < 0) { - debug("syz_usb_connect: usb_fuzzer_ep0_write failed with %d\n", rv); + debug("syz_usb_connect: usb_fuzzer_ep0_read/write failed with %d\n", rv); return rv; } } @@ -444,7 +461,7 @@ static volatile long syz_usb_control_io(volatile long a0, volatile long a1, vola struct usb_fuzzer_control_event event; event.inner.type = 0; event.inner.length = USB_MAX_PACKET_SIZE; - int rv = usb_fuzzer_ep0_read(fd, (struct usb_fuzzer_event*)&event); + int rv = usb_fuzzer_event_fetch(fd, (struct usb_fuzzer_event*)&event); if (rv < 0) { debug("syz_usb_control_io: usb_fuzzer_ep0_read failed with %d\n", rv); return rv; @@ -458,18 +475,18 @@ static volatile long syz_usb_control_io(volatile long a0, volatile long a1, vola event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT", event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength); - if (!(event.ctrl.bRequestType & USB_DIR_IN) && event.ctrl.wLength != 0) { - debug("syz_usb_control_io: OUT data:\n"); - debug_dump_data(&event.data[0], event.ctrl.wLength); - } - bool response_found = false; char* response_data = NULL; uint32 response_length = 0; - NONFAILING(response_found = lookup_control_io_response(descs, resps, &event.ctrl, &response_data, &response_length)); - if (!response_found) { - debug("syz_usb_control_io: no response found\n"); - return -1; + + if (event.ctrl.bRequestType & USB_DIR_IN) { + NONFAILING(response_found = lookup_control_io_response(descs, resps, &event.ctrl, &response_data, &response_length)); + if (!response_found) { + debug("syz_usb_control_io: no response found\n"); + return -1; + } + } else { + response_length = event.ctrl.wLength; } struct usb_fuzzer_ep_io_data response; @@ -477,16 +494,25 @@ static volatile long syz_usb_control_io(volatile long a0, volatile long a1, vola 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); - if (event.ctrl.wLength < response.inner.length) - response.inner.length = event.ctrl.wLength; - debug("syz_usb_control_io: response length = %d\n", response.inner.length); - debug_dump_data(&response.data[0], response.inner.length); - rv = usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + else + memset(&response.data[0], 0, response_length); + + if (event.ctrl.bRequestType & USB_DIR_IN) { + debug("syz_usb_control_io: IN, length = %d\n", response.inner.length); + debug_dump_data(&response.data[0], response.inner.length); + rv = usb_fuzzer_ep0_write(fd, (struct usb_fuzzer_ep_io*)&response); + } else { + rv = usb_fuzzer_ep0_read(fd, (struct usb_fuzzer_ep_io*)&response); + debug("syz_usb_control_io: OUT, length = %d\n", response.inner.length); + debug_dump_data(&event.data[0], response.inner.length); + } if (rv < 0) { - debug("syz_usb_control_io: usb_fuzzer_ep0_write failed with %d\n", rv); + debug("syz_usb_control_io: usb_fuzzer_ep0_read/write failed with %d\n", rv); return rv; } |
