// https://syzkaller.appspot.com/bug?id=94a5bd822dcdb0024919441e2a8c7720380df06f #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include pthread_barrier_t barrier; void *thread_bc(void *arg) { char target[256]; for (int i = 0; i < 10000; i++) { char buf[256]; sprintf(buf, "lower/b_%d", i); pthread_barrier_wait(&barrier); readlink(buf, target, sizeof(target)); } return NULL; } int main() { setvbuf(stdout, NULL, _IONBF, 0); printf("[*] Starting reproducer...\n"); if (mkdir("lower", 0777) < 0 && errno != EEXIST) { printf("[-] Failed to mkdir lower: %s\n", strerror(errno)); exit(1); } if (mkdir("upper", 0777) < 0 && errno != EEXIST) { printf("[-] Failed to mkdir upper: %s\n", strerror(errno)); exit(1); } if (mkdir("work", 0777) < 0 && errno != EEXIST) { printf("[-] Failed to mkdir work: %s\n", strerror(errno)); exit(1); } if (mkdir("merged", 0777) < 0 && errno != EEXIST) { printf("[-] Failed to mkdir merged: %s\n", strerror(errno)); exit(1); } printf("[+] Directories created successfully.\n"); if (mount("overlay", "merged", "overlay", 0, "lowerdir=lower,upperdir=upper,workdir=work") != 0) { printf("[-] Failed to mount overlay: %s\n", strerror(errno)); exit(1); } printf("[+] Overlayfs mounted successfully.\n"); // Phase 1: Record DCACHE_PAR_LOOKUP -> lower_dir_lock printf("[*] Phase 1: Recording DCACHE_PAR_LOOKUP -> lower_dir_lock...\n"); for (int i = 0; i < 100; i++) { char buf[256]; sprintf(buf, "merged/a_%d", i); int fd = open(buf, O_CREAT | O_RDWR, 0666); if (fd >= 0) close(fd); } printf("[+] Phase 1 completed.\n"); // Phase 2: Record lower_dir_lock -> DCACHE_PAR_LOOKUP printf("[*] Phase 2: Recording lower_dir_lock -> DCACHE_PAR_LOOKUP...\n"); if (pthread_barrier_init(&barrier, NULL, 4) != 0) { printf("[-] Failed to init barrier: %s\n", strerror(errno)); exit(1); } pthread_t tb, tc, td, te; if (pthread_create(&tb, NULL, thread_bc, NULL) != 0 || pthread_create(&tc, NULL, thread_bc, NULL) != 0 || pthread_create(&td, NULL, thread_bc, NULL) != 0 || pthread_create(&te, NULL, thread_bc, NULL) != 0) { printf("[-] Failed to create threads: %s\n", strerror(errno)); exit(1); } pthread_join(tb, NULL); pthread_join(tc, NULL); pthread_join(td, NULL); pthread_join(te, NULL); printf("[+] Phase 2 completed.\n"); if (umount("merged") != 0) { printf("[-] Failed to umount merged: %s\n", strerror(errno)); exit(1); } printf("[+] Overlayfs unmounted successfully.\n"); return 0; }