// https://syzkaller.appspot.com/bug?id=d72d645c2507178b6052a8add5abf043d1ce625a // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } static void sleep_ms(uint64_t ms) { usleep(ms * 1000); } static uint64_t current_time_ms(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) exit(1); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; } static void thread_start(void* (*fn)(void*), void* arg) { pthread_t th; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128 << 10); int i = 0; for (; i < 100; i++) { if (pthread_create(&th, &attr, fn, arg) == 0) { pthread_attr_destroy(&attr); return; } if (errno == EAGAIN) { usleep(50); continue; } break; } exit(1); } typedef struct { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static void sandbox_common() { struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = 128 << 20; setrlimit(RLIMIT_AS, &rlim); rlim.rlim_cur = rlim.rlim_max = 8 << 20; setrlimit(RLIMIT_MEMLOCK, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_FSIZE, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max = 0; setrlimit(RLIMIT_CORE, &rlim); rlim.rlim_cur = rlim.rlim_max = 256; setrlimit(RLIMIT_NOFILE, &rlim); } static void loop(); static int do_sandbox_none(void) { sandbox_common(); loop(); return 0; } struct thread_t { int created, call; event_t ready, done; }; 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 (;;) { event_wait(&th->ready); event_reset(&th->ready); execute_call(th->call); __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); event_set(&th->done); } return 0; } static void execute_one(void) { int i, call, thread; int collide = 0; again: for (call = 0; call < 3; call++) { for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) { struct thread_t* th = &threads[thread]; if (!th->created) { th->created = 1; event_init(&th->ready); event_init(&th->done); event_set(&th->done); thread_start(thr, th); } if (!event_isset(&th->done)) continue; event_reset(&th->done); th->call = call; __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); event_set(&th->ready); if (collide && (call % 2) == 0) break; event_timedwait(&th->done, 50); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); if (!collide) { collide = 1; goto again; } } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter = 0; for (;; iter++) { int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { execute_one(); exit(0); } int status = 0; uint64_t start = current_time_ms(); for (;;) { if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) break; sleep_ms(1); if (current_time_ms() - start < 5000) { continue; } kill_and_wait(pid, &status); break; } } } uint64_t r[1] = {0xffffffffffffffff}; void execute_call(int call) { intptr_t res = 0; switch (call) { case 0: memcpy((void*)0x20000000, "/dev/pf\000", 8); res = syscall(SYS_openat, 0xffffffffffffff9cul, 0x20000000ul, 2ul, 0ul); if (res != -1) r[0] = res; break; case 1: memcpy( (void*)0x20000980, "\x74\x0d\xb3\x7a\x34\xff\x64\x74\xa6\x9b\x9d\x4b\xb1\xf3\xf7\x94\x50" "\xd4\x10\x4f\x99\xf9\xc8\xbb\x8c\x36\x4c\x73\x82\x6f\xe7\xa4\x83\xf3" "\xb6\x5f\xf0\x38\x0d\xda\xe2\x8f\x47\x9d\xa6\x5e\x1e\x68\xb5\xc8\x9f" "\x8c\xb7\xaa\x7d\x9f\x2a\x69\xec\x43\x70\x45\xd1\xb3\xac\x68\x2c\x2c" "\xe1\x15\x97\xf1\xa7\x4c\x59\x7a\xb7\x0a\xc2\x06\xcb\x6a\x9a\x85\x2b" "\xa4\x65\x63\x3a\xd6\x46\x8a\xf0\x24\x14\x23\x3e\x32\xd3\x65\xcf\xb7" "\x4b\x74\xce\xca\x1a\xb0\x0f\xcf\x4b\x85\x44\x45\x31\x3b\x70\xca\xb5" "\xc8\xf6\x90\xcc\xfb\xeb\xf8\x45\xf1\xe6\xee\xce\xb1\x1a\xce\xe4\xcc" "\xc8\xf4\x2a\xc2\x42\x97\x1b\x6e\x2d\x84\x72\x2d\x32\xe9\x5e\x32\xb0" "\xd9\x2a\xfc\x6e\x1a\xd5\x57\xc1\x46\xff\x16\xeb\x51\xf3\xeb\xd9\x9f" "\x53\xeb\xcc\x93\x46\x43\x83\x92\x2e\xa7\x82\x49\x3f\xba\x04\xce\x46" "\xd7\x0c\x58\xdb\x55\x18\x23\x8d\xb7\xe0\xf1\x11\x9a\x93\x82\x62\x8d" "\x41\x3b\x12\xab\x7f\xb4\x52\x93\xc8\xc8\x0b\x5e\xe6\x6f\xf6\x2f\xf3" "\x6c\xa9\x7e\x74\x72\x3e\xb5\xd9\xba\xc3\xc8\x36\x67\x61\x6a\xa6\x9e" "\x93\x8d\x26\x14\xbe\x26\xf9\x24\xf3\xdb\x72\x83\x2f\xc3\x4b\xc1\x9a" "\x81\x90\xd1\x63\xb2\xda\x8e\xe2\x4c\x31\xea\x65\x8f\xc2\x59\xa7\xc3" "\xfe\x2b\x71\xe4\xb3\xd9\xe3\x1b\x13\x48\x52\xce\x1d\xc0\x0e\xae\xd2" "\x08\x67\x9f\x62\x81\x02\x91\x81\x41\x94\x38\x2f\x4c\xfe\x74\x97\xeb" "\xb0\x98\x31\xa2\x2f\xd9\x66\xf8\x3e\x86\xda\x87\x9a\x05\x08\x24\x14" "\x1e\xef\xd6\x81\x32\x17\xe9\xb4\xb8\x30\xa6\x76\xd1\x6a\xe8\xa7\x62" "\x9d\x7d\xad\xf6\x37\xfa\x39\x23\xfa\xa1\x20\x45\x09\x4b\x57\x33\x26" "\x17\x4f\xec\xdf\xbc\x6d\xc5\xab\x8f\xe3\x30\x23\x5b\x78\x8d\x84\x0e" "\x70\x28\xf9\x46\x0d\xf5\x84\x06\xba\x05\xe2\x82\x32\x9a\x74\x78\xb0" "\x1f\xc8\x9b\x03\x8e\x81\x18\xe6\x74\xcc\x8d\x5e\xc8\x13\xab\x58\x36" "\x1a\xd5\x4d\x61\x4d\xec\x46\xe2\x7a\x8c\xc0\x0f\x50\x18\x13\x0b\xe0" "\xe5\xaf\x14\xc4\x7b\x81\x22\x59\x73\x84\x0b\x34\xd9\x7c\x55\x33\x25" "\xd6\x99\xdc\x5e\xc1\x1d\x9e\x64\xd9\x3f\x4f\x9e\xd2\xae\x0e\x32\x46" "\x36\x23\xd3\x1c\x14\x5d\xd8\xeb\x55\xa5\x53\x18\xb0\xec\x07\x8d\x50" "\xb7\x36\xa9\xfb\xc5\x25\xfb\xfe\xb4\xe2\x45\xc9\x34\x09\x7c\x96\x1f" "\xaf\x54\xc7\x37\x89\x4e\x11\xb4\xbb\x27\x25\xaf\x5a\x9a\xe8\x8a\x2a" "\xa9\x0a\xe1\x18\x29\xf9\xfc\x62\x41\xc2\xc3\x11\xdc\xdb\x04\x32\x6c" "\x22\xae\x95\x86\x78\x81\x6d\x52\x62\x25\x86\xba\x23\xbe\x5a\x85\xf3" "\x18\x9a\xfc\x26\x02\xf3\x64\x6a\x42\x69\x42\xdf\xa0\x25\x8b\x25\x41" "\xd3\xa3\x32\x13\x4d\x03\x6f\x5d\x8a\x23\xf9\xe8\x3e\x29\xd8\x22\xc5" "\xf5\xee\x07\x59\xda\xa0\x0d\x74\xb3\x8b\x41\x6b\x64\x41\xb8\x6a\x05" "\x15\x23\x21\x2a\x29\xb7\xd7\xeb\xf9\x0f\x04\xff\xea\xdf\x1e\x63\xdb" "\x62\x01\xf2\x53\x91\xd4\x46\xea\x16\xf2\x35\x71\x1a\x19\x9b\xf1\x2c" "\xef\xd3\xdc\x23\x2b\x30\xf0\x35\x93\x33\x67\x24\xd9\xba\x69\xc6\x92" "\xe8\x53\xb7\x41\xe4\xb3\x54\xa2\x6e\x6f\xce\x82\x0e\xea\x44\xf2\x18" "\xda\x88\xb5\xdf\x74\xd4\x52\xcc\x92\xdc\xf8\xba\x3f\xdd\xaa\x9c\xff" "\x82\x74\x4f\x04\x6c\x10\xf2\x12\x4d\x15\x11\xeb\xb4\xb5\x7c\x4e\xe2" "\x26\x70\x9f\x38\xd9\x9e\xbf\x54\x2c\xd9\x53\xc3\x80\x4d\x4b\x1f\x4e" "\xd5\xe5\x68\x27\xe3\x05\x63\xd0\x9f\x49\x09\x04\x66\xc8\x3f\xda\x2e" "\x31\x2f\x69\xc5\x03\x02\x2c\x89\x06\x24\x8a\x20\xe1\xa5\x16\xca\xcf" "\xe8\xd3\xa4\xd7\x7f\x37\x52\x2e\xe7\x12\x15\xf6\xa3\x5e\x05\xea\xb0" "\xf5\x06\x16\x0d\x37\xa0\x39\x62\xa8\xa6\x00\xc5\x02\x45\x66\x7c\xd0" "\x6d\x2d\x9c\x0f\xc0\xac\x43\x3c\x1d\x45\x90\x09\xe9\xe9\x34\xe0\x88" "\x85\x45\x3b\x4c\x67\x69\x93\x07\xe5\xe4\x88\x13\xfc\x5f\xd1\x06\x04" "\xa8\x6a\x2d\xc5\xef\x0e\x51\x4a\xd9\x39\x98\x35\x4c\x4a\xa4\xff\x97" "\x7f\x88\x7c\xed\xd7\x15\x3a\xd7\xbe\xf4\xc9\x97\x7b\xcb\x50\xec\xe0" "\xec\xef\x12\xfb\x35\x4d\x23\x3c\x38\xfe\x4c\xdc\xec\xf4\x12\x1c\x1c" "\xdf\xa4\x06\x6e\x5c\x13\x1c\x67\xae\x52\xb6\xc8\xfd\x16\x50\x02\x17" "\xb5\x45\x1c\x05\x9c\xe4\xa3\x64\xab\x25\xa1\x07\x79\x81\xb8\xfd\x72" "\x2f\x80\x55\x1e\xb8\x64\x5f\x3c\x33\x07\xcb\x52\xd4\x71\xeb\x0b\xf5" "\x6b\x4f\x4c\xf6\xc7\xbe\x3a\xef\xa8\x77\x94\xe3\xa0\xfe\xc0\xc6\x24" "\x2f\xc3\x3c\x6e\x10\x1a\x4a\x24\x37\x7b\x83\x5a\x57\xbd\x8a\xa0\xd4" "\xfa\xbc\x98\x4a\xa6\x8c\x56\xfb\x5d\xa5\x48\x38\x03\x04\xa2\x5b\x0a" "\x4f\xec\x1c\x2f\x1c\x0a\xc1\x1a\xcd\xba\x5e\x61\x34\xa8\x47\x91\x2d" "\x43\x59\xeb\x23\x2d\xc5\x88\x95\x6a\x14\xc2\xba\x23\x2f\x64\x43\x69" "\xaf\x4a\x15\xdd\x91\x91\x61\xf4\x9d\xb2\x7c\xc1\x3a\xb6\xf2\x78\x17" "\xbc\x2f\xb6\x1f", 1024); memcpy((void*)0x20000d80, "\xa2\x47\xfb\x1e\xf5\xdc\x52\x72\xca\x65\x31\x17\x5f\x8a\x91\x43" "\xd5\x12\xdf\xfd\xda\x26\x9c\x9b\x22\xc5\x3d\xee\x0c\x91\x76\x4f", 32); *(uint32_t*)0x20000da0 = 0; *(uint8_t*)0x20000da4 = 0; *(uint64_t*)0x20000da8 = 0; *(uint64_t*)0x20000db0 = 0; *(uint64_t*)0x20000db8 = 0; *(uint64_t*)0x20000dc0 = 0; *(uint64_t*)0x20000dc8 = 0; *(uint64_t*)0x20000dd0 = 0; *(uint64_t*)0x20000dd8 = 0; *(uint64_t*)0x20000de0 = 0; *(uint32_t*)0x20000de8 = 0; syscall(SYS_ioctl, -1, 0xc450443dul, 0x20000980ul); break; case 2: syscall(SYS_ioctl, r[0], 0xcbe04404ul, 0x20000040ul); break; } } int main(void) { syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); do_sandbox_none(); return 0; }