aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_usb.h
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2020-03-13 00:32:32 +0100
committerDmitry Vyukov <dvyukov@google.com>2020-03-13 07:44:43 +0100
commitd89275f2aaa8ae95a2bcb8e8f8b022708d2d6951 (patch)
tree9dd63965cdab5e5e3e3d041fa39aba4072d57a50 /executor/common_usb.h
parentd850e9d08467726cd94b6a9caaf8090c594721ba (diff)
executor, sys/linux: add ath9k usb descriptions
Among other things this changes timeout for USB programs from 2 to 3 seconds. ath9k fuzzing also requires ath9k firmware to be present, so system images need to be regenerated with the updated script.
Diffstat (limited to 'executor/common_usb.h')
-rw-r--r--executor/common_usb.h132
1 files changed, 106 insertions, 26 deletions
diff --git a/executor/common_usb.h b/executor/common_usb.h
index 34e3e3166..29196c2d0 100644
--- a/executor/common_usb.h
+++ b/executor/common_usb.h
@@ -28,7 +28,7 @@ struct usb_device_index {
int iface_cur;
};
-static bool parse_usb_descriptor(char* buffer, size_t length, struct usb_device_index* index)
+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;
@@ -193,7 +193,7 @@ struct usb_info {
static struct usb_info usb_devices[MAX_USB_FDS];
static int usb_devices_num;
-static struct usb_device_index* add_usb_index(int fd, char* dev, size_t dev_len)
+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 >= MAX_USB_FDS)
@@ -708,7 +708,7 @@ static void analyze_control_request(int fd, struct usb_ctrlrequest* ctrl)
#endif // USB_DEBUG
-#define USB_MAX_PACKET_SIZE 1024
+#define USB_MAX_PACKET_SIZE 4096
struct usb_raw_control_event {
struct usb_raw_event inner;
@@ -745,8 +745,8 @@ static const char default_lang_id[] = {
0x09, 0x04 // English (United States)
};
-static bool lookup_connect_response(int fd, struct vusb_connect_descriptors* descs, struct usb_ctrlrequest* ctrl,
- char** response_data, uint32* response_length)
+static bool lookup_connect_response_in(int fd, const struct vusb_connect_descriptors* descs, const struct usb_ctrlrequest* ctrl,
+ char** response_data, uint32* response_length)
{
struct usb_device_index* index = lookup_usb_index(fd);
uint8 str_idx;
@@ -807,30 +807,85 @@ static bool lookup_connect_response(int fd, struct vusb_connect_descriptors* des
*response_length = descs->qual_len;
return true;
default:
- fail("lookup_connect_response: no response");
- return false;
+ break;
}
break;
default:
- fail("lookup_connect_response: no response");
- return false;
+ break;
}
break;
default:
- fail("lookup_connect_response: no response");
- return false;
+ break;
}
+ fail("lookup_connect_response_in: unknown request");
return false;
}
-static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
+#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)
{
- uint64 speed = a0;
- uint64 dev_len = a1;
- char* dev = (char*)a2;
- struct vusb_connect_descriptors* descs = (struct vusb_connect_descriptors*)a3;
+ 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;
+ }
+
+ fail("lookup_connect_response_out: unknown request");
+ return false;
+}
+#endif
+
+#if 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
+
+static bool lookup_connect_response_out_ath9k(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:
+ 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:
+ break;
+ }
+ break;
+ }
+
+ fail("lookup_connect_response_out_ath9k: unknown request");
+ return false;
+}
+#endif
+
+typedef bool (*lookup_connect_response_t)(int fd, const struct vusb_connect_descriptors* descs,
+ const struct usb_ctrlrequest* ctrl, bool* done);
+
+static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const char* dev,
+ const struct vusb_connect_descriptors* descs, lookup_connect_response_t lookup_connect_response_out)
+{
debug("syz_usb_connect: dev: %p\n", dev);
if (!dev) {
debug("syz_usb_connect: dev is null\n");
@@ -902,26 +957,27 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil
analyze_control_request(fd, &event.ctrl);
#endif
- bool response_found = false;
char* response_data = NULL;
uint32 response_length = 0;
if (event.ctrl.bRequestType & USB_DIR_IN) {
- NONFAILING(response_found = lookup_connect_response(fd, descs, &event.ctrl, &response_data, &response_length));
+ bool response_found = false;
+ NONFAILING(response_found = lookup_connect_response_in(fd, descs, &event.ctrl, &response_data, &response_length));
if (!response_found) {
debug("syz_usb_connect: unknown control 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 control OUT request");
+ if (!lookup_connect_response_out(fd, descs, &event.ctrl, &done)) {
+ debug("syz_usb_connect: unknown control OUT request\n");
return -1;
}
- done = true;
+ response_data = NULL;
+ response_length = event.ctrl.wLength;
}
- if (done) {
+ if ((event.ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
+ event.ctrl.bRequest == USB_REQ_SET_CONFIGURATION) {
rv = configure_device(fd);
if (rv < 0) {
debug("syz_usb_connect: configure_device failed with %d\n", rv);
@@ -963,6 +1019,30 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatil
return fd;
}
+#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)
+{
+ 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;
+
+ return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_generic);
+}
+#endif
+
+#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)
+{
+ 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;
+
+ return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_ath9k);
+}
+#endif
+
#if SYZ_EXECUTOR || __NR_syz_usb_control_io
struct vusb_descriptor {
uint8 req_type;
@@ -990,7 +1070,7 @@ struct vusb_responses {
struct vusb_response* resps[0];
} __attribute__((packed));
-static bool lookup_control_response(struct vusb_descriptors* descs, struct vusb_responses* resps,
+static bool lookup_control_response(const struct vusb_descriptors* descs, const struct vusb_responses* resps,
struct usb_ctrlrequest* ctrl, char** response_data, uint32* response_length)
{
int descs_num = 0;
@@ -1057,8 +1137,8 @@ static bool lookup_control_response(struct vusb_descriptors* descs, struct vusb_
static volatile long syz_usb_control_io(volatile long a0, volatile long a1, volatile long a2)
{
int fd = a0;
- struct vusb_descriptors* descs = (struct vusb_descriptors*)a1;
- struct vusb_responses* resps = (struct vusb_responses*)a2;
+ 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;