// https://syzkaller.appspot.com/bug?id=42c3998fce1a032008cec46ed09481c3f8fc0e84 #define _GNU_SOURCE #include #include #include #include #include #include #include #include volatile int stop = 0; static void *thread1(void *arg) { while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) { int fd = open("test_fifo", O_RDONLY); if (fd >= 0) { if (close(fd) < 0) { // Ignore close errors in threads to avoid spamming } } } return NULL; } static void *thread2(void *arg) { while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) { int fd = open("test_fifo", O_RDONLY | O_NONBLOCK); if (fd >= 0) { if (close(fd) < 0) { // Ignore close errors in threads } } } return NULL; } int main(void) { int res; // Clean up any existing fifo unlink("test_fifo"); res = mkfifo("test_fifo", 0666); if (res < 0) { printf("[-] Failed to mkfifo: %s\n", strerror(errno)); exit(1); } printf("[+] mkfifo successful.\n"); pthread_t t1[4], t2[4]; for (int i = 0; i < 4; i++) { res = pthread_create(&t1[i], NULL, thread1, NULL); if (res != 0) { printf("[-] Failed to pthread_create thread1: %s\n", strerror(res)); exit(1); } res = pthread_create(&t2[i], NULL, thread2, NULL); if (res != 0) { printf("[-] Failed to pthread_create thread2: %s\n", strerror(res)); exit(1); } } printf("[+] Threads created successfully.\n"); // Let the threads race for a few seconds to trigger KCSAN sleep(5); printf("[+] Sleep finished, stopping threads.\n"); __atomic_store_n(&stop, 1, __ATOMIC_RELAXED); // Wake up blocked readers and keep writer open so new readers don't block int wfd = open("test_fifo", O_RDWR); if (wfd < 0) { printf("[-] Failed to open test_fifo with O_RDWR: %s\n", strerror(errno)); exit(1); } printf("[+] open test_fifo with O_RDWR successful.\n"); for (int i = 0; i < 4; i++) { res = pthread_join(t1[i], NULL); if (res != 0) { printf("[-] Failed to pthread_join thread1: %s\n", strerror(res)); exit(1); } res = pthread_join(t2[i], NULL); if (res != 0) { printf("[-] Failed to pthread_join thread2: %s\n", strerror(res)); exit(1); } } printf("[+] Threads joined successfully.\n"); res = close(wfd); if (res < 0) { printf("[-] Failed to close wfd: %s\n", strerror(errno)); exit(1); } printf("[+] close wfd successful.\n"); res = unlink("test_fifo"); if (res < 0) { printf("[-] Failed to unlink test_fifo: %s\n", strerror(errno)); exit(1); } printf("[+] unlink test_fifo successful.\n"); // Allow time for KCSAN to report sleep(1); printf("[+] Reproducer finished.\n"); return 0; }