github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/common_usb.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 // Generic parts of implementation of syz_usb_* pseudo-syscalls. 7 8 #define USB_MAX_IFACE_NUM 4 9 #define USB_MAX_EP_NUM 32 10 #define USB_MAX_FDS 6 11 12 struct usb_endpoint_index { 13 // Copy of the endpoint descriptor: 14 struct usb_endpoint_descriptor desc; 15 // Raw Gadget endpoint handle used for this endpoint (Linux only): 16 int handle; 17 }; 18 19 struct usb_iface_index { 20 // Pointer to where the original interface descriptor is stored: 21 struct usb_interface_descriptor* iface; 22 // Cached copied of some of the interface attributes: 23 uint8 bInterfaceNumber; 24 uint8 bAlternateSetting; 25 uint8 bInterfaceClass; 26 // Endpoint indexes: 27 struct usb_endpoint_index eps[USB_MAX_EP_NUM]; 28 int eps_num; 29 }; 30 31 struct usb_device_index { 32 // Pointer to where the original descriptors are stored: 33 struct usb_device_descriptor* dev; 34 struct usb_config_descriptor* config; 35 // Cached copied of some of the device attributes: 36 uint8 bDeviceClass; 37 uint8 bMaxPower; 38 // Config and interface attributes/indexes: 39 int config_length; 40 struct usb_iface_index ifaces[USB_MAX_IFACE_NUM]; 41 int ifaces_num; 42 int iface_cur; 43 }; 44 45 struct usb_info { 46 int fd; 47 struct usb_device_index index; 48 }; 49 50 #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \ 51 __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write 52 static struct usb_info usb_devices[USB_MAX_FDS]; 53 54 static struct usb_device_index* lookup_usb_index(int fd) 55 { 56 for (int i = 0; i < USB_MAX_FDS; i++) { 57 if (__atomic_load_n(&usb_devices[i].fd, __ATOMIC_ACQUIRE) == fd) 58 return &usb_devices[i].index; 59 } 60 return NULL; 61 } 62 #endif 63 64 #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k 65 static int usb_devices_num; 66 67 static bool parse_usb_descriptor(const char* buffer, size_t length, struct usb_device_index* index) 68 { 69 if (length < sizeof(*index->dev) + sizeof(*index->config)) 70 return false; 71 72 memset(index, 0, sizeof(*index)); 73 74 index->dev = (struct usb_device_descriptor*)buffer; 75 index->config = (struct usb_config_descriptor*)(buffer + sizeof(*index->dev)); 76 index->bDeviceClass = index->dev->bDeviceClass; 77 index->bMaxPower = index->config->bMaxPower; 78 index->config_length = length - sizeof(*index->dev); 79 index->iface_cur = -1; 80 size_t offset = 0; 81 82 while (true) { 83 if (offset + 1 >= length) 84 break; 85 uint8 desc_length = buffer[offset]; 86 uint8 desc_type = buffer[offset + 1]; 87 if (desc_length <= 2) 88 break; 89 if (offset + desc_length > length) 90 break; 91 if (desc_type == USB_DT_INTERFACE && index->ifaces_num < USB_MAX_IFACE_NUM) { 92 struct usb_interface_descriptor* iface = (struct usb_interface_descriptor*)(buffer + offset); 93 debug("parse_usb_descriptor: found interface #%u (%d, %d) at %p\n", 94 index->ifaces_num, iface->bInterfaceNumber, iface->bAlternateSetting, iface); 95 index->ifaces[index->ifaces_num].iface = iface; 96 index->ifaces[index->ifaces_num].bInterfaceNumber = iface->bInterfaceNumber; 97 index->ifaces[index->ifaces_num].bAlternateSetting = iface->bAlternateSetting; 98 index->ifaces[index->ifaces_num].bInterfaceClass = iface->bInterfaceClass; 99 index->ifaces_num++; 100 } 101 if (desc_type == USB_DT_ENDPOINT && index->ifaces_num > 0) { 102 struct usb_iface_index* iface = &index->ifaces[index->ifaces_num - 1]; 103 debug("parse_usb_descriptor: found endpoint #%u at %p\n", iface->eps_num, buffer + offset); 104 if (iface->eps_num < USB_MAX_EP_NUM) { 105 memcpy(&iface->eps[iface->eps_num].desc, buffer + offset, sizeof(iface->eps[iface->eps_num].desc)); 106 iface->eps_num++; 107 } 108 } 109 offset += desc_length; 110 } 111 112 return true; 113 } 114 115 // add_usb_index() and lookup_usb_index() helper functions allow to store and lookup per-device metadata 116 // associated with a file descriptor that is used to comminicate with a particular emulated device. 117 118 static struct usb_device_index* add_usb_index(int fd, const char* dev, size_t dev_len) 119 { 120 int i = __atomic_fetch_add(&usb_devices_num, 1, __ATOMIC_RELAXED); 121 if (i >= USB_MAX_FDS) 122 return NULL; 123 124 if (!parse_usb_descriptor(dev, dev_len, &usb_devices[i].index)) 125 return NULL; 126 127 __atomic_store_n(&usb_devices[i].fd, fd, __ATOMIC_RELEASE); 128 return &usb_devices[i].index; 129 } 130 131 #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k 132 133 #if USB_DEBUG 134 135 #include <linux/hid.h> 136 #include <linux/usb/audio.h> 137 #include <linux/usb/cdc.h> 138 #include <linux/usb/ch11.h> 139 #include <linux/usb/ch9.h> 140 141 // drivers/usb/class/usblp.c 142 #define USBLP_REQ_GET_ID 0x00 143 #define USBLP_REQ_GET_STATUS 0x01 144 #define USBLP_REQ_RESET 0x02 145 146 const char* usb_class_to_string(unsigned value) 147 { 148 switch (value) { 149 case USB_CLASS_PER_INTERFACE: 150 return "USB_CLASS_PER_INTERFACE"; 151 case USB_CLASS_AUDIO: 152 return "USB_CLASS_AUDIO"; 153 case USB_CLASS_COMM: 154 return "USB_CLASS_COMM"; 155 case USB_CLASS_HID: 156 return "USB_CLASS_HID"; 157 case USB_CLASS_PHYSICAL: 158 return "USB_CLASS_PHYSICAL"; 159 case USB_CLASS_STILL_IMAGE: 160 return "USB_CLASS_STILL_IMAGE"; 161 case USB_CLASS_PRINTER: 162 return "USB_CLASS_PRINTER"; 163 case USB_CLASS_MASS_STORAGE: 164 return "USB_CLASS_MASS_STORAGE"; 165 case USB_CLASS_HUB: 166 return "USB_CLASS_HUB"; 167 case USB_CLASS_CDC_DATA: 168 return "USB_CLASS_CDC_DATA"; 169 case USB_CLASS_CSCID: 170 return "USB_CLASS_CSCID"; 171 case USB_CLASS_CONTENT_SEC: 172 return "USB_CLASS_CONTENT_SEC"; 173 case USB_CLASS_VIDEO: 174 return "USB_CLASS_VIDEO"; 175 case USB_CLASS_WIRELESS_CONTROLLER: 176 return "USB_CLASS_WIRELESS_CONTROLLER"; 177 case USB_CLASS_MISC: 178 return "USB_CLASS_MISC"; 179 case USB_CLASS_APP_SPEC: 180 return "USB_CLASS_APP_SPEC"; 181 case USB_CLASS_VENDOR_SPEC: 182 return "USB_CLASS_VENDOR_SPEC"; 183 } 184 return "unknown"; 185 } 186 187 // A helper function that allows to see what kind of device is being emulated. 188 // Useful for debugging. 189 static void analyze_usb_device(struct usb_device_index* index) 190 { 191 debug("analyze_usb_device: idVendor = %04x\n", (unsigned)index->dev->idVendor); 192 debug("analyze_usb_device: idProduct = %04x\n", (unsigned)index->dev->idProduct); 193 194 debug("analyze_usb_device: bDeviceClass = %x (%s)\n", (unsigned)index->dev->bDeviceClass, 195 usb_class_to_string(index->dev->bDeviceClass)); 196 debug("analyze_usb_device: bDeviceSubClass = %x\n", (unsigned)index->dev->bDeviceSubClass); 197 debug("analyze_usb_device: bDeviceProtocol = %x\n", (unsigned)index->dev->bDeviceProtocol); 198 199 for (int i = 0; i < index->ifaces_num; i++) { 200 struct usb_interface_descriptor* iface = index->ifaces[i].iface; 201 debug("analyze_usb_device: interface #%d:\n", i); 202 debug("analyze_usb_device: bInterfaceClass = %x (%s)\n", (unsigned)iface->bInterfaceClass, 203 usb_class_to_string(iface->bInterfaceClass)); 204 debug("analyze_usb_device: bInterfaceSubClass = %x\n", (unsigned)iface->bInterfaceSubClass); 205 debug("analyze_usb_device: bInterfaceProtocol = %x\n", (unsigned)iface->bInterfaceProtocol); 206 } 207 } 208 209 static bool analyze_control_request_standard(struct usb_device_index* index, struct usb_ctrlrequest* ctrl) 210 { 211 uint8 bDeviceClass = index->bDeviceClass; 212 uint8 bInterfaceClass = index->ifaces[index->iface_cur].bInterfaceClass; 213 214 // For some reason HID class GET_DESCRIPTOR requests are STANDARD. 215 if (bDeviceClass == USB_CLASS_HID || bInterfaceClass == USB_CLASS_HID) { 216 switch (ctrl->bRequest) { 217 case USB_REQ_GET_DESCRIPTOR: 218 debug("analyze_control_request: req = USB_REQ_GET_DESCRIPTOR\n"); 219 switch (ctrl->wValue >> 8) { 220 case HID_DT_HID: 221 debug("analyze_control_request: desc = HID_DT_HID\n"); 222 return true; 223 case HID_DT_REPORT: 224 debug("analyze_control_request: desc = HID_DT_REPORT\n"); 225 return true; 226 case HID_DT_PHYSICAL: 227 debug("analyze_control_request: desc = HID_DT_PHYSICAL\n"); 228 return false; 229 } 230 } 231 // Fallthrough to lookup normal STANDARD requests. 232 } 233 234 switch (ctrl->bRequest) { 235 case USB_REQ_GET_DESCRIPTOR: 236 debug("analyze_control_request: req = USB_REQ_GET_DESCRIPTOR\n"); 237 switch (ctrl->wValue >> 8) { 238 case USB_DT_DEVICE: 239 debug("analyze_control_request: desc = USB_DT_DEVICE\n"); 240 return true; 241 case USB_DT_CONFIG: 242 debug("analyze_control_request: desc = USB_DT_CONFIG, index = %d\n", (int)(ctrl->wValue & 0xff)); 243 return true; 244 case USB_DT_STRING: 245 debug("analyze_control_request: desc = USB_DT_STRING\n"); 246 return true; 247 case USB_DT_INTERFACE: 248 debug("analyze_control_request: desc = USB_DT_INTERFACE\n"); 249 break; 250 case USB_DT_ENDPOINT: 251 debug("analyze_control_request: desc = USB_DT_ENDPOINT\n"); 252 break; 253 case USB_DT_DEVICE_QUALIFIER: 254 debug("analyze_control_request: desc = USB_DT_DEVICE_QUALIFIER\n"); 255 return true; 256 case USB_DT_OTHER_SPEED_CONFIG: 257 debug("analyze_control_request: desc = USB_DT_OTHER_SPEED_CONFIG\n"); 258 break; 259 case USB_DT_INTERFACE_POWER: 260 debug("analyze_control_request: desc = USB_DT_INTERFACE_POWER\n"); 261 break; 262 case USB_DT_OTG: 263 debug("analyze_control_request: desc = USB_DT_OTG\n"); 264 break; 265 case USB_DT_DEBUG: 266 debug("analyze_control_request: desc = USB_DT_DEBUG\n"); 267 break; 268 case USB_DT_INTERFACE_ASSOCIATION: 269 debug("analyze_control_request: desc = USB_DT_INTERFACE_ASSOCIATION\n"); 270 break; 271 case USB_DT_SECURITY: 272 debug("analyze_control_request: desc = USB_DT_SECURITY\n"); 273 break; 274 case USB_DT_KEY: 275 debug("analyze_control_request: desc = USB_DT_KEY\n"); 276 break; 277 case USB_DT_ENCRYPTION_TYPE: 278 debug("analyze_control_request: desc = USB_DT_ENCRYPTION_TYPE\n"); 279 break; 280 case USB_DT_BOS: 281 debug("analyze_control_request: desc = USB_DT_BOS\n"); 282 return true; 283 case USB_DT_DEVICE_CAPABILITY: 284 debug("analyze_control_request: desc = USB_DT_DEVICE_CAPABILITY\n"); 285 break; 286 case USB_DT_WIRELESS_ENDPOINT_COMP: 287 debug("analyze_control_request: desc = USB_DT_WIRELESS_ENDPOINT_COMP\n"); 288 break; 289 case USB_DT_WIRE_ADAPTER: 290 debug("analyze_control_request: desc = USB_DT_WIRE_ADAPTER\n"); 291 break; 292 case USB_DT_RPIPE: 293 debug("analyze_control_request: desc = USB_DT_RPIPE\n"); 294 break; 295 case USB_DT_CS_RADIO_CONTROL: 296 debug("analyze_control_request: desc = USB_DT_CS_RADIO_CONTROL\n"); 297 break; 298 case USB_DT_PIPE_USAGE: 299 debug("analyze_control_request: desc = USB_DT_PIPE_USAGE\n"); 300 break; 301 case USB_DT_SS_ENDPOINT_COMP: 302 debug("analyze_control_request: desc = USB_DT_SS_ENDPOINT_COMP\n"); 303 break; 304 case USB_DT_SSP_ISOC_ENDPOINT_COMP: 305 debug("analyze_control_request: desc = USB_DT_SSP_ISOC_ENDPOINT_COMP\n"); 306 break; 307 default: 308 debug("analyze_control_request: desc = unknown = 0x%x\n", (int)(ctrl->wValue >> 8)); 309 break; 310 } 311 break; 312 case USB_REQ_GET_STATUS: 313 debug("analyze_control_request: req = USB_REQ_GET_STATUS\n"); 314 break; 315 case USB_REQ_CLEAR_FEATURE: 316 debug("analyze_control_request: req = USB_REQ_CLEAR_FEATURE\n"); 317 break; 318 case USB_REQ_SET_FEATURE: 319 debug("analyze_control_request: req = USB_REQ_SET_FEATURE\n"); 320 break; 321 case USB_REQ_GET_CONFIGURATION: 322 debug("analyze_control_request: req = USB_REQ_GET_CONFIGURATION\n"); 323 return true; 324 case USB_REQ_SET_CONFIGURATION: 325 debug("analyze_control_request: req = USB_REQ_SET_CONFIGURATION\n"); 326 break; 327 case USB_REQ_GET_INTERFACE: 328 debug("analyze_control_request: req = USB_REQ_GET_INTERFACE\n"); 329 return true; 330 case USB_REQ_SET_INTERFACE: 331 debug("analyze_control_request: req = USB_REQ_SET_INTERFACE\n"); 332 break; 333 default: 334 debug("analyze_control_request: req = unknown = 0x%x\n", (int)ctrl->bRequest); 335 break; 336 } 337 338 return false; 339 } 340 341 static bool analyze_control_request_class(struct usb_device_index* index, struct usb_ctrlrequest* ctrl) 342 { 343 uint8 bDeviceClass = index->bDeviceClass; 344 uint8 bInterfaceClass = index->ifaces[index->iface_cur].bInterfaceClass; 345 346 if (bDeviceClass == USB_CLASS_HID || bInterfaceClass == USB_CLASS_HID) { 347 switch (ctrl->bRequest) { 348 case HID_REQ_GET_REPORT: 349 debug("analyze_control_request: req = HID_REQ_GET_REPORT\n"); 350 return true; 351 case HID_REQ_GET_IDLE: 352 debug("analyze_control_request: req = HID_REQ_GET_IDLE\n"); 353 break; 354 case HID_REQ_GET_PROTOCOL: 355 debug("analyze_control_request: req = HID_REQ_GET_PROTOCOL\n"); 356 return true; 357 case HID_REQ_SET_REPORT: 358 debug("analyze_control_request: req = HID_REQ_SET_REPORT\n"); 359 break; 360 case HID_REQ_SET_IDLE: 361 debug("analyze_control_request: req = HID_REQ_SET_IDLE\n"); 362 break; 363 case HID_REQ_SET_PROTOCOL: 364 debug("analyze_control_request: req = HID_REQ_SET_PROTOCOL\n"); 365 break; 366 } 367 } 368 369 if (bDeviceClass == USB_CLASS_AUDIO || bInterfaceClass == USB_CLASS_AUDIO) { 370 switch (ctrl->bRequest) { 371 case UAC_SET_CUR: 372 debug("analyze_control_request: req = UAC_SET_CUR\n"); 373 break; 374 case UAC_GET_CUR: 375 debug("analyze_control_request: req = UAC_GET_CUR\n"); 376 return true; 377 case UAC_SET_MIN: 378 debug("analyze_control_request: req = UAC_SET_MIN\n"); 379 break; 380 case UAC_GET_MIN: 381 debug("analyze_control_request: req = UAC_GET_MIN\n"); 382 return true; 383 case UAC_SET_MAX: 384 debug("analyze_control_request: req = UAC_SET_MAX\n"); 385 break; 386 case UAC_GET_MAX: 387 debug("analyze_control_request: req = UAC_GET_MAX\n"); 388 return true; 389 case UAC_SET_RES: 390 debug("analyze_control_request: req = UAC_SET_RES\n"); 391 break; 392 case UAC_GET_RES: 393 debug("analyze_control_request: req = UAC_GET_RES\n"); 394 return true; 395 case UAC_SET_MEM: 396 debug("analyze_control_request: req = UAC_SET_MEM\n"); 397 break; 398 case UAC_GET_MEM: 399 debug("analyze_control_request: req = UAC_GET_MEM\n"); 400 return true; 401 } 402 } 403 404 if (bDeviceClass == USB_CLASS_PRINTER || bInterfaceClass == USB_CLASS_PRINTER) { 405 switch (ctrl->bRequest) { 406 case USBLP_REQ_GET_ID: 407 debug("analyze_control_request: req = USBLP_REQ_GET_ID\n"); 408 return true; 409 case USBLP_REQ_GET_STATUS: 410 debug("analyze_control_request: req = USBLP_REQ_GET_STATUS\n"); 411 return true; 412 case USBLP_REQ_RESET: 413 debug("analyze_control_request: req = USBLP_REQ_RESET\n"); 414 break; 415 } 416 } 417 418 if (bDeviceClass == USB_CLASS_HUB || bInterfaceClass == USB_CLASS_HUB) { 419 switch (ctrl->bRequest) { 420 case USB_REQ_GET_DESCRIPTOR: 421 switch (ctrl->wValue >> 8) { 422 case USB_DT_HUB: 423 debug("analyze_control_request: desc = USB_DT_HUB\n"); 424 return true; 425 case USB_DT_SS_HUB: 426 debug("analyze_control_request: desc = USB_DT_SS_HUB\n"); 427 return true; 428 } 429 case USB_REQ_GET_STATUS: 430 debug("analyze_control_request: req = USB_REQ_GET_STATUS\n"); 431 return true; 432 case HUB_SET_DEPTH: 433 debug("analyze_control_request: req = HUB_SET_DEPTH\n"); 434 break; 435 } 436 } 437 438 if (bInterfaceClass == USB_CLASS_COMM) { 439 switch (ctrl->bRequest) { 440 case USB_CDC_SEND_ENCAPSULATED_COMMAND: 441 debug("analyze_control_request: req = USB_CDC_SEND_ENCAPSULATED_COMMAND\n"); 442 break; 443 case USB_CDC_GET_ENCAPSULATED_RESPONSE: 444 debug("analyze_control_request: req = USB_CDC_GET_ENCAPSULATED_RESPONSE\n"); 445 break; 446 case USB_CDC_REQ_SET_LINE_CODING: 447 debug("analyze_control_request: req = USB_CDC_REQ_SET_LINE_CODING\n"); 448 break; 449 case USB_CDC_REQ_GET_LINE_CODING: 450 debug("analyze_control_request: req = USB_CDC_REQ_GET_LINE_CODING\n"); 451 break; 452 case USB_CDC_REQ_SET_CONTROL_LINE_STATE: 453 debug("analyze_control_request: req = USB_CDC_REQ_SET_CONTROL_LINE_STATE\n"); 454 break; 455 case USB_CDC_REQ_SEND_BREAK: 456 debug("analyze_control_request: req = USB_CDC_REQ_SEND_BREAK\n"); 457 break; 458 case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: 459 debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_MULTICAST_FILTERS\n"); 460 break; 461 case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: 462 debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER\n"); 463 break; 464 case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: 465 debug("analyze_control_request: req = USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER\n"); 466 break; 467 case USB_CDC_SET_ETHERNET_PACKET_FILTER: 468 debug("analyze_control_request: req = USB_CDC_SET_ETHERNET_PACKET_FILTER\n"); 469 break; 470 case USB_CDC_GET_ETHERNET_STATISTIC: 471 debug("analyze_control_request: req = USB_CDC_GET_ETHERNET_STATISTIC\n"); 472 break; 473 case USB_CDC_GET_NTB_PARAMETERS: 474 debug("analyze_control_request: req = USB_CDC_GET_NTB_PARAMETERS\n"); 475 return true; 476 case USB_CDC_GET_NET_ADDRESS: 477 debug("analyze_control_request: req = USB_CDC_GET_NET_ADDRESS\n"); 478 break; 479 case USB_CDC_SET_NET_ADDRESS: 480 debug("analyze_control_request: req = USB_CDC_SET_NET_ADDRESS\n"); 481 break; 482 case USB_CDC_GET_NTB_FORMAT: 483 debug("analyze_control_request: req = USB_CDC_GET_NTB_FORMAT\n"); 484 return true; 485 case USB_CDC_SET_NTB_FORMAT: 486 debug("analyze_control_request: req = USB_CDC_SET_NTB_FORMAT\n"); 487 break; 488 case USB_CDC_GET_NTB_INPUT_SIZE: 489 debug("analyze_control_request: req = USB_CDC_GET_NTB_INPUT_SIZE\n"); 490 return true; 491 case USB_CDC_SET_NTB_INPUT_SIZE: 492 debug("analyze_control_request: req = USB_CDC_SET_NTB_INPUT_SIZE\n"); 493 break; 494 case USB_CDC_GET_MAX_DATAGRAM_SIZE: 495 debug("analyze_control_request: req = USB_CDC_GET_MAX_DATAGRAM_SIZE\n"); 496 return true; 497 case USB_CDC_SET_MAX_DATAGRAM_SIZE: 498 debug("analyze_control_request: req = USB_CDC_SET_MAX_DATAGRAM_SIZE\n"); 499 break; 500 case USB_CDC_GET_CRC_MODE: 501 debug("analyze_control_request: req = USB_CDC_GET_CRC_MODE\n"); 502 return true; 503 case USB_CDC_SET_CRC_MODE: 504 debug("analyze_control_request: req = USB_CDC_SET_CRC_MODE\n"); 505 break; 506 } 507 } 508 509 return false; 510 } 511 512 static bool analyze_control_request_vendor(struct usb_device_index* index, struct usb_ctrlrequest* ctrl) 513 { 514 // Ignore vendor requests for now. 515 return true; 516 } 517 518 // A helper function that prints a request in readable form and returns whether descriptions for this 519 // request exist. Needs to be updated manually when new descriptions are added. Useful for debugging. 520 static void analyze_control_request(int fd, struct usb_ctrlrequest* ctrl) 521 { 522 struct usb_device_index* index = lookup_usb_index(fd); 523 524 if (!index) 525 return; 526 527 switch (ctrl->bRequestType & USB_TYPE_MASK) { 528 case USB_TYPE_STANDARD: 529 debug("analyze_control_request: type = USB_TYPE_STANDARD\n"); 530 if (analyze_control_request_standard(index, ctrl)) 531 return; 532 break; 533 case USB_TYPE_CLASS: 534 debug("analyze_control_request: type = USB_TYPE_CLASS\n"); 535 if (analyze_control_request_class(index, ctrl)) 536 return; 537 break; 538 case USB_TYPE_VENDOR: 539 debug("analyze_control_request: type = USB_TYPE_VENDOR\n"); 540 if (analyze_control_request_vendor(index, ctrl)) 541 return; 542 break; 543 } 544 545 if (ctrl->bRequestType & USB_DIR_IN) { 546 char message[128]; 547 debug("analyze_control_request: unknown control request\n"); 548 snprintf(&message[0], sizeof(message), "BUG: unknown control request (0x%x, 0x%x, 0x%x, 0x%x, %d)", 549 ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, ctrl->wLength); 550 write_file("/dev/kmsg", &message[0]); 551 } 552 } 553 554 #endif // USB_DEBUG 555 556 struct vusb_connect_string_descriptor { 557 uint32 len; 558 char* str; 559 } __attribute__((packed)); 560 561 struct vusb_connect_descriptors { 562 uint32 qual_len; 563 char* qual; 564 uint32 bos_len; 565 char* bos; 566 uint32 strs_len; 567 struct vusb_connect_string_descriptor strs[0]; 568 } __attribute__((packed)); 569 570 #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k 571 572 static const char default_string[] = { 573 8, USB_DT_STRING, 574 's', 0, 'y', 0, 'z', 0 // UTF16-encoded "syz" 575 }; 576 577 static const char default_lang_id[] = { 578 4, USB_DT_STRING, 579 0x09, 0x04 // English (United States) 580 }; 581 582 // lookup_connect_response_in() is a helper function that returns a response to a USB IN request 583 // based on syzkaller-generated arguments provided to syz_usb_connect* pseudo-syscalls. The data 584 // and its length to be used as a response are returned in *response_data and *response_length. 585 // The return value of this function lookup_connect_response_inindicates whether the request is known to syzkaller. 586 587 static bool lookup_connect_response_in(int fd, const struct vusb_connect_descriptors* descs, 588 const struct usb_ctrlrequest* ctrl, 589 struct usb_qualifier_descriptor* qual, 590 char** response_data, uint32* response_length) 591 { 592 struct usb_device_index* index = lookup_usb_index(fd); 593 uint8 str_idx; 594 595 if (!index) 596 return false; 597 598 switch (ctrl->bRequestType & USB_TYPE_MASK) { 599 case USB_TYPE_STANDARD: 600 switch (ctrl->bRequest) { 601 case USB_REQ_GET_DESCRIPTOR: 602 switch (ctrl->wValue >> 8) { 603 case USB_DT_DEVICE: 604 *response_data = (char*)index->dev; 605 *response_length = sizeof(*index->dev); 606 return true; 607 case USB_DT_CONFIG: 608 *response_data = (char*)index->config; 609 *response_length = index->config_length; 610 return true; 611 case USB_DT_STRING: 612 str_idx = (uint8)ctrl->wValue; 613 if (descs && str_idx < descs->strs_len) { 614 *response_data = descs->strs[str_idx].str; 615 *response_length = descs->strs[str_idx].len; 616 return true; 617 } 618 if (str_idx == 0) { 619 *response_data = (char*)&default_lang_id[0]; 620 *response_length = default_lang_id[0]; 621 return true; 622 } 623 *response_data = (char*)&default_string[0]; 624 *response_length = default_string[0]; 625 return true; 626 case USB_DT_BOS: 627 *response_data = descs->bos; 628 *response_length = descs->bos_len; 629 return true; 630 case USB_DT_DEVICE_QUALIFIER: 631 if (!descs->qual) { 632 // Fill in DEVICE_QUALIFIER based on DEVICE if not provided. 633 qual->bLength = sizeof(*qual); 634 qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; 635 qual->bcdUSB = index->dev->bcdUSB; 636 qual->bDeviceClass = index->dev->bDeviceClass; 637 qual->bDeviceSubClass = index->dev->bDeviceSubClass; 638 qual->bDeviceProtocol = index->dev->bDeviceProtocol; 639 qual->bMaxPacketSize0 = index->dev->bMaxPacketSize0; 640 qual->bNumConfigurations = index->dev->bNumConfigurations; 641 qual->bRESERVED = 0; 642 *response_data = (char*)qual; 643 *response_length = sizeof(*qual); 644 return true; 645 } 646 *response_data = descs->qual; 647 *response_length = descs->qual_len; 648 return true; 649 default: 650 break; 651 } 652 break; 653 default: 654 break; 655 } 656 break; 657 default: 658 break; 659 } 660 661 debug("lookup_connect_response_in: unknown request"); 662 return false; 663 } 664 665 #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k 666 667 // lookup_connect_response_out() functions process a USB OUT request and return in *done 668 // whether this is the last request that must be handled by syz_usb_connect* pseudo-syscalls. 669 670 typedef bool (*lookup_connect_out_response_t)(int fd, const struct vusb_connect_descriptors* descs, 671 const struct usb_ctrlrequest* ctrl, bool* done); 672 673 #if SYZ_EXECUTOR || __NR_syz_usb_connect 674 static bool lookup_connect_response_out_generic(int fd, const struct vusb_connect_descriptors* descs, 675 const struct usb_ctrlrequest* ctrl, bool* done) 676 { 677 switch (ctrl->bRequestType & USB_TYPE_MASK) { 678 case USB_TYPE_STANDARD: 679 switch (ctrl->bRequest) { 680 case USB_REQ_SET_CONFIGURATION: 681 *done = true; 682 return true; 683 default: 684 break; 685 } 686 break; 687 } 688 689 debug("lookup_connect_response_out: unknown request"); 690 return false; 691 } 692 #endif // SYZ_EXECUTOR || __NR_syz_usb_connect 693 694 #if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k) 695 696 // drivers/net/wireless/ath/ath9k/hif_usb.h 697 #define ATH9K_FIRMWARE_DOWNLOAD 0x30 698 #define ATH9K_FIRMWARE_DOWNLOAD_COMP 0x31 699 700 static bool lookup_connect_response_out_ath9k(int fd, const struct vusb_connect_descriptors* descs, 701 const struct usb_ctrlrequest* ctrl, bool* done) 702 { 703 switch (ctrl->bRequestType & USB_TYPE_MASK) { 704 case USB_TYPE_STANDARD: 705 switch (ctrl->bRequest) { 706 case USB_REQ_SET_CONFIGURATION: 707 return true; 708 default: 709 break; 710 } 711 break; 712 case USB_TYPE_VENDOR: 713 switch (ctrl->bRequest) { 714 case ATH9K_FIRMWARE_DOWNLOAD: 715 return true; 716 case ATH9K_FIRMWARE_DOWNLOAD_COMP: 717 *done = true; 718 return true; 719 default: 720 break; 721 } 722 break; 723 } 724 725 debug("lookup_connect_response_out_ath9k: unknown request"); 726 return false; 727 } 728 729 #endif // SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k 730 731 #if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_control_io) 732 733 struct vusb_descriptor { 734 uint8 req_type; 735 uint8 desc_type; 736 uint32 len; 737 char data[0]; 738 } __attribute__((packed)); 739 740 struct vusb_descriptors { 741 uint32 len; 742 struct vusb_descriptor* generic; 743 struct vusb_descriptor* descs[0]; 744 } __attribute__((packed)); 745 746 struct vusb_response { 747 uint8 type; 748 uint8 req; 749 uint32 len; 750 char data[0]; 751 } __attribute__((packed)); 752 753 struct vusb_responses { 754 uint32 len; 755 struct vusb_response* generic; 756 struct vusb_response* resps[0]; 757 } __attribute__((packed)); 758 759 // lookup_control_response() is a helper function that returns a response to a USB IN request based 760 // on syzkaller-generated arguments provided to syz_usb_control_io* pseudo-syscalls. The data and its 761 // length to be used as a response are returned in *response_data and *response_length. The return 762 // value of this function indicates whether the response for this request is provided in 763 // syz_usb_control_io* arguments. 764 765 static bool lookup_control_response(const struct vusb_descriptors* descs, const struct vusb_responses* resps, 766 struct usb_ctrlrequest* ctrl, char** response_data, uint32* response_length) 767 { 768 int descs_num = 0; 769 int resps_num = 0; 770 771 if (descs) 772 descs_num = (descs->len - offsetof(struct vusb_descriptors, descs)) / sizeof(descs->descs[0]); 773 if (resps) 774 resps_num = (resps->len - offsetof(struct vusb_responses, resps)) / sizeof(resps->resps[0]); 775 776 uint8 req = ctrl->bRequest; 777 uint8 req_type = ctrl->bRequestType & USB_TYPE_MASK; 778 uint8 desc_type = ctrl->wValue >> 8; 779 780 if (req == USB_REQ_GET_DESCRIPTOR) { 781 int i; 782 783 for (i = 0; i < descs_num; i++) { 784 struct vusb_descriptor* desc = descs->descs[i]; 785 if (!desc) 786 continue; 787 if (desc->req_type == req_type && desc->desc_type == desc_type) { 788 *response_length = desc->len; 789 if (*response_length != 0) 790 *response_data = &desc->data[0]; 791 else 792 *response_data = NULL; 793 return true; 794 } 795 } 796 797 if (descs && descs->generic) { 798 *response_data = &descs->generic->data[0]; 799 *response_length = descs->generic->len; 800 return true; 801 } 802 } else { 803 int i; 804 805 for (i = 0; i < resps_num; i++) { 806 struct vusb_response* resp = resps->resps[i]; 807 if (!resp) 808 continue; 809 if (resp->type == req_type && resp->req == req) { 810 *response_length = resp->len; 811 if (*response_length != 0) 812 *response_data = &resp->data[0]; 813 else 814 *response_data = NULL; 815 return true; 816 } 817 } 818 819 if (resps && resps->generic) { 820 *response_data = &resps->generic->data[0]; 821 *response_length = resps->generic->len; 822 return true; 823 } 824 } 825 826 return false; 827 } 828 829 #endif // SYZ_EXECUTOR || __NR_syz_usb_control_io