// https://syzkaller.appspot.com/bug?id=af3a0728c8cbf6903ec2b0836441287cced00c1c // 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 #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 __thread int skip_segv; static __thread jmp_buf segv_env; static void segv_handler(int sig, siginfo_t* info, void* uctx) { uintptr_t addr = (uintptr_t)info->si_addr; const uintptr_t prog_start = 1 << 20; const uintptr_t prog_end = 100 << 20; if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { _longjmp(segv_env, 1); } doexit(sig); } static void install_segv_handler() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = segv_handler; sa.sa_flags = SA_NODEFER | SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGBUS, &sa, NULL); } #define NONFAILING(...) \ { \ __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ if (_setjmp(segv_env) == 0) { \ __VA_ARGS__; \ } \ __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ } 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 int collide; 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); if (collide && call % 2) break; 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[2] = {0xffffffffffffffff, 0xffffffffffffffff}; void execute_call(int call) { long res; switch (call) { case 0: NONFAILING(memcpy( (void*)0x20000980, "\x2f\x00\x7e\x57\x4d\x00\x03\x30\x80\x90\x22\xcf\xde\x26\x55\x5d\xc9" "\xec\xfe\x19\x74\x40\x6e\xda\xd3\x83\x64\x78\x2d\x63\xb6\x61\x28\x54" "\xb9\xe4\x9d\xbd\xca\xef\x71\x81\x97\xe3\x7e\x87\x0a\x30\x8b\x1e\x3a" "\x79\x8f\xa7\x88\xa4\x6d\x30\x25\xef\x93\x3e\x51\x82\x8a\xb6\x75\x06" "\x4e\x2a\xdb\xe9\x12\x64\x23\xb4\xa7\x3d\x68\xfb\xe9\x9c\x6d\xb2\xf1" "\x60\xd4\x9c\xb6\xcc\xe7\x6c\x27\x28\x9a\x4f\x9d\x19\x73\x54\xaa\xa5" "\x86\x0d\x23\x83\xdf\x87\x52\x6b\xaa\x18\x4d\x90\xbb\x77\x29\x36\x64" "\x17\xbc\x33\xd7\x65\xe9\xbc\x2f\x88\x2a\x13\xf3\xa9\xc1\xf6\x06\x60" "\xbd\x4f\xd2\xfa\x31\xd2\xc0\xa7\x75\x24\x22\x89\xbc\xe0\x62\xd1\x0d" "\x24\xde\xd5\x40\x69\x18\xa6\x6b\x2c\x75\xc4\x3f\xe1\xff\x45\x8a\xe5" "\xcd\x9f\xec\x63\x03\x9b\xa5\xa7\xb6\x6a\x60\xed\xe5\xcc\xda\xbc\x7e" "\xe7\x76\x60\xef\x23\x58\xcc\xdf\xf0\x22\x26\x02\x13\x84\xb0\xc2\x35" "\xf1\x14\xed\x9a\xde\x92\x76\x7a\xec\xc2\x56\xac\xde\xb6\x10\xdf\x42" "\xe7\x16\x9f\x24\x03\x57\xf7\x35\xae\x5f\xe2\x90\x17\xe5\x1e\x27\x25" "\x2f\x48\xb9\x5b\xfb\xbb\x3a\x86\x55\x35\x29\x8b\xdc\x36\xd7\x1d\xb6" "\x35\xf4\x1c\x57\x77\x1d\xb7\x7a\xea\xff\x88\x3f\xeb\x3d\xc3\xcc\x24" "\xbd\x3c\x03\x6e\x39\x6a\xd3\xaf\x37\x94\x50\x58\x83\x9e\x81\x22\x70" "\xbc\x40\x90\x1f\xa6\x54\xe7\xcc\x32\x92\xa8\x2f\xc8\x0c\x37\x4d\xc0" "\x71\x42\xa1\xc2\xe9\xd3\xe2\x52\x8e\x4f\xda\xc3\x2b\xca\xef\xe9\x10" "\xeb\xd3\xb9\x48\xa3\xbf\xeb\xef\x5f\xa8\xd8\x24\x73\xc7\xfb\xf3\xec" "\x76\x3a\x1b\x61\x3d\xd7\x47\xd5\x29\xea\x70\xef\x02\x98\xff\xf5\x66" "\x16\x30\xb9\x9a\x79\xec\x82\x69\xaf\x9b\xe1\x78\xae\xca\x17\xfe\xfb" "\x14\xfd\x3d\x00\x97\x5a\x99\x9d\x79\xba\x89\x4d\xba\xe4\xc1\xa6\xef" "\x5f\x1e\x35\xaf\x57\xd8\x28\x78\x22\x6d\x07\xe6\x3a\x3f\x45\x96\x7e" "\x0e\xe8\x59\xbb\x6e\x0f\x3c\x66\xe6\x8c\x44\x52\x08\xbb\x32\xbb\x23" "\x42\x94\x8a\xa3\xf4\x13\xea\x98\x1d\xcf\x59\xc2\x73\x23\xf4\x94\x5e" "\x32\x5b\xa0\xe6\x9e\x43\x6e\x55\x43\x6a\x93\x24\xf5\xa4\x58\xc5\xac" "\xb6\x01\x10\x4c\xf2\xfc\x7a\xdc\x67\xa0\x66\x2f\x54\x99\xdc\x4f\x72" "\xfd\x4d\x8f\x4f\x68\xad\x5d\xa5\x2e\xd8\xc9\x29\xf7\x51\xf2\x8d\x9d" "\x63\xfa\x34\xb3\x5d\x4f\xcf\xe8\xc5\x48\xeb\x35\xe3\xa1\xd0\x8c\x07" "\x7e\x7d\x7e\xa6\x1e\x71\x6e\xaa\x6f\xc3\x42\x87\xd5\x86\xdc\xc0", 526)); res = syscall(__NR_openat, -1, 0x20000980, 0, 0); if (res != -1) r[0] = res; break; case 1: NONFAILING(memcpy((void*)0x20000000, "/dev/ptmx", 10)); syscall(__NR_openat, 0xffffffffffffff9c, 0x20000000, 0, 0); break; case 2: syscall(__NR_mprotect, 0x20000000, 0x800000, 4); break; case 3: NONFAILING(memcpy((void*)0x20000000, "\x7a\x31\x00\x00\x00", 5)); res = syscall(__NR_openat, r[0], 0x20000000, 0x200002, 0); if (res != -1) r[1] = res; break; case 4: syscall(__NR_read, r[1], 0x20000040, 0xe2); break; } } void execute_one() { execute(5); collide = 1; execute(5); } int main() { syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0); install_segv_handler(); for (;;) { loop(); } }