// https://syzkaller.appspot.com/bug?id=7349616606afa3c986c377792f7ccbf9daae1142 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #ifndef SYS_memfd_create #define SYS_memfd_create 319 #endif #define NUM_IDLE_THREADS 50 #define NUM_NORMAL_THREADS 150 #define SENDFILE_SIZE (1024 * 1024) // 1MB void *worker(void *arg) { long is_idle = (long)arg; if (is_idle) { struct sched_param param = {0}; int res = syscall(SYS_sched_setscheduler, syscall(SYS_gettid), SCHED_IDLE, ¶m); if (res < 0) { printf("[-] Failed to sched_setscheduler: %s\n", strerror(errno)); } else { printf("[+] sched_setscheduler successful.\n"); } } else { int res = setpriority(PRIO_PROCESS, syscall(SYS_gettid), -20); if (res < 0) { printf("[-] Failed to setpriority: %s\n", strerror(errno)); } else { printf("[+] setpriority successful.\n"); } } int fd_in = syscall(SYS_memfd_create, "in", 0); if (fd_in < 0) { char filename[64]; sprintf(filename, "/tmp/in_%ld", syscall(SYS_gettid)); fd_in = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666); } if (fd_in < 0) { printf("[-] Failed to create fd_in: %s\n", strerror(errno)); exit(1); } int res = ftruncate(fd_in, SENDFILE_SIZE); if (res < 0) { printf("[-] Failed to ftruncate fd_in: %s\n", strerror(errno)); exit(1); } int fd_out = syscall(SYS_memfd_create, "out", 0); if (fd_out < 0) { char filename[64]; sprintf(filename, "/tmp/out_%ld", syscall(SYS_gettid)); fd_out = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666); } if (fd_out < 0) { printf("[-] Failed to create fd_out: %s\n", strerror(errno)); exit(1); } while (1) { res = lseek(fd_in, 0, SEEK_SET); if (res < 0) { printf("[-] Failed to lseek fd_in: %s\n", strerror(errno)); exit(1); } res = lseek(fd_out, 0, SEEK_SET); if (res < 0) { printf("[-] Failed to lseek fd_out: %s\n", strerror(errno)); exit(1); } res = ftruncate(fd_out, 0); if (res < 0) { printf("[-] Failed to ftruncate fd_out: %s\n", strerror(errno)); exit(1); } ssize_t sres = sendfile(fd_out, fd_in, NULL, SENDFILE_SIZE); if (sres < 0) { printf("[-] Failed to sendfile: %s\n", strerror(errno)); exit(1); } } return NULL; } int main(void) { printf("[*] Starting reproducer...\n"); int fd = open("/proc/sys/kernel/panic_on_rcu_stall", O_WRONLY); if (fd >= 0) { int res = write(fd, "1\n", 2); if (res < 0) { printf("[-] Failed to write panic_on_rcu_stall: %s\n", strerror(errno)); } else { printf("[+] write panic_on_rcu_stall successful.\n"); } close(fd); } else { printf("[-] Failed to open panic_on_rcu_stall: %s\n", strerror(errno)); } pthread_t idle_threads[NUM_IDLE_THREADS]; pthread_t normal_threads[NUM_NORMAL_THREADS]; printf("[*] Creating idle threads...\n"); for (int i = 0; i < NUM_IDLE_THREADS; i++) { int res = pthread_create(&idle_threads[i], NULL, worker, (void *)1); if (res != 0) { printf("[-] Failed to pthread_create idle thread: %s\n", strerror(res)); exit(1); } } printf("[+] pthread_create idle threads successful.\n"); usleep(500000); printf("[*] Creating normal threads...\n"); for (int i = 0; i < NUM_NORMAL_THREADS; i++) { int res = pthread_create(&normal_threads[i], NULL, worker, (void *)0); if (res != 0) { printf("[-] Failed to pthread_create normal thread: %s\n", strerror(res)); exit(1); } } printf("[+] pthread_create normal threads successful.\n"); for (int i = 0; i < NUM_IDLE_THREADS; i++) { int res = pthread_join(idle_threads[i], NULL); if (res != 0) { printf("[-] Failed to pthread_join idle thread: %s\n", strerror(res)); exit(1); } } for (int i = 0; i < NUM_NORMAL_THREADS; i++) { int res = pthread_join(normal_threads[i], NULL); if (res != 0) { printf("[-] Failed to pthread_join normal thread: %s\n", strerror(res)); exit(1); } } return 0; }