xref: /freebsd/tools/test/stress2/misc/syzkaller47.sh (revision cbc3ecb7)
1cbc3ecb7SPeter Holm#!/bin/sh
2cbc3ecb7SPeter Holm
3cbc3ecb7SPeter Holm# panic: ASan: Invalid access, 32-byte read at 0xfffffe01f76145a0, UseAfterScope(f8)
4cbc3ecb7SPeter Holm# cpuid = 3
5cbc3ecb7SPeter Holm# time = 1635158022
6cbc3ecb7SPeter Holm# KDB: stack backtrace:
7cbc3ecb7SPeter Holm# db_trace_self_wrapper() at db_trace_self_wrapper+0xa5/frame 0xfffffe01f7614170
8cbc3ecb7SPeter Holm# kdb_backtrace() at kdb_backtrace+0xc9/frame 0xfffffe01f76142d0
9cbc3ecb7SPeter Holm# vpanic() at vpanic+0x248/frame 0xfffffe01f76143b0
10cbc3ecb7SPeter Holm# panic() at panic+0xb5/frame 0xfffffe01f7614480
11cbc3ecb7SPeter Holm# __asan_storeN() at __asan_storeN/frame 0xfffffe01f7614550
12cbc3ecb7SPeter Holm# smp_masked_invlpg_range() at smp_masked_invlpg_range+0xb2/frame 0xfffffe01f7614630
13cbc3ecb7SPeter Holm# pmap_invalidate_range() at pmap_invalidate_range+0x22b/frame 0xfffffe01f7614730
14cbc3ecb7SPeter Holm# vm_thread_stack_create() at vm_thread_stack_create+0xf5/frame 0xfffffe01f7614910
15cbc3ecb7SPeter Holm# kstack_import() at kstack_import+0xcache_alloc() at cache_alloc+0x556/frame 0xfffffe01f7614a10
16cbc3ecb7SPeter Holm# cache_alloc_retry() at cache_alloc_retry+0x30/frame 0xfffffe01f7614a80
17cbc3ecb7SPeter Holm# vm_thread_new() at vm_thread_new+0x61/frame 0xfffffe01f7614ab0
18cbc3ecb7SPeter Holm# thread_alloc() at thread_alloc+0x5f/frame 0xfffffe01f7614af0
19cbc3ecb7SPeter Holm# thread_create() at thread_create+0x1b3/frame 0xfffffe01f7614bf0
20cbc3ecb7SPeter Holm# sys_thr_new() at sys_thr_new+0x15a/framd30
21cbc3ecb7SPeter Holm# amd64_syscall() at amd64_syscall+0x31e/frame 0xfffffe01f7614f30
22cbc3ecb7SPeter Holm# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01f7614f30
23cbc3ecb7SPeter Holm# --- syscall (0, FreeBSD ELF64, nosys), rip = 0x8003afafa, rsp = 0x7fffdfffdf58, rbp = 0x7fffdfffdf70 ---
24cbc3ecb7SPeter Holm# KDB: enter: panic
25cbc3ecb7SPeter Holm# [ thread pid 69407 tid 100937 ]
26cbc3ecb7SPeter Holm# Stopped at      kdb_enter+0x37: movq    $0,0x2638c4e(%rip)
27cbc3ecb7SPeter Holm# db> x/s version
28cbc3ecb7SPeter Holm# version:  FreeBSD 14.0-CURRENT #0 main-n250242-eab5358b9080-dirty: Mon Oct 25 11:32:45 CEST 2021
29cbc3ecb7SPeter Holm# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO-KASAN
30cbc3ecb7SPeter Holm# db>
31cbc3ecb7SPeter Holm
32cbc3ecb7SPeter Holm[ `uname -p` != "amd64" ] && exit 0
33cbc3ecb7SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
34cbc3ecb7SPeter Holm[ "`sysctl -in kern.features.kasan`" != "1" ] && exit 0
35cbc3ecb7SPeter Holm
36cbc3ecb7SPeter Holm. ../default.cfg
37cbc3ecb7SPeter Holmcat > /tmp/syzkaller47.c <<EOF
38cbc3ecb7SPeter Holm// https://syzkaller.appspot.com/bug?id=5676c1c4b457596c1a8782e4a8533f4e9ff2aa0e
39cbc3ecb7SPeter Holm// autogenerated by syzkaller (https://github.com/google/syzkaller)
40cbc3ecb7SPeter Holm// Reported-by: syzbot+a5898c11651b423b501f@syzkaller.appspotmail.com
41cbc3ecb7SPeter Holm
42cbc3ecb7SPeter Holm#define _GNU_SOURCE
43cbc3ecb7SPeter Holm
44cbc3ecb7SPeter Holm#include <sys/types.h>
45cbc3ecb7SPeter Holm
46cbc3ecb7SPeter Holm#include <dirent.h>
47cbc3ecb7SPeter Holm#include <errno.h>
48cbc3ecb7SPeter Holm#include <pthread.h>
49cbc3ecb7SPeter Holm#include <pwd.h>
50cbc3ecb7SPeter Holm#include <setjmp.h>
51cbc3ecb7SPeter Holm#include <signal.h>
52cbc3ecb7SPeter Holm#include <stdarg.h>
53cbc3ecb7SPeter Holm#include <stdbool.h>
54cbc3ecb7SPeter Holm#include <stdint.h>
55cbc3ecb7SPeter Holm#include <stdio.h>
56cbc3ecb7SPeter Holm#include <stdlib.h>
57cbc3ecb7SPeter Holm#include <string.h>
58cbc3ecb7SPeter Holm#include <sys/endian.h>
59cbc3ecb7SPeter Holm#include <sys/resource.h>
60cbc3ecb7SPeter Holm#include <sys/stat.h>
61cbc3ecb7SPeter Holm#include <sys/syscall.h>
62cbc3ecb7SPeter Holm#include <sys/wait.h>
63cbc3ecb7SPeter Holm#include <time.h>
64cbc3ecb7SPeter Holm#include <unistd.h>
65cbc3ecb7SPeter Holm
66cbc3ecb7SPeter Holmstatic __thread int skip_segv;
67cbc3ecb7SPeter Holmstatic __thread jmp_buf segv_env;
68cbc3ecb7SPeter Holm
69cbc3ecb7SPeter Holmstatic void segv_handler(int sig, siginfo_t* info, void* ctx __unused)
70cbc3ecb7SPeter Holm{
71cbc3ecb7SPeter Holm  uintptr_t addr = (uintptr_t)info->si_addr;
72cbc3ecb7SPeter Holm  const uintptr_t prog_start = 1 << 20;
73cbc3ecb7SPeter Holm  const uintptr_t prog_end = 100 << 20;
74cbc3ecb7SPeter Holm  int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
75cbc3ecb7SPeter Holm  int valid = addr < prog_start || addr > prog_end;
76cbc3ecb7SPeter Holm  if (sig == SIGBUS)
77cbc3ecb7SPeter Holm    valid = 1;
78cbc3ecb7SPeter Holm  if (skip && valid) {
79cbc3ecb7SPeter Holm    _longjmp(segv_env, 1);
80cbc3ecb7SPeter Holm  }
81cbc3ecb7SPeter Holm  exit(sig);
82cbc3ecb7SPeter Holm}
83cbc3ecb7SPeter Holm
84cbc3ecb7SPeter Holmstatic void install_segv_handler(void)
85cbc3ecb7SPeter Holm{
86cbc3ecb7SPeter Holm  struct sigaction sa;
87cbc3ecb7SPeter Holm  memset(&sa, 0, sizeof(sa));
88cbc3ecb7SPeter Holm  sa.sa_sigaction = segv_handler;
89cbc3ecb7SPeter Holm  sa.sa_flags = SA_NODEFER | SA_SIGINFO;
90cbc3ecb7SPeter Holm  sigaction(SIGSEGV, &sa, NULL);
91cbc3ecb7SPeter Holm  sigaction(SIGBUS, &sa, NULL);
92cbc3ecb7SPeter Holm}
93cbc3ecb7SPeter Holm
94cbc3ecb7SPeter Holm#define NONFAILING(...)                                                        \
95cbc3ecb7SPeter Holm  ({                                                                           \
96cbc3ecb7SPeter Holm    int ok = 1;                                                                \
97cbc3ecb7SPeter Holm    __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
98cbc3ecb7SPeter Holm    if (_setjmp(segv_env) == 0) {                                              \
99cbc3ecb7SPeter Holm      __VA_ARGS__;                                                             \
100cbc3ecb7SPeter Holm    } else                                                                     \
101cbc3ecb7SPeter Holm      ok = 0;                                                                  \
102cbc3ecb7SPeter Holm    __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
103cbc3ecb7SPeter Holm    ok;                                                                        \
104cbc3ecb7SPeter Holm  })
105cbc3ecb7SPeter Holm
106cbc3ecb7SPeter Holmstatic void kill_and_wait(int pid, int* status)
107cbc3ecb7SPeter Holm{
108cbc3ecb7SPeter Holm  kill(pid, SIGKILL);
109cbc3ecb7SPeter Holm  while (waitpid(-1, status, 0) != pid) {
110cbc3ecb7SPeter Holm  }
111cbc3ecb7SPeter Holm}
112cbc3ecb7SPeter Holm
113cbc3ecb7SPeter Holmstatic void sleep_ms(uint64_t ms)
114cbc3ecb7SPeter Holm{
115cbc3ecb7SPeter Holm  usleep(ms * 1000);
116cbc3ecb7SPeter Holm}
117cbc3ecb7SPeter Holm
118cbc3ecb7SPeter Holmstatic uint64_t current_time_ms(void)
119cbc3ecb7SPeter Holm{
120cbc3ecb7SPeter Holm  struct timespec ts;
121cbc3ecb7SPeter Holm  if (clock_gettime(CLOCK_MONOTONIC, &ts))
122cbc3ecb7SPeter Holm    exit(1);
123cbc3ecb7SPeter Holm  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
124cbc3ecb7SPeter Holm}
125cbc3ecb7SPeter Holm
126cbc3ecb7SPeter Holmstatic void use_temporary_dir(void)
127cbc3ecb7SPeter Holm{
128cbc3ecb7SPeter Holm  char tmpdir_template[] = "./syzkaller.XXXXXX";
129cbc3ecb7SPeter Holm  char* tmpdir = mkdtemp(tmpdir_template);
130cbc3ecb7SPeter Holm  if (!tmpdir)
131cbc3ecb7SPeter Holm    exit(1);
132cbc3ecb7SPeter Holm  if (chmod(tmpdir, 0777))
133cbc3ecb7SPeter Holm    exit(1);
134cbc3ecb7SPeter Holm  if (chdir(tmpdir))
135cbc3ecb7SPeter Holm    exit(1);
136cbc3ecb7SPeter Holm}
137cbc3ecb7SPeter Holm
138cbc3ecb7SPeter Holmstatic void __attribute__((noinline)) remove_dir(const char* dir)
139cbc3ecb7SPeter Holm{
140cbc3ecb7SPeter Holm  DIR* dp = opendir(dir);
141cbc3ecb7SPeter Holm  if (dp == NULL) {
142cbc3ecb7SPeter Holm    if (errno == EACCES) {
143cbc3ecb7SPeter Holm      if (rmdir(dir))
144cbc3ecb7SPeter Holm        exit(1);
145cbc3ecb7SPeter Holm      return;
146cbc3ecb7SPeter Holm    }
147cbc3ecb7SPeter Holm    exit(1);
148cbc3ecb7SPeter Holm  }
149cbc3ecb7SPeter Holm  struct dirent* ep = 0;
150cbc3ecb7SPeter Holm  while ((ep = readdir(dp))) {
151cbc3ecb7SPeter Holm    if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
152cbc3ecb7SPeter Holm      continue;
153cbc3ecb7SPeter Holm    char filename[FILENAME_MAX];
154cbc3ecb7SPeter Holm    snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
155cbc3ecb7SPeter Holm    struct stat st;
156cbc3ecb7SPeter Holm    if (lstat(filename, &st))
157cbc3ecb7SPeter Holm      exit(1);
158cbc3ecb7SPeter Holm    if (S_ISDIR(st.st_mode)) {
159cbc3ecb7SPeter Holm      remove_dir(filename);
160cbc3ecb7SPeter Holm      continue;
161cbc3ecb7SPeter Holm    }
162cbc3ecb7SPeter Holm    if (unlink(filename))
163cbc3ecb7SPeter Holm      exit(1);
164cbc3ecb7SPeter Holm  }
165cbc3ecb7SPeter Holm  closedir(dp);
166cbc3ecb7SPeter Holm  if (rmdir(dir))
167cbc3ecb7SPeter Holm    exit(1);
168cbc3ecb7SPeter Holm}
169cbc3ecb7SPeter Holm
170cbc3ecb7SPeter Holmstatic void thread_start(void* (*fn)(void*), void* arg)
171cbc3ecb7SPeter Holm{
172cbc3ecb7SPeter Holm  pthread_t th;
173cbc3ecb7SPeter Holm  pthread_attr_t attr;
174cbc3ecb7SPeter Holm  pthread_attr_init(&attr);
175cbc3ecb7SPeter Holm  pthread_attr_setstacksize(&attr, 128 << 10);
176cbc3ecb7SPeter Holm  int i = 0;
177cbc3ecb7SPeter Holm  for (; i < 100; i++) {
178cbc3ecb7SPeter Holm    if (pthread_create(&th, &attr, fn, arg) == 0) {
179cbc3ecb7SPeter Holm      pthread_attr_destroy(&attr);
180cbc3ecb7SPeter Holm      return;
181cbc3ecb7SPeter Holm    }
182cbc3ecb7SPeter Holm    if (errno == EAGAIN) {
183cbc3ecb7SPeter Holm      usleep(50);
184cbc3ecb7SPeter Holm      continue;
185cbc3ecb7SPeter Holm    }
186cbc3ecb7SPeter Holm    break;
187cbc3ecb7SPeter Holm  }
188cbc3ecb7SPeter Holm  exit(1);
189cbc3ecb7SPeter Holm}
190cbc3ecb7SPeter Holm
191cbc3ecb7SPeter Holmtypedef struct {
192cbc3ecb7SPeter Holm  pthread_mutex_t mu;
193cbc3ecb7SPeter Holm  pthread_cond_t cv;
194cbc3ecb7SPeter Holm  int state;
195cbc3ecb7SPeter Holm} event_t;
196cbc3ecb7SPeter Holm
197cbc3ecb7SPeter Holmstatic void event_init(event_t* ev)
198cbc3ecb7SPeter Holm{
199cbc3ecb7SPeter Holm  if (pthread_mutex_init(&ev->mu, 0))
200cbc3ecb7SPeter Holm    exit(1);
201cbc3ecb7SPeter Holm  if (pthread_cond_init(&ev->cv, 0))
202cbc3ecb7SPeter Holm    exit(1);
203cbc3ecb7SPeter Holm  ev->state = 0;
204cbc3ecb7SPeter Holm}
205cbc3ecb7SPeter Holm
206cbc3ecb7SPeter Holmstatic void event_reset(event_t* ev)
207cbc3ecb7SPeter Holm{
208cbc3ecb7SPeter Holm  ev->state = 0;
209cbc3ecb7SPeter Holm}
210cbc3ecb7SPeter Holm
211cbc3ecb7SPeter Holmstatic void event_set(event_t* ev)
212cbc3ecb7SPeter Holm{
213cbc3ecb7SPeter Holm  pthread_mutex_lock(&ev->mu);
214cbc3ecb7SPeter Holm  if (ev->state)
215cbc3ecb7SPeter Holm    exit(1);
216cbc3ecb7SPeter Holm  ev->state = 1;
217cbc3ecb7SPeter Holm  pthread_mutex_unlock(&ev->mu);
218cbc3ecb7SPeter Holm  pthread_cond_broadcast(&ev->cv);
219cbc3ecb7SPeter Holm}
220cbc3ecb7SPeter Holm
221cbc3ecb7SPeter Holmstatic void event_wait(event_t* ev)
222cbc3ecb7SPeter Holm{
223cbc3ecb7SPeter Holm  pthread_mutex_lock(&ev->mu);
224cbc3ecb7SPeter Holm  while (!ev->state)
225cbc3ecb7SPeter Holm    pthread_cond_wait(&ev->cv, &ev->mu);
226cbc3ecb7SPeter Holm  pthread_mutex_unlock(&ev->mu);
227cbc3ecb7SPeter Holm}
228cbc3ecb7SPeter Holm
229cbc3ecb7SPeter Holmstatic int event_isset(event_t* ev)
230cbc3ecb7SPeter Holm{
231cbc3ecb7SPeter Holm  pthread_mutex_lock(&ev->mu);
232cbc3ecb7SPeter Holm  int res = ev->state;
233cbc3ecb7SPeter Holm  pthread_mutex_unlock(&ev->mu);
234cbc3ecb7SPeter Holm  return res;
235cbc3ecb7SPeter Holm}
236cbc3ecb7SPeter Holm
237cbc3ecb7SPeter Holmstatic int event_timedwait(event_t* ev, uint64_t timeout)
238cbc3ecb7SPeter Holm{
239cbc3ecb7SPeter Holm  uint64_t start = current_time_ms();
240cbc3ecb7SPeter Holm  uint64_t now = start;
241cbc3ecb7SPeter Holm  pthread_mutex_lock(&ev->mu);
242cbc3ecb7SPeter Holm  for (;;) {
243cbc3ecb7SPeter Holm    if (ev->state)
244cbc3ecb7SPeter Holm      break;
245cbc3ecb7SPeter Holm    uint64_t remain = timeout - (now - start);
246cbc3ecb7SPeter Holm    struct timespec ts;
247cbc3ecb7SPeter Holm    ts.tv_sec = remain / 1000;
248cbc3ecb7SPeter Holm    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
249cbc3ecb7SPeter Holm    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
250cbc3ecb7SPeter Holm    now = current_time_ms();
251cbc3ecb7SPeter Holm    if (now - start > timeout)
252cbc3ecb7SPeter Holm      break;
253cbc3ecb7SPeter Holm  }
254cbc3ecb7SPeter Holm  int res = ev->state;
255cbc3ecb7SPeter Holm  pthread_mutex_unlock(&ev->mu);
256cbc3ecb7SPeter Holm  return res;
257cbc3ecb7SPeter Holm}
258cbc3ecb7SPeter Holm
259cbc3ecb7SPeter Holmstatic void sandbox_common()
260cbc3ecb7SPeter Holm{
261cbc3ecb7SPeter Holm  struct rlimit rlim;
262cbc3ecb7SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 128 << 20;
263cbc3ecb7SPeter Holm  setrlimit(RLIMIT_AS, &rlim);
264cbc3ecb7SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 8 << 20;
265cbc3ecb7SPeter Holm  setrlimit(RLIMIT_MEMLOCK, &rlim);
266cbc3ecb7SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
267cbc3ecb7SPeter Holm  setrlimit(RLIMIT_FSIZE, &rlim);
268cbc3ecb7SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
269cbc3ecb7SPeter Holm  setrlimit(RLIMIT_STACK, &rlim);
270cbc3ecb7SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 0;
271cbc3ecb7SPeter Holm  setrlimit(RLIMIT_CORE, &rlim);
272cbc3ecb7SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 256;
273cbc3ecb7SPeter Holm  setrlimit(RLIMIT_NOFILE, &rlim);
274cbc3ecb7SPeter Holm}
275cbc3ecb7SPeter Holm
276cbc3ecb7SPeter Holmstatic void loop();
277cbc3ecb7SPeter Holm
278cbc3ecb7SPeter Holmstatic int do_sandbox_none(void)
279cbc3ecb7SPeter Holm{
280cbc3ecb7SPeter Holm  sandbox_common();
281cbc3ecb7SPeter Holm  loop();
282cbc3ecb7SPeter Holm  return 0;
283cbc3ecb7SPeter Holm}
284cbc3ecb7SPeter Holm
285cbc3ecb7SPeter Holmstruct thread_t {
286cbc3ecb7SPeter Holm  int created, call;
287cbc3ecb7SPeter Holm  event_t ready, done;
288cbc3ecb7SPeter Holm};
289cbc3ecb7SPeter Holm
290cbc3ecb7SPeter Holmstatic struct thread_t threads[16];
291cbc3ecb7SPeter Holmstatic void execute_call(int call);
292cbc3ecb7SPeter Holmstatic int running;
293cbc3ecb7SPeter Holm
294cbc3ecb7SPeter Holmstatic void* thr(void* arg)
295cbc3ecb7SPeter Holm{
296cbc3ecb7SPeter Holm  struct thread_t* th = (struct thread_t*)arg;
297cbc3ecb7SPeter Holm  for (;;) {
298cbc3ecb7SPeter Holm    event_wait(&th->ready);
299cbc3ecb7SPeter Holm    event_reset(&th->ready);
300cbc3ecb7SPeter Holm    execute_call(th->call);
301cbc3ecb7SPeter Holm    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
302cbc3ecb7SPeter Holm    event_set(&th->done);
303cbc3ecb7SPeter Holm  }
304cbc3ecb7SPeter Holm  return 0;
305cbc3ecb7SPeter Holm}
306cbc3ecb7SPeter Holm
307cbc3ecb7SPeter Holmstatic void execute_one(void)
308cbc3ecb7SPeter Holm{
309cbc3ecb7SPeter Holm  int i, call, thread;
310cbc3ecb7SPeter Holm  int collide = 0;
311cbc3ecb7SPeter Holmagain:
312cbc3ecb7SPeter Holm  for (call = 0; call < 2; call++) {
313cbc3ecb7SPeter Holm    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
314cbc3ecb7SPeter Holm         thread++) {
315cbc3ecb7SPeter Holm      struct thread_t* th = &threads[thread];
316cbc3ecb7SPeter Holm      if (!th->created) {
317cbc3ecb7SPeter Holm        th->created = 1;
318cbc3ecb7SPeter Holm        event_init(&th->ready);
319cbc3ecb7SPeter Holm        event_init(&th->done);
320cbc3ecb7SPeter Holm        event_set(&th->done);
321cbc3ecb7SPeter Holm        thread_start(thr, th);
322cbc3ecb7SPeter Holm      }
323cbc3ecb7SPeter Holm      if (!event_isset(&th->done))
324cbc3ecb7SPeter Holm        continue;
325cbc3ecb7SPeter Holm      event_reset(&th->done);
326cbc3ecb7SPeter Holm      th->call = call;
327cbc3ecb7SPeter Holm      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
328cbc3ecb7SPeter Holm      event_set(&th->ready);
329cbc3ecb7SPeter Holm      if (collide && (call % 2) == 0)
330cbc3ecb7SPeter Holm        break;
331cbc3ecb7SPeter Holm      event_timedwait(&th->done, 50);
332cbc3ecb7SPeter Holm      break;
333cbc3ecb7SPeter Holm    }
334cbc3ecb7SPeter Holm  }
335cbc3ecb7SPeter Holm  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
336cbc3ecb7SPeter Holm    sleep_ms(1);
337cbc3ecb7SPeter Holm  if (!collide) {
338cbc3ecb7SPeter Holm    collide = 1;
339cbc3ecb7SPeter Holm    goto again;
340cbc3ecb7SPeter Holm  }
341cbc3ecb7SPeter Holm}
342cbc3ecb7SPeter Holm
343cbc3ecb7SPeter Holmstatic void execute_one(void);
344cbc3ecb7SPeter Holm
345cbc3ecb7SPeter Holm#define WAIT_FLAGS 0
346cbc3ecb7SPeter Holm
347cbc3ecb7SPeter Holmstatic void loop(void)
348cbc3ecb7SPeter Holm{
349cbc3ecb7SPeter Holm  int iter = 0;
350cbc3ecb7SPeter Holm  for (;; iter++) {
351cbc3ecb7SPeter Holm    char cwdbuf[32];
352cbc3ecb7SPeter Holm    sprintf(cwdbuf, "./%d", iter);
353cbc3ecb7SPeter Holm    if (mkdir(cwdbuf, 0777))
354cbc3ecb7SPeter Holm      exit(1);
355cbc3ecb7SPeter Holm    int pid = fork();
356cbc3ecb7SPeter Holm    if (pid < 0)
357cbc3ecb7SPeter Holm      exit(1);
358cbc3ecb7SPeter Holm    if (pid == 0) {
359cbc3ecb7SPeter Holm      if (chdir(cwdbuf))
360cbc3ecb7SPeter Holm        exit(1);
361cbc3ecb7SPeter Holm      execute_one();
362cbc3ecb7SPeter Holm      exit(0);
363cbc3ecb7SPeter Holm    }
364cbc3ecb7SPeter Holm    int status = 0;
365cbc3ecb7SPeter Holm    uint64_t start = current_time_ms();
366cbc3ecb7SPeter Holm    for (;;) {
367cbc3ecb7SPeter Holm      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
368cbc3ecb7SPeter Holm        break;
369cbc3ecb7SPeter Holm      sleep_ms(1);
370cbc3ecb7SPeter Holm      if (current_time_ms() - start < 5000)
371cbc3ecb7SPeter Holm        continue;
372cbc3ecb7SPeter Holm      kill_and_wait(pid, &status);
373cbc3ecb7SPeter Holm      break;
374cbc3ecb7SPeter Holm    }
375cbc3ecb7SPeter Holm    remove_dir(cwdbuf);
376cbc3ecb7SPeter Holm  }
377cbc3ecb7SPeter Holm}
378cbc3ecb7SPeter Holm
379cbc3ecb7SPeter Holmvoid execute_call(int call)
380cbc3ecb7SPeter Holm{
381cbc3ecb7SPeter Holm  switch (call) {
382cbc3ecb7SPeter Holm  case 0:
383cbc3ecb7SPeter Holm    syscall(SYS_rfork, 0x4030ul);
384cbc3ecb7SPeter Holm    break;
385cbc3ecb7SPeter Holm  case 1:
386cbc3ecb7SPeter Holm    syscall(SYS_thr_new, 0ul, 0ul);
387cbc3ecb7SPeter Holm    break;
388cbc3ecb7SPeter Holm  }
389cbc3ecb7SPeter Holm}
390cbc3ecb7SPeter Holmint main(void)
391cbc3ecb7SPeter Holm{
392cbc3ecb7SPeter Holm  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
393cbc3ecb7SPeter Holm  install_segv_handler();
394cbc3ecb7SPeter Holm  use_temporary_dir();
395cbc3ecb7SPeter Holm  do_sandbox_none();
396cbc3ecb7SPeter Holm  return 0;
397cbc3ecb7SPeter Holm}
398cbc3ecb7SPeter HolmEOF
399cbc3ecb7SPeter Holmmycc -o /tmp/syzkaller47 -Wall -Wextra -O0 /tmp/syzkaller47.c -lpthread || exit 1
400cbc3ecb7SPeter Holm
401cbc3ecb7SPeter Holm(cd /tmp; timeout 2m ./syzkaller47)
402cbc3ecb7SPeter Holm
403cbc3ecb7SPeter Holmrm -rf /tmp/syzkaller47 /tmp/syzkaller47.c /tmp/syzkaller.*
404cbc3ecb7SPeter Holmexit 0
405