github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/common_usb_linux.h (about)

     1  // Copyright 2020 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  // This file is shared between executor and csource package.
     5  
     6  // Linux-specific implementation of syz_usb_* pseudo-syscalls.
     7  
     8  #include "common_usb.h"
     9  
    10  #define UDC_NAME_LENGTH_MAX 128
    11  
    12  struct usb_raw_init {
    13  	__u8 driver_name[UDC_NAME_LENGTH_MAX];
    14  	__u8 device_name[UDC_NAME_LENGTH_MAX];
    15  	__u8 speed;
    16  };
    17  
    18  enum usb_raw_event_type {
    19  	USB_RAW_EVENT_INVALID = 0,
    20  	USB_RAW_EVENT_CONNECT = 1,
    21  	USB_RAW_EVENT_CONTROL = 2,
    22  };
    23  
    24  struct usb_raw_event {
    25  	__u32 type;
    26  	__u32 length;
    27  	__u8 data[0];
    28  };
    29  
    30  struct usb_raw_ep_io {
    31  	__u16 ep;
    32  	__u16 flags;
    33  	__u32 length;
    34  	__u8 data[0];
    35  };
    36  
    37  #define USB_RAW_EPS_NUM_MAX 30
    38  #define USB_RAW_EP_NAME_MAX 16
    39  #define USB_RAW_EP_ADDR_ANY 0xff
    40  
    41  struct usb_raw_ep_caps {
    42  	__u32 type_control : 1;
    43  	__u32 type_iso : 1;
    44  	__u32 type_bulk : 1;
    45  	__u32 type_int : 1;
    46  	__u32 dir_in : 1;
    47  	__u32 dir_out : 1;
    48  };
    49  
    50  struct usb_raw_ep_limits {
    51  	__u16 maxpacket_limit;
    52  	__u16 max_streams;
    53  	__u32 reserved;
    54  };
    55  
    56  struct usb_raw_ep_info {
    57  	__u8 name[USB_RAW_EP_NAME_MAX];
    58  	__u32 addr;
    59  	struct usb_raw_ep_caps caps;
    60  	struct usb_raw_ep_limits limits;
    61  };
    62  
    63  struct usb_raw_eps_info {
    64  	struct usb_raw_ep_info eps[USB_RAW_EPS_NUM_MAX];
    65  };
    66  
    67  #define USB_RAW_IOCTL_INIT _IOW('U', 0, struct usb_raw_init)
    68  #define USB_RAW_IOCTL_RUN _IO('U', 1)
    69  #define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event)
    70  #define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io)
    71  #define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io)
    72  #define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor)
    73  #define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32)
    74  #define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io)
    75  #define USB_RAW_IOCTL_EP_READ _IOWR('U', 8, struct usb_raw_ep_io)
    76  #define USB_RAW_IOCTL_CONFIGURE _IO('U', 9)
    77  #define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32)
    78  #define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info)
    79  #define USB_RAW_IOCTL_EP0_STALL _IO('U', 12)
    80  #define USB_RAW_IOCTL_EP_SET_HALT _IOW('U', 13, __u32)
    81  #define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32)
    82  #define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32)
    83  
    84  #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
    85  static int usb_raw_open()
    86  {
    87  	return open("/dev/raw-gadget", O_RDWR);
    88  }
    89  
    90  static int usb_raw_init(int fd, uint32 speed, const char* driver, const char* device)
    91  {
    92  	struct usb_raw_init arg;
    93  	strncpy((char*)&arg.driver_name[0], driver, sizeof(arg.driver_name));
    94  	strncpy((char*)&arg.device_name[0], device, sizeof(arg.device_name));
    95  	arg.speed = speed;
    96  	return ioctl(fd, USB_RAW_IOCTL_INIT, &arg);
    97  }
    98  
    99  static int usb_raw_run(int fd)
   100  {
   101  	return ioctl(fd, USB_RAW_IOCTL_RUN, 0);
   102  }
   103  #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
   104  
   105  #if SYZ_EXECUTOR || __NR_syz_usb_ep_write
   106  static int usb_raw_ep_write(int fd, struct usb_raw_ep_io* io)
   107  {
   108  	return ioctl(fd, USB_RAW_IOCTL_EP_WRITE, io);
   109  }
   110  #endif // SYZ_EXECUTOR || __NR_syz_usb_ep_write
   111  
   112  #if SYZ_EXECUTOR || __NR_syz_usb_ep_read
   113  static int usb_raw_ep_read(int fd, struct usb_raw_ep_io* io)
   114  {
   115  	return ioctl(fd, USB_RAW_IOCTL_EP_READ, io);
   116  }
   117  #endif // SYZ_EXECUTOR || __NR_syz_usb_ep_read
   118  
   119  #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
   120  
   121  static int usb_raw_configure(int fd)
   122  {
   123  	return ioctl(fd, USB_RAW_IOCTL_CONFIGURE, 0);
   124  }
   125  
   126  static int usb_raw_vbus_draw(int fd, uint32 power)
   127  {
   128  	return ioctl(fd, USB_RAW_IOCTL_VBUS_DRAW, power);
   129  }
   130  
   131  #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
   132  
   133  #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io
   134  static int usb_raw_ep0_write(int fd, struct usb_raw_ep_io* io)
   135  {
   136  	return ioctl(fd, USB_RAW_IOCTL_EP0_WRITE, io);
   137  }
   138  
   139  static int usb_raw_ep0_read(int fd, struct usb_raw_ep_io* io)
   140  {
   141  	return ioctl(fd, USB_RAW_IOCTL_EP0_READ, io);
   142  }
   143  
   144  static int usb_raw_event_fetch(int fd, struct usb_raw_event* event)
   145  {
   146  	return ioctl(fd, USB_RAW_IOCTL_EVENT_FETCH, event);
   147  }
   148  
   149  static int usb_raw_ep_enable(int fd, struct usb_endpoint_descriptor* desc)
   150  {
   151  	return ioctl(fd, USB_RAW_IOCTL_EP_ENABLE, desc);
   152  }
   153  
   154  static int usb_raw_ep_disable(int fd, int ep)
   155  {
   156  	return ioctl(fd, USB_RAW_IOCTL_EP_DISABLE, ep);
   157  }
   158  
   159  static int usb_raw_ep0_stall(int fd)
   160  {
   161  	return ioctl(fd, USB_RAW_IOCTL_EP0_STALL, 0);
   162  }
   163  #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io
   164  
   165  #if SYZ_EXECUTOR || __NR_syz_usb_control_io
   166  static int lookup_interface(int fd, uint8 bInterfaceNumber, uint8 bAlternateSetting)
   167  {
   168  	struct usb_device_index* index = lookup_usb_index(fd);
   169  	if (!index)
   170  		return -1;
   171  
   172  	for (int i = 0; i < index->ifaces_num; i++) {
   173  		if (index->ifaces[i].bInterfaceNumber == bInterfaceNumber &&
   174  		    index->ifaces[i].bAlternateSetting == bAlternateSetting)
   175  			return i;
   176  	}
   177  	return -1;
   178  }
   179  #endif // SYZ_EXECUTOR || __NR_syz_usb_control_io
   180  
   181  #if SYZ_EXECUTOR || __NR_syz_usb_ep_write || __NR_syz_usb_ep_read
   182  static int lookup_endpoint(int fd, uint8 bEndpointAddress)
   183  {
   184  	struct usb_device_index* index = lookup_usb_index(fd);
   185  	if (!index)
   186  		return -1;
   187  	if (index->iface_cur < 0)
   188  		return -1;
   189  
   190  	for (int ep = 0; ep < index->ifaces[index->iface_cur].eps_num; ep++)
   191  		if (index->ifaces[index->iface_cur].eps[ep].desc.bEndpointAddress == bEndpointAddress)
   192  			return index->ifaces[index->iface_cur].eps[ep].handle;
   193  	return -1;
   194  }
   195  #endif // SYZ_EXECUTOR || __NR_syz_usb_ep_write || __NR_syz_usb_ep_read
   196  
   197  #define USB_MAX_PACKET_SIZE 4096
   198  
   199  struct usb_raw_control_event {
   200  	struct usb_raw_event inner;
   201  	struct usb_ctrlrequest ctrl;
   202  	char data[USB_MAX_PACKET_SIZE];
   203  };
   204  
   205  struct usb_raw_ep_io_data {
   206  	struct usb_raw_ep_io inner;
   207  	char data[USB_MAX_PACKET_SIZE];
   208  };
   209  
   210  #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io
   211  static void set_interface(int fd, int n)
   212  {
   213  	struct usb_device_index* index = lookup_usb_index(fd);
   214  	if (!index)
   215  		return;
   216  
   217  	if (index->iface_cur >= 0 && index->iface_cur < index->ifaces_num) {
   218  		for (int ep = 0; ep < index->ifaces[index->iface_cur].eps_num; ep++) {
   219  			int rv = usb_raw_ep_disable(fd, index->ifaces[index->iface_cur].eps[ep].handle);
   220  			if (rv < 0) {
   221  				debug("set_interface: failed to disable endpoint 0x%02x\n",
   222  				      index->ifaces[index->iface_cur].eps[ep].desc.bEndpointAddress);
   223  			} else {
   224  				debug("set_interface: endpoint 0x%02x disabled\n",
   225  				      index->ifaces[index->iface_cur].eps[ep].desc.bEndpointAddress);
   226  			}
   227  		}
   228  	}
   229  	if (n >= 0 && n < index->ifaces_num) {
   230  		for (int ep = 0; ep < index->ifaces[n].eps_num; ep++) {
   231  			int rv = usb_raw_ep_enable(fd, &index->ifaces[n].eps[ep].desc);
   232  			if (rv < 0) {
   233  				debug("set_interface: failed to enable endpoint 0x%02x\n",
   234  				      index->ifaces[n].eps[ep].desc.bEndpointAddress);
   235  			} else {
   236  				debug("set_interface: endpoint 0x%02x enabled as %d\n",
   237  				      index->ifaces[n].eps[ep].desc.bEndpointAddress, rv);
   238  				index->ifaces[n].eps[ep].handle = rv;
   239  			}
   240  		}
   241  		index->iface_cur = n;
   242  	}
   243  }
   244  #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usb_control_io
   245  
   246  #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
   247  static int configure_device(int fd)
   248  {
   249  	struct usb_device_index* index = lookup_usb_index(fd);
   250  
   251  	if (!index)
   252  		return -1;
   253  
   254  	int rv = usb_raw_vbus_draw(fd, index->bMaxPower);
   255  	if (rv < 0) {
   256  		debug("configure_device: usb_raw_vbus_draw failed with %d\n", rv);
   257  		return rv;
   258  	}
   259  	rv = usb_raw_configure(fd);
   260  	if (rv < 0) {
   261  		debug("configure_device: usb_raw_configure failed with %d\n", rv);
   262  		return rv;
   263  	}
   264  	set_interface(fd, 0);
   265  	return 0;
   266  }
   267  
   268  static volatile long syz_usb_connect_impl(uint64 speed, uint64 dev_len, const char* dev,
   269  					  const struct vusb_connect_descriptors* descs,
   270  					  lookup_connect_out_response_t lookup_connect_response_out)
   271  {
   272  	debug("syz_usb_connect: dev: %p\n", dev);
   273  	if (!dev) {
   274  		debug("syz_usb_connect: dev is null\n");
   275  		return -1;
   276  	}
   277  
   278  	debug("syz_usb_connect: device data:\n");
   279  	debug_dump_data(dev, dev_len);
   280  
   281  	int fd = usb_raw_open();
   282  	if (fd < 0) {
   283  		debug("syz_usb_connect: usb_raw_open failed with %d\n", fd);
   284  		return fd;
   285  	}
   286  	if (fd >= MAX_FDS) {
   287  		close(fd);
   288  		debug("syz_usb_connect: too many open fds\n");
   289  		return -1;
   290  	}
   291  	debug("syz_usb_connect: usb_raw_open success\n");
   292  
   293  	struct usb_device_index* index = add_usb_index(fd, dev, dev_len);
   294  	if (!index) {
   295  		debug("syz_usb_connect: add_usb_index failed\n");
   296  		return -1;
   297  	}
   298  	debug("syz_usb_connect: add_usb_index success\n");
   299  
   300  #if USB_DEBUG
   301  	analyze_usb_device(index);
   302  #endif
   303  
   304  	// TODO: consider creating two dummy_udc's per proc to increace the chance of
   305  	// triggering interaction between multiple USB devices within the same program.
   306  	char device[32];
   307  	sprintf(&device[0], "dummy_udc.%llu", procid);
   308  	int rv = usb_raw_init(fd, speed, "dummy_udc", &device[0]);
   309  	if (rv < 0) {
   310  		debug("syz_usb_connect: usb_raw_init failed with %d\n", rv);
   311  		return rv;
   312  	}
   313  	debug("syz_usb_connect: usb_raw_init success\n");
   314  
   315  	rv = usb_raw_run(fd);
   316  	if (rv < 0) {
   317  		debug("syz_usb_connect: usb_raw_run failed with %d\n", rv);
   318  		return rv;
   319  	}
   320  	debug("syz_usb_connect: usb_raw_run success\n");
   321  
   322  	bool done = false;
   323  	while (!done) {
   324  		struct usb_raw_control_event event;
   325  		event.inner.type = 0;
   326  		event.inner.length = sizeof(event.ctrl);
   327  		rv = usb_raw_event_fetch(fd, (struct usb_raw_event*)&event);
   328  		if (rv < 0) {
   329  			debug("syz_usb_connect: usb_raw_event_fetch failed with %d\n", rv);
   330  			return rv;
   331  		}
   332  		if (event.inner.type != USB_RAW_EVENT_CONTROL)
   333  			continue;
   334  
   335  		debug("syz_usb_connect: bReqType: 0x%x (%s), bReq: 0x%x, wVal: 0x%x, wIdx: 0x%x, wLen: %d\n",
   336  		      event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT",
   337  		      event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength);
   338  
   339  #if USB_DEBUG
   340  		analyze_control_request(fd, &event.ctrl);
   341  #endif
   342  
   343  		char* response_data = NULL;
   344  		uint32 response_length = 0;
   345  		struct usb_qualifier_descriptor qual;
   346  
   347  		if (event.ctrl.bRequestType & USB_DIR_IN) {
   348  			if (!lookup_connect_response_in(fd, descs, &event.ctrl, &qual, &response_data, &response_length)) {
   349  				debug("syz_usb_connect: unknown request, stalling\n");
   350  				usb_raw_ep0_stall(fd);
   351  				continue;
   352  			}
   353  		} else {
   354  			if (!lookup_connect_response_out(fd, descs, &event.ctrl, &done)) {
   355  				debug("syz_usb_connect: unknown request, stalling\n");
   356  				usb_raw_ep0_stall(fd);
   357  				continue;
   358  			}
   359  			response_data = NULL;
   360  			response_length = event.ctrl.wLength;
   361  		}
   362  
   363  		if ((event.ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
   364  		    event.ctrl.bRequest == USB_REQ_SET_CONFIGURATION) {
   365  			rv = configure_device(fd);
   366  			if (rv < 0) {
   367  				debug("syz_usb_connect: configure_device failed with %d\n", rv);
   368  				return rv;
   369  			}
   370  		}
   371  
   372  		struct usb_raw_ep_io_data response;
   373  		response.inner.ep = 0;
   374  		response.inner.flags = 0;
   375  		if (response_length > sizeof(response.data))
   376  			response_length = 0;
   377  		if (event.ctrl.wLength < response_length)
   378  			response_length = event.ctrl.wLength;
   379  		response.inner.length = response_length;
   380  		if (response_data)
   381  			memcpy(&response.data[0], response_data, response_length);
   382  		else
   383  			memset(&response.data[0], 0, response_length);
   384  
   385  		if (event.ctrl.bRequestType & USB_DIR_IN) {
   386  			debug("syz_usb_connect: writing %d bytes\n", response.inner.length);
   387  			rv = usb_raw_ep0_write(fd, (struct usb_raw_ep_io*)&response);
   388  		} else {
   389  			rv = usb_raw_ep0_read(fd, (struct usb_raw_ep_io*)&response);
   390  			debug("syz_usb_connect: read %d bytes\n", response.inner.length);
   391  			debug_dump_data(&event.data[0], response.inner.length);
   392  		}
   393  		if (rv < 0) {
   394  			debug("syz_usb_connect: usb_raw_ep0_read/write failed with %d\n", rv);
   395  			return rv;
   396  		}
   397  	}
   398  
   399  	sleep_ms(200);
   400  
   401  	debug("syz_usb_connect: configured\n");
   402  
   403  	return fd;
   404  }
   405  
   406  #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
   407  
   408  #if SYZ_EXECUTOR || __NR_syz_usb_connect
   409  static volatile long syz_usb_connect(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
   410  {
   411  	uint64 speed = a0;
   412  	uint64 dev_len = a1;
   413  	const char* dev = (const char*)a2;
   414  	const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a3;
   415  
   416  	return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_generic);
   417  }
   418  #endif // SYZ_EXECUTOR || __NR_syz_usb_connect
   419  
   420  #if SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k
   421  static volatile long syz_usb_connect_ath9k(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
   422  {
   423  	uint64 speed = a0;
   424  	uint64 dev_len = a1;
   425  	const char* dev = (const char*)a2;
   426  	const struct vusb_connect_descriptors* descs = (const struct vusb_connect_descriptors*)a3;
   427  
   428  	return syz_usb_connect_impl(speed, dev_len, dev, descs, &lookup_connect_response_out_ath9k);
   429  }
   430  #endif // SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k
   431  
   432  #if SYZ_EXECUTOR || __NR_syz_usb_control_io
   433  static volatile long syz_usb_control_io(volatile long a0, volatile long a1, volatile long a2)
   434  {
   435  	int fd = a0;
   436  	const struct vusb_descriptors* descs = (const struct vusb_descriptors*)a1;
   437  	const struct vusb_responses* resps = (const struct vusb_responses*)a2;
   438  
   439  	struct usb_raw_control_event event;
   440  	event.inner.type = 0;
   441  	event.inner.length = USB_MAX_PACKET_SIZE;
   442  	int rv = usb_raw_event_fetch(fd, (struct usb_raw_event*)&event);
   443  	if (rv < 0) {
   444  		debug("syz_usb_control_io: usb_raw_ep0_read failed with %d\n", rv);
   445  		return rv;
   446  	}
   447  	if (event.inner.type != USB_RAW_EVENT_CONTROL) {
   448  		debug("syz_usb_control_io: wrong event type: %d\n", (int)event.inner.type);
   449  		return -1;
   450  	}
   451  
   452  	debug("syz_usb_control_io: bReqType: 0x%x (%s), bReq: 0x%x, wVal: 0x%x, wIdx: 0x%x, wLen: %d\n",
   453  	      event.ctrl.bRequestType, (event.ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT",
   454  	      event.ctrl.bRequest, event.ctrl.wValue, event.ctrl.wIndex, event.ctrl.wLength);
   455  
   456  #if USB_DEBUG
   457  	analyze_control_request(fd, &event.ctrl);
   458  #endif
   459  
   460  	char* response_data = NULL;
   461  	uint32 response_length = 0;
   462  
   463  	if ((event.ctrl.bRequestType & USB_DIR_IN) && event.ctrl.wLength) {
   464  		if (!lookup_control_response(descs, resps, &event.ctrl, &response_data, &response_length)) {
   465  			debug("syz_usb_connect: unknown request, stalling\n");
   466  			usb_raw_ep0_stall(fd);
   467  			return -1;
   468  		}
   469  	} else {
   470  		if ((event.ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD ||
   471  		    event.ctrl.bRequest == USB_REQ_SET_INTERFACE) {
   472  			int iface_num = event.ctrl.wIndex;
   473  			int alt_set = event.ctrl.wValue;
   474  			debug("syz_usb_control_io: setting interface (%d, %d)\n", iface_num, alt_set);
   475  			int iface_index = lookup_interface(fd, iface_num, alt_set);
   476  			if (iface_index < 0) {
   477  				debug("syz_usb_control_io: interface (%d, %d) not found\n", iface_num, alt_set);
   478  			} else {
   479  				set_interface(fd, iface_index);
   480  				debug("syz_usb_control_io: interface (%d, %d) set\n", iface_num, alt_set);
   481  			}
   482  		}
   483  
   484  		response_length = event.ctrl.wLength;
   485  	}
   486  
   487  	struct usb_raw_ep_io_data response;
   488  	response.inner.ep = 0;
   489  	response.inner.flags = 0;
   490  	if (response_length > sizeof(response.data))
   491  		response_length = 0;
   492  	if (event.ctrl.wLength < response_length)
   493  		response_length = event.ctrl.wLength;
   494  	if ((event.ctrl.bRequestType & USB_DIR_IN) && !event.ctrl.wLength) {
   495  		// Something fishy is going on, try to read more data.
   496  		response_length = USB_MAX_PACKET_SIZE;
   497  	}
   498  	response.inner.length = response_length;
   499  	if (response_data)
   500  		memcpy(&response.data[0], response_data, response_length);
   501  	else
   502  		memset(&response.data[0], 0, response_length);
   503  
   504  	if ((event.ctrl.bRequestType & USB_DIR_IN) && event.ctrl.wLength) {
   505  		debug("syz_usb_control_io: writing %d bytes\n", response.inner.length);
   506  		debug_dump_data(&response.data[0], response.inner.length);
   507  		rv = usb_raw_ep0_write(fd, (struct usb_raw_ep_io*)&response);
   508  	} else {
   509  		rv = usb_raw_ep0_read(fd, (struct usb_raw_ep_io*)&response);
   510  		debug("syz_usb_control_io: read %d bytes\n", response.inner.length);
   511  		debug_dump_data(&response.data[0], response.inner.length);
   512  	}
   513  	if (rv < 0) {
   514  		debug("syz_usb_control_io: usb_raw_ep0_read/write failed with %d\n", rv);
   515  		return rv;
   516  	}
   517  
   518  	sleep_ms(200);
   519  
   520  	return 0;
   521  }
   522  #endif // SYZ_EXECUTOR || __NR_syz_usb_control_io
   523  
   524  #if SYZ_EXECUTOR || __NR_syz_usb_ep_write
   525  static volatile long syz_usb_ep_write(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
   526  {
   527  	int fd = a0;
   528  	uint8 ep = a1;
   529  	uint32 len = a2;
   530  	char* data = (char*)a3;
   531  
   532  	int ep_handle = lookup_endpoint(fd, ep);
   533  	if (ep_handle < 0) {
   534  		debug("syz_usb_ep_write: endpoint not found\n");
   535  		return -1;
   536  	}
   537  	debug("syz_usb_ep_write: endpoint handle: %d\n", ep_handle);
   538  
   539  	struct usb_raw_ep_io_data io_data;
   540  	io_data.inner.ep = ep_handle;
   541  	io_data.inner.flags = 0;
   542  	if (len > sizeof(io_data.data))
   543  		len = sizeof(io_data.data);
   544  	io_data.inner.length = len;
   545  	memcpy(&io_data.data[0], data, len);
   546  
   547  	int rv = usb_raw_ep_write(fd, (struct usb_raw_ep_io*)&io_data);
   548  	if (rv < 0) {
   549  		debug("syz_usb_ep_write: usb_raw_ep_write failed with %d\n", rv);
   550  		return rv;
   551  	}
   552  
   553  	sleep_ms(200);
   554  
   555  	return 0;
   556  }
   557  #endif // SYZ_EXECUTOR || __NR_syz_usb_ep_write
   558  
   559  #if SYZ_EXECUTOR || __NR_syz_usb_ep_read
   560  static volatile long syz_usb_ep_read(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
   561  {
   562  	int fd = a0;
   563  	uint8 ep = a1;
   564  	uint32 len = a2;
   565  	char* data = (char*)a3;
   566  
   567  	int ep_handle = lookup_endpoint(fd, ep);
   568  	if (ep_handle < 0) {
   569  		debug("syz_usb_ep_read: endpoint not found\n");
   570  		return -1;
   571  	}
   572  	debug("syz_usb_ep_read: endpoint handle: %d\n", ep_handle);
   573  
   574  	struct usb_raw_ep_io_data io_data;
   575  	io_data.inner.ep = ep_handle;
   576  	io_data.inner.flags = 0;
   577  	if (len > sizeof(io_data.data))
   578  		len = sizeof(io_data.data);
   579  	io_data.inner.length = len;
   580  
   581  	int rv = usb_raw_ep_read(fd, (struct usb_raw_ep_io*)&io_data);
   582  	if (rv < 0) {
   583  		debug("syz_usb_ep_read: usb_raw_ep_read failed with %d\n", rv);
   584  		return rv;
   585  	}
   586  
   587  	memcpy(&data[0], &io_data.data[0], io_data.inner.length);
   588  
   589  	debug("syz_usb_ep_read: received data:\n");
   590  	debug_dump_data(&io_data.data[0], io_data.inner.length);
   591  
   592  	sleep_ms(200);
   593  
   594  	return 0;
   595  }
   596  #endif // SYZ_EXECUTOR || __NR_syz_usb_ep_read
   597  
   598  #if SYZ_EXECUTOR || __NR_syz_usb_disconnect
   599  static volatile long syz_usb_disconnect(volatile long a0)
   600  {
   601  	int fd = a0;
   602  
   603  	int rv = close(fd);
   604  
   605  	sleep_ms(200);
   606  
   607  	return rv;
   608  }
   609  #endif // SYZ_EXECUTOR || __NR_syz_usb_disconnect