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