// https://syzkaller.appspot.com/bug?id=dd1d56e3b757e27199f6cae72cd0e80106000d2e #define _GNU_SOURCE #include #include #include #include #include #include #include int main() { // Fix working directory for system() and other path-based operations if (chdir("/") < 0) { perror("chdir"); } // Ensure the virtual DVB driver is loaded system("modprobe vidtv"); // Try to bind the device in case it was unbound by a previous run int bind_fd = open("/sys/bus/platform/drivers/vidtv/bind", O_WRONLY); if (bind_fd >= 0) { if (write(bind_fd, "vidtv.0", 7) > 0) { printf("[+] Bound driver vidtv.0\n"); } close(bind_fd); } char dev_path[256] = {0}; int found = 0; // Wait for the device to appear for (int i = 0; i < 50; i++) { glob_t gl; if (glob("/dev/dvb/adapter*/frontend*", 0, NULL, &gl) == 0 && gl.gl_pathc > 0) { // Check if it's vidtv by looking at sysfs for (size_t j = 0; j < gl.gl_pathc; j++) { char *path = gl.gl_pathv[j]; int adapter, frontend; if (sscanf(path, "/dev/dvb/adapter%d/frontend%d", &adapter, &frontend) == 2) { char sysfs_path[512]; snprintf(sysfs_path, sizeof(sysfs_path), "/sys/class/dvb/dvb%d.frontend%d/device", adapter, frontend); char target[512]; ssize_t len = readlink(sysfs_path, target, sizeof(target) - 1); if (len > 0) { target[len] = '\0'; if (strstr(target, "vidtv") != NULL) { strncpy(dev_path, path, sizeof(dev_path) - 1); found = 1; break; } } } } if (!found && i == 49) { // Fallback to the first one if vidtv specifically is not found strncpy(dev_path, gl.gl_pathv[0], sizeof(dev_path) - 1); found = 1; } if (found) { globfree(&gl); break; } } globfree(&gl); usleep(100000); // 100ms } if (!found) { printf("[-] No DVB frontend devices found\n"); return 1; } printf("[+] Found frontend: %s\n", dev_path); // 1. Open the frontend device (increments refcount) int fd = open(dev_path, O_RDONLY); if (fd < 0) { printf("[-] Failed to open frontend device: %s\n", strerror(errno)); return 1; } printf("[+] Opened frontend device\n"); // 2. Unbind the platform driver to trigger media_device_cleanup() and destroy the mutex int unbind_fd = open("/sys/bus/platform/drivers/vidtv/unbind", O_WRONLY); if (unbind_fd >= 0) { // The platform device is typically named "vidtv.0", but could be "vidtv" if (write(unbind_fd, "vidtv.0", 7) < 0) { if (write(unbind_fd, "vidtv", 5) < 0) { printf("[-] Failed to write to unbind: %s\n", strerror(errno)); } else { printf("[+] Unbound driver vidtv\n"); } } else { printf("[+] Unbound driver vidtv.0\n"); } close(unbind_fd); } else { printf("[-] Failed to open unbind: %s\n", strerror(errno)); // Fallback: try to remove the module if unbind fails system("rmmod dvb_vidtv_bridge"); system("rmmod vidtv"); } // Give the kernel a moment to process the unbind and destroy the mutex usleep(500000); printf("[+] Closing frontend device to trigger the bug...\n"); // 3. Close the frontend device. // This triggers dvb_frontend_release() which will attempt to lock the destroyed graph_mutex. if (close(fd) < 0) { printf("[-] Failed to close frontend device: %s\n", strerror(errno)); } else { printf("[+] Closed frontend device\n"); } // Wait for the asynchronous warning to be printed sleep(2); printf("[+] Done.\n"); return 0; }