// https://syzkaller.appspot.com/bug?id=4383f618da77d7caee6212ce8921a61f92ba95d7 #define _GNU_SOURCE #include #include #include #include #include #include #include #include void setup_configfs(void) { mkdir("/sys/kernel/config", 0755); if (mount("configfs", "/sys/kernel/config", "configfs", 0, NULL) < 0 && errno != EBUSY) { printf("[-] Failed to mount configfs: %s\n", strerror(errno)); exit(1); } printf("[+] configfs mounted.\n"); } int do_mkdir(const char *path) { if (mkdir(path, 0777) < 0 && errno != EEXIST) { printf("[-] Failed to mkdir %s: %s\n", path, strerror(errno)); return -1; } printf("[+] mkdir %s successful.\n", path); return 0; } int do_rmdir(const char *path) { if (rmdir(path) < 0) { printf("[-] Failed to rmdir %s: %s\n", path, strerror(errno)); return -1; } printf("[+] rmdir %s successful.\n", path); return 0; } int main(void) { int fd; setvbuf(stdout, NULL, _IONBF, 0); setup_configfs(); // Action 1: inode_lock -> &p->frag_sem // Subsystem root, might already exist or fail to create, ignore error. mkdir("/sys/kernel/config/usb_gadget", 0777); if (do_mkdir("/sys/kernel/config/usb_gadget/g1") < 0) exit(1); if (do_rmdir("/sys/kernel/config/usb_gadget/g1") < 0) exit(1); // Action 2: gadget_subsys.su_mutex -> func_lock -> tpg_instances_lock if (do_mkdir("/sys/kernel/config/usb_gadget/g1") < 0) exit(1); if (do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/tcm.0") < 0) { printf("[-] tcm function creation failed, maybe not supported. Exiting.\n"); exit(1); } // Action 3: tpg_instances_lock -> inode_lock mkdir("/sys/kernel/config/target", 0777); if (do_mkdir("/sys/kernel/config/target/usb_gadget") < 0) exit(1); if (do_mkdir("/sys/kernel/config/target/usb_gadget/naa.6001405000000000") < 0) exit(1); if (do_mkdir("/sys/kernel/config/target/usb_gadget/naa.6001405000000000/tpgt_1") < 0) exit(1); // Action 4: &p->frag_sem -> gadget_subsys.su_mutex if (do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/uvc.0") < 0) exit(1); if (do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/uvc.0/streaming/uncompressed/u") < 0) exit(1); if (do_mkdir("/sys/kernel/config/usb_gadget/g1/functions/uvc.0/streaming/uncompressed/u/1080p") < 0) exit(1); fd = open("/sys/kernel/config/usb_gadget/g1/functions/uvc.0/streaming/uncompressed/u/1080p/wWidth", O_WRONLY); if (fd < 0) { printf("[-] Failed to open wWidth: %s\n", strerror(errno)); exit(1); } printf("[+] open wWidth successful.\n"); if (write(fd, "1920\n", 5) < 0) { printf("[-] Failed to write wWidth: %s\n", strerror(errno)); } else { printf("[+] write wWidth successful.\n"); } close(fd); sleep(1); printf("[+] Done.\n"); return 0; }