// https://syzkaller.appspot.com/bug?id=fad611d7ddd914f0b4488742a63b93f31b321ca0 #include #include #include #include #include #include #include #include #include static void check_and_print(int res, const char *msg) { if (res < 0 && errno != EEXIST) { printf("[-] %s: %s\n", msg, strerror(errno)); exit(1); } printf("[+] %s successful.\n", msg); } int main(void) { // Setup unbuffered IO setvbuf(stdout, NULL, _IONBF, 0); // Mount configfs if (mount("none", "/sys/kernel/config", "configfs", 0, NULL) != 0) { if (errno != EBUSY) { printf("[-] Failed to mount configfs: %s\n", strerror(errno)); } } printf("[+] mount configfs successful (or already mounted).\n"); // 1. Create gadget int res = mkdir("/sys/kernel/config/usb_gadget/g1", 0777); check_and_print(res, "mkdir g1"); // 2. Create UVC function res = mkdir("/sys/kernel/config/usb_gadget/g1/functions/uvc.0", 0777); check_and_print(res, "mkdir uvc.0"); // 3. Create TCM function (establishes su_mutex -> opts->dep_lock) // This also auto-loads usb_f_tcm which registers the usb_gadget fabric res = mkdir("/sys/kernel/config/usb_gadget/g1/functions/tcm.0", 0777); check_and_print(res, "mkdir tcm.0"); // 4. Create target fabric directory res = mkdir("/sys/kernel/config/target/usb_gadget", 0777); check_and_print(res, "mkdir target/usb_gadget"); // 5. Create target port res = mkdir("/sys/kernel/config/target/usb_gadget/naa.1234", 0777); check_and_print(res, "mkdir naa.1234"); // 6. Create TPG (establishes opts->dep_lock -> i_mutex_key) res = mkdir("/sys/kernel/config/target/usb_gadget/naa.1234/tpgt_1", 0777); check_and_print(res, "mkdir tpgt_1"); // 7. Remove TPG (establishes i_mutex_key -> frag_sem) res = rmdir("/sys/kernel/config/target/usb_gadget/naa.1234/tpgt_1"); if (res < 0) { printf("[-] rmdir tpgt_1 failed: %s\n", strerror(errno)); exit(1); } printf("[+] rmdir tpgt_1 successful.\n"); // 8. Read iTerminal (establishes frag_sem -> su_mutex and triggers lockdep) int fd = open("/sys/kernel/config/usb_gadget/g1/functions/uvc.0/control/terminal/output/default/iTerminal", O_RDONLY); if (fd < 0) { printf("[-] open iTerminal failed: %s\n", strerror(errno)); exit(1); } printf("[+] open iTerminal successful.\n"); char buf[128]; res = read(fd, buf, sizeof(buf)); if (res < 0) { printf("[-] read iTerminal failed: %s\n", strerror(errno)); } else { printf("[+] read iTerminal successful.\n"); } close(fd); // Sleep a bit to allow lockdep to print the warning sleep(1); return 0; }