// https://syzkaller.appspot.com/bug?id=f318ac4742bf8703535c973a869898a21fb10e3e #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include int main(void) { setvbuf(stdout, NULL, _IONBF, 0); printf("[*] Starting reproducer...\n"); // Step 1: Record pipe->mutex -> of->mutex int pipefd[2]; if (pipe(pipefd) < 0) { printf("[-] pipe failed: %s\n", strerror(errno)); return 1; } int fd = open("/sys/power/resume", O_WRONLY); if (fd < 0) { printf("[-] open /sys/power/resume failed: %s\n", strerror(errno)); return 1; } const char *dummy = "/nonexistent"; if (write(pipefd[1], dummy, strlen(dummy)) < 0) { printf("[-] write to pipe failed: %s\n", strerror(errno)); return 1; } // This will acquire pipe->mutex then of->mutex if (splice(pipefd[0], NULL, fd, NULL, strlen(dummy), 0) < 0) { printf("[-] splice returned error (expected): %s\n", strerror(errno)); } else { printf("[+] splice succeeded.\n"); } close(fd); close(pipefd[0]); close(pipefd[1]); printf("[+] Step 1 complete.\n"); // Step 2: Record of->mutex -> sbi->pipe_mutex -> pipe->mutex int autofs_pipe[2]; if (pipe(autofs_pipe) < 0) { printf("[-] autofs pipe failed: %s\n", strerror(errno)); return 1; } if (mkdir("/tmp/autofs_test", 0777) < 0 && errno != EEXIST) { printf("[-] mkdir failed: %s\n", strerror(errno)); return 1; } char data[128]; snprintf(data, sizeof(data), "fd=%d,pgrp=%d,minproto=5,maxproto=5", autofs_pipe[1], getpgrp()); if (mount("autofs", "/tmp/autofs_test", "autofs", 0, data) < 0) { printf("[-] mount autofs failed: %s\n", strerror(errno)); return 1; } printf("[+] autofs mounted.\n"); pid_t child = fork(); if (child < 0) { printf("[-] fork failed: %s\n", strerror(errno)); return 1; } if (child == 0) { // Child process setpgid(0, 0); // Leave oz_mode so automount is triggered int fd2 = open("/sys/power/resume", O_WRONLY); if (fd2 < 0) { printf("[-] child open /sys/power/resume failed: %s\n", strerror(errno)); exit(1); } const char *path = "/tmp/autofs_test/foo"; // This will acquire of->mutex, trigger automount, acquire sbi->pipe_mutex, then pipe->mutex // It will block waiting for autofs daemon. write(fd2, path, strlen(path)); close(fd2); exit(0); } // Parent process // Wait a bit for child to trigger lockdep sleep(2); // Cleanup kill(child, SIGKILL); waitpid(child, NULL, 0); umount("/tmp/autofs_test"); printf("[+] Reproducer complete.\n"); return 0; }