Skip to content
Permalink
Browse files

executor: update USB fuzzing code to use new kernel API

The kernel API has changed and now differentiates between IN and OUT
control requests.
  • Loading branch information...
xairy committed Jul 11, 2019
1 parent ff7bf04 commit 186a30b993773059e01e8b0bc4d12a9d360d0577
Showing with 136 additions and 84 deletions.
  1. +68 −42 executor/common_usb.h
  2. +68 −42 pkg/csource/generated.go
@@ -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,16 +108,21 @@ 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)
{
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,35 +475,44 @@ 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;
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);
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;
}

0 comments on commit 186a30b

Please sign in to comment.
You can’t perform that action at this time.