// https://syzkaller.appspot.com/bug?id=fad611d7ddd914f0b4488742a63b93f31b321ca0 #include #include #include #include #include #include #include void do_mkdir(const char *path) { if (mkdir(path, 0777) < 0 && errno != EEXIST) { printf("[-] Failed to create %s: %s\n", path, strerror(errno)); exit(1); } printf("[+] Created %s\n", path); } void do_rmdir(const char *path) { if (rmdir(path) < 0) { printf("[-] Failed to remove %s: %s\n", path, strerror(errno)); exit(1); } printf("[+] Removed %s\n", path); } int main(void) { // 1. Create gadget and UVC function do_mkdir("/sys/kernel/config/usb_gadget/g1"); do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/uvc.0"); do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/uvc.0/streaming/mjpeg/m"); // 2. Create TCM function // Establishes: gadget_subsys.su_mutex -> func_lock -> tpg_instances_lock do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/tcm.0"); // 3. Create target fabric // Establishes: tpg_instances_lock -> inode_lock do_mkdir("/sys/kernel/config/target/usb_gadget"); do_mkdir("/sys/kernel/config/target/usb_gadget/naa.12345"); do_mkdir("/sys/kernel/config/target/usb_gadget/naa.12345/tpgt_1"); // 4. Create and remove a dummy directory // Establishes: inode_lock -> frag_sem do_mkdir("/sys/kernel/config/usb_gadget/g2"); do_rmdir("/sys/kernel/config/usb_gadget/g2"); // 5. Read bmaControls // Establishes: frag_sem -> gadget_subsys.su_mutex (Triggers Lockdep splat) const char *bma_path = "/sys/kernel/config/usb_gadget/g1/functions/uvc.0/streaming/mjpeg/m/bmaControls"; int fd = open(bma_path, O_RDONLY); if (fd < 0) { printf("[-] Failed to open %s: %s\n", bma_path, strerror(errno)); exit(1); } printf("[+] Opened %s\n", bma_path); char buf[128]; if (read(fd, buf, sizeof(buf)) < 0) { printf("[-] Failed to read %s: %s\n", bma_path, strerror(errno)); } else { printf("[+] Read %s successfully\n", bma_path); } close(fd); // Wait for asynchronous lockdep splat to be processed sleep(2); return 0; }