// https://syzkaller.appspot.com/bug?id=001410d947fa7742a85647e596c45661118c7d24 // autogenerated by syzkaller (http://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include __attribute__((noreturn)) static void doexit(int status) { volatile unsigned i; syscall(__NR_exit_group, status); for (i = 0;; i++) { } } #include #include #include #include #include const int kFailStatus = 67; const int kRetryStatus = 69; static void fail(const char* msg, ...) { int e = errno; va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, " (errno %d)\n", e); doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus); } static uint64_t current_time_ms() { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) fail("clock_gettime failed"); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; } static void execute_one(); extern unsigned long long procid; static void loop() { int iter; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) fail("clone failed"); if (pid == 0) { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); execute_one(); int fd; for (fd = 3; fd < 30; fd++) close(fd); doexit(0); } int status = 0; uint64_t start = current_time_ms(); for (;;) { int res = waitpid(-1, &status, __WALL | WNOHANG); if (res == pid) { break; } usleep(1000); if (current_time_ms() - start < 5 * 1000) continue; kill(-pid, SIGKILL); kill(pid, SIGKILL); while (waitpid(-1, &status, __WALL) != pid) { } break; } } } struct thread_t { int created, running, call; pthread_t th; }; static struct thread_t threads[16]; static void execute_call(int call); static int running; static void* thr(void* arg) { struct thread_t* th = (struct thread_t*)arg; for (;;) { while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0); execute_call(th->call); __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); __atomic_store_n(&th->running, 0, __ATOMIC_RELEASE); syscall(SYS_futex, &th->running, FUTEX_WAKE); } return 0; } static void execute(int num_calls) { int call, thread; running = 0; for (call = 0; call < num_calls; call++) { for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) { struct thread_t* th = &threads[thread]; if (!th->created) { th->created = 1; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128 << 10); pthread_create(&th->th, &attr, thr, th); } if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) { th->call = call; __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); __atomic_store_n(&th->running, 1, __ATOMIC_RELEASE); syscall(SYS_futex, &th->running, FUTEX_WAKE); struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 20 * 1000 * 1000; syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts); if (__atomic_load_n(&running, __ATOMIC_RELAXED)) usleep((call == num_calls - 1) ? 10000 : 1000); break; } } } } uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; void execute_call(int call) { long res; switch (call) { case 0: memcpy((void*)0x20000080, "/dev/snapshot", 14); res = syscall(__NR_openat, 0xffffffffffffff9c, 0x20000080, 0x50200, 0); if (res != -1) r[0] = res; break; case 1: *(uint32_t*)0x20001540 = 0xdd; memcpy((void*)0x20001544, "\xa3\x38\x1e\xcd\x74\xfc\x88\x73\xd6\x2e\x13\xdc\xd5\x43\xbd\x39" "\xe6\x3b\x47\x53\x10\xae\x26\x5e\xcd\x8f\x57\x5a\x64\x46\x6b\xba" "\xa9\x78\xab\xfe\x54\xcd\x69\x55\x11\xf1\x78\x68\xac\xa8\xf0\x42" "\xe3\x02\x73\x20\x5d\x32\x17\x4b\xc9\x0e\x8f\xdd\x8c\x43\xd5\x80" "\x6f\x67\x82\x16\x83\x7e\xc9\x68\xa2\x30\x42\xf0\x7e\x8d\x78\x23" "\xe5\xeb\x05\xa8\x9a\xc7\x7f\xb0\x1b\xc1\xf9\xa4\xd8\xaa\xe3\x01" "\xb9\xbc\x38\x55\xb9\x1f\xe8\x19\x06\xe5\xf1\xc1\xb8\xce\x9b\x83" "\xd3\x3d\x39\x91\x7c\x95\x4d\x11\xa2\xcb\xf7\x82\x37\x47\x52\xd0" "\x40\xc3\x9b\x73\x21\xe7\x92\xd0\x1c\x1a\xb7\x5d\xfb\xa3\xf1\xee" "\xca\xeb\xe4\x16\xdb\xef\xa1\xca\xdd\x55\x91\x30\x4c\xc2\x73\xcd" "\xc0\x7d\x36\x51\x50\x4e\xcc\x52\x7f\x58\x86\x53\x3e\xe2\x6f\x26" "\x3e\x78\xe8\x22\x3a\x6c\xdb\x2a\xfd\x28\xbd\x6c\x1a\x00\xad\xc5" "\x80\xe1\x19\x35\xae\xba\x5c\x3b\xfb\xe3\x2c\x43\x18\x55\x76\xf8" "\xab\x82\x60\x1d\xfa\xc9\x4a\x8d\xd9\x95\xea\x23\xb8", 221); syscall(__NR_ioctl, r[0], 0x4004ae8b, 0x20001540); break; case 2: res = syscall(__NR_pipe2, 0x20000500, 0); if (res != -1) { r[1] = *(uint32_t*)0x20000500; r[2] = *(uint32_t*)0x20000504; } break; case 3: *(uint32_t*)0x20000040 = 0x148; *(uint8_t*)0x20000044 = 0x4d; *(uint16_t*)0x20000045 = 0; syscall(__NR_write, r[2], 0x20000040, 7); break; case 4: memcpy((void*)0x20000140, "./file0", 8); syscall(__NR_mkdir, 0x20000140, 0); break; case 5: memcpy((void*)0x200000c0, "./file0", 8); memcpy((void*)0x20000340, "9p", 3); memcpy((void*)0x200003c0, "trans=fd,", 9); memcpy((void*)0x200003c9, "rfdno", 5); *(uint8_t*)0x200003ce = 0x3d; sprintf((char*)0x200003cf, "0x%016llx", (long long)r[1]); *(uint8_t*)0x200003e1 = 0x2c; memcpy((void*)0x200003e2, "wfdno", 5); *(uint8_t*)0x200003e7 = 0x3d; sprintf((char*)0x200003e8, "0x%016llx", (long long)r[2]); *(uint8_t*)0x200003fa = 0x2c; memcpy((void*)0x200003fb, "version=9p2000.u", 16); *(uint8_t*)0x2000040b = 0x2c; *(uint8_t*)0x2000040c = 0; syscall(__NR_mount, 0, 0x200000c0, 0x20000340, 0, 0x200003c0); break; case 6: res = syscall(__NR_pipe2, 0x20000000, 0x80800); if (res != -1) r[3] = *(uint32_t*)0x20000000; break; case 7: *(uint8_t*)0x200001c0 = 2; *(uint8_t*)0x200001c1 = 1; *(uint16_t*)0x200001c2 = 1; *(uint16_t*)0x200001c4 = 7; *(uint16_t*)0x200001c6 = 7; syscall(__NR_ioctl, r[0], 0x5602, 0x200001c0); break; case 8: syscall(__NR_read, r[3], 0x20000540, 0x1000); break; case 9: *(uint32_t*)0x20000480 = 0x2a; *(uint8_t*)0x20000484 = 0x29; *(uint16_t*)0x20000485 = 1; *(uint32_t*)0x20000487 = 0; *(uint8_t*)0x2000048b = 0; *(uint32_t*)0x2000048c = 0; *(uint64_t*)0x20000490 = 0; *(uint64_t*)0x20000498 = 0; *(uint8_t*)0x200004a0 = 0; *(uint16_t*)0x200004a1 = 7; memcpy((void*)0x200004a3, "./file0", 7); syscall(__NR_write, r[2], 0x20000480, 0x2a); break; case 10: *(uint32_t*)0x20000280 = 0x5b; *(uint8_t*)0x20000284 = 0x29; *(uint16_t*)0x20000285 = 1; *(uint32_t*)0x20000287 = 0; *(uint8_t*)0x2000028b = 0; *(uint32_t*)0x2000028c = 0; *(uint64_t*)0x20000290 = 0; *(uint64_t*)0x20000298 = 0; *(uint8_t*)0x200002a0 = 0; *(uint16_t*)0x200002a1 = 0xd; memcpy((void*)0x200002a3, "./file0/file0", 13); *(uint8_t*)0x200002b0 = 0; *(uint32_t*)0x200002b1 = 0; *(uint64_t*)0x200002b5 = 0; *(uint64_t*)0x200002bd = 0xfffffffffffffff8; *(uint8_t*)0x200002c5 = 0; *(uint16_t*)0x200002c6 = 0x13; memcpy((void*)0x200002c8, "./file0/file0/file0", 19); syscall(__NR_write, r[2], 0x20000280, 0x5b); break; case 11: memcpy((void*)0x20000300, "./file0", 8); memcpy((void*)0x20000380, "9p", 3); memcpy((void*)0x20000200, "trans=fd,", 9); memcpy((void*)0x20000209, "rfdno", 5); *(uint8_t*)0x2000020e = 0x3d; sprintf((char*)0x2000020f, "0x%016llx", (long long)r[2]); *(uint8_t*)0x20000221 = 0x2c; memcpy((void*)0x20000222, "wfdno", 5); *(uint8_t*)0x20000227 = 0x3d; sprintf((char*)0x20000228, "0x%016llx", (long long)r[2]); *(uint8_t*)0x2000023a = 0x2c; *(uint8_t*)0x2000023b = 0; syscall(__NR_mount, 0, 0x20000300, 0x20000380, 0x800000, 0x20000200); break; case 12: memcpy((void*)0x20000100, "./file0", 8); memcpy((void*)0x20000180, "osx.", 4); memcpy((void*)0x20000184, "version=9p2000.u", 16); syscall(__NR_removexattr, 0x20000100, 0x20000180); break; } } void execute_one() { execute(13); } int main() { syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0); for (;;) { loop(); } }