xref: /freebsd/tools/test/stress2/misc/syzkaller64.sh (revision 7f658f99f7ed5d1d0e0802073bb22eb8a0a784fb)
1bce30c89SPeter Holm#!/bin/sh
2bce30c89SPeter Holm
3bce30c89SPeter Holm[ `uname -p` != "amd64" ] && exit 0
4bce30c89SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
5bce30c89SPeter Holm[ "`sysctl -in kern.features.kasan`" != "1" ] && exit 0
6bce30c89SPeter Holm
7bce30c89SPeter Holm. ../default.cfg
8bce30c89SPeter Holmprog=$(basename "$0" .sh)
9bce30c89SPeter Holmcat > /tmp/$prog.c <<EOF
10bce30c89SPeter Holm// https://syzkaller.appspot.com/bug?id=749aa1fdb67018e9c0179373a60d523511bff02c
11bce30c89SPeter Holm// autogenerated by syzkaller (https://github.com/google/syzkaller)
12bce30c89SPeter Holm// Reported-by: syzbot+5cb51285603332d9be11@syzkaller.appspotmail.com
13bce30c89SPeter Holm
14bce30c89SPeter Holm#define _GNU_SOURCE
15bce30c89SPeter Holm
16bce30c89SPeter Holm#include <sys/types.h>
17bce30c89SPeter Holm
18bce30c89SPeter Holm#include <errno.h>
19bce30c89SPeter Holm#include <pthread.h>
20bce30c89SPeter Holm#include <pwd.h>
21bce30c89SPeter Holm#include <setjmp.h>
22bce30c89SPeter Holm#include <signal.h>
23bce30c89SPeter Holm#include <stdarg.h>
24bce30c89SPeter Holm#include <stdbool.h>
25bce30c89SPeter Holm#include <stdint.h>
26bce30c89SPeter Holm#include <stdio.h>
27bce30c89SPeter Holm#include <stdlib.h>
28bce30c89SPeter Holm#include <string.h>
29bce30c89SPeter Holm#include <sys/endian.h>
30bce30c89SPeter Holm#include <sys/resource.h>
31bce30c89SPeter Holm#include <sys/syscall.h>
32bce30c89SPeter Holm#include <sys/wait.h>
33bce30c89SPeter Holm#include <time.h>
34bce30c89SPeter Holm#include <unistd.h>
35bce30c89SPeter Holm
36bce30c89SPeter Holmstatic __thread int clone_ongoing;
37bce30c89SPeter Holmstatic __thread int skip_segv;
38bce30c89SPeter Holmstatic __thread jmp_buf segv_env;
39bce30c89SPeter Holm
40bce30c89SPeter Holmstatic void segv_handler(int sig, siginfo_t* info, void* ctx __unused)
41bce30c89SPeter Holm{
42bce30c89SPeter Holm  if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
43bce30c89SPeter Holm    exit(sig);
44bce30c89SPeter Holm  }
45bce30c89SPeter Holm  uintptr_t addr = (uintptr_t)info->si_addr;
46bce30c89SPeter Holm  const uintptr_t prog_start = 1 << 20;
47bce30c89SPeter Holm  const uintptr_t prog_end = 100 << 20;
48bce30c89SPeter Holm  int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
49bce30c89SPeter Holm  int valid = addr < prog_start || addr > prog_end;
50bce30c89SPeter Holm  if (sig == SIGBUS)
51bce30c89SPeter Holm    valid = 1;
52bce30c89SPeter Holm  if (skip && valid) {
53bce30c89SPeter Holm    _longjmp(segv_env, 1);
54bce30c89SPeter Holm  }
55bce30c89SPeter Holm  exit(sig);
56bce30c89SPeter Holm}
57bce30c89SPeter Holm
58bce30c89SPeter Holmstatic void install_segv_handler(void)
59bce30c89SPeter Holm{
60bce30c89SPeter Holm  struct sigaction sa;
61bce30c89SPeter Holm  memset(&sa, 0, sizeof(sa));
62bce30c89SPeter Holm  sa.sa_sigaction = segv_handler;
63bce30c89SPeter Holm  sa.sa_flags = SA_NODEFER | SA_SIGINFO;
64bce30c89SPeter Holm  sigaction(SIGSEGV, &sa, NULL);
65bce30c89SPeter Holm  sigaction(SIGBUS, &sa, NULL);
66bce30c89SPeter Holm}
67bce30c89SPeter Holm
68bce30c89SPeter Holm#define NONFAILING(...)                                                        \
69bce30c89SPeter Holm  ({                                                                           \
70bce30c89SPeter Holm    int ok = 1;                                                                \
71bce30c89SPeter Holm    __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
72bce30c89SPeter Holm    if (_setjmp(segv_env) == 0) {                                              \
73bce30c89SPeter Holm      __VA_ARGS__;                                                             \
74bce30c89SPeter Holm    } else                                                                     \
75bce30c89SPeter Holm      ok = 0;                                                                  \
76bce30c89SPeter Holm    __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
77bce30c89SPeter Holm    ok;                                                                        \
78bce30c89SPeter Holm  })
79bce30c89SPeter Holm
80bce30c89SPeter Holmstatic void kill_and_wait(int pid, int* status)
81bce30c89SPeter Holm{
82bce30c89SPeter Holm  kill(pid, SIGKILL);
83bce30c89SPeter Holm  while (waitpid(-1, status, 0) != pid) {
84bce30c89SPeter Holm  }
85bce30c89SPeter Holm}
86bce30c89SPeter Holm
87bce30c89SPeter Holmstatic void sleep_ms(uint64_t ms)
88bce30c89SPeter Holm{
89bce30c89SPeter Holm  usleep(ms * 1000);
90bce30c89SPeter Holm}
91bce30c89SPeter Holm
92bce30c89SPeter Holmstatic uint64_t current_time_ms(void)
93bce30c89SPeter Holm{
94bce30c89SPeter Holm  struct timespec ts;
95bce30c89SPeter Holm  if (clock_gettime(CLOCK_MONOTONIC, &ts))
96bce30c89SPeter Holm    exit(1);
97bce30c89SPeter Holm  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
98bce30c89SPeter Holm}
99bce30c89SPeter Holm
100bce30c89SPeter Holmstatic void thread_start(void* (*fn)(void*), void* arg)
101bce30c89SPeter Holm{
102bce30c89SPeter Holm  pthread_t th;
103bce30c89SPeter Holm  pthread_attr_t attr;
104bce30c89SPeter Holm  pthread_attr_init(&attr);
105bce30c89SPeter Holm  pthread_attr_setstacksize(&attr, 128 << 10);
106bce30c89SPeter Holm  int i = 0;
107bce30c89SPeter Holm  for (; i < 100; i++) {
108bce30c89SPeter Holm    if (pthread_create(&th, &attr, fn, arg) == 0) {
109bce30c89SPeter Holm      pthread_attr_destroy(&attr);
110bce30c89SPeter Holm      return;
111bce30c89SPeter Holm    }
112bce30c89SPeter Holm    if (errno == EAGAIN) {
113bce30c89SPeter Holm      usleep(50);
114bce30c89SPeter Holm      continue;
115bce30c89SPeter Holm    }
116bce30c89SPeter Holm    break;
117bce30c89SPeter Holm  }
118bce30c89SPeter Holm  exit(1);
119bce30c89SPeter Holm}
120bce30c89SPeter Holm
121bce30c89SPeter Holmtypedef struct {
122bce30c89SPeter Holm  pthread_mutex_t mu;
123bce30c89SPeter Holm  pthread_cond_t cv;
124bce30c89SPeter Holm  int state;
125bce30c89SPeter Holm} event_t;
126bce30c89SPeter Holm
127bce30c89SPeter Holmstatic void event_init(event_t* ev)
128bce30c89SPeter Holm{
129bce30c89SPeter Holm  if (pthread_mutex_init(&ev->mu, 0))
130bce30c89SPeter Holm    exit(1);
131bce30c89SPeter Holm  if (pthread_cond_init(&ev->cv, 0))
132bce30c89SPeter Holm    exit(1);
133bce30c89SPeter Holm  ev->state = 0;
134bce30c89SPeter Holm}
135bce30c89SPeter Holm
136bce30c89SPeter Holmstatic void event_reset(event_t* ev)
137bce30c89SPeter Holm{
138bce30c89SPeter Holm  ev->state = 0;
139bce30c89SPeter Holm}
140bce30c89SPeter Holm
141bce30c89SPeter Holmstatic void event_set(event_t* ev)
142bce30c89SPeter Holm{
143bce30c89SPeter Holm  pthread_mutex_lock(&ev->mu);
144bce30c89SPeter Holm  if (ev->state)
145bce30c89SPeter Holm    exit(1);
146bce30c89SPeter Holm  ev->state = 1;
147bce30c89SPeter Holm  pthread_mutex_unlock(&ev->mu);
148bce30c89SPeter Holm  pthread_cond_broadcast(&ev->cv);
149bce30c89SPeter Holm}
150bce30c89SPeter Holm
151bce30c89SPeter Holmstatic void event_wait(event_t* ev)
152bce30c89SPeter Holm{
153bce30c89SPeter Holm  pthread_mutex_lock(&ev->mu);
154bce30c89SPeter Holm  while (!ev->state)
155bce30c89SPeter Holm    pthread_cond_wait(&ev->cv, &ev->mu);
156bce30c89SPeter Holm  pthread_mutex_unlock(&ev->mu);
157bce30c89SPeter Holm}
158bce30c89SPeter Holm
159bce30c89SPeter Holmstatic int event_isset(event_t* ev)
160bce30c89SPeter Holm{
161bce30c89SPeter Holm  pthread_mutex_lock(&ev->mu);
162bce30c89SPeter Holm  int res = ev->state;
163bce30c89SPeter Holm  pthread_mutex_unlock(&ev->mu);
164bce30c89SPeter Holm  return res;
165bce30c89SPeter Holm}
166bce30c89SPeter Holm
167bce30c89SPeter Holmstatic int event_timedwait(event_t* ev, uint64_t timeout)
168bce30c89SPeter Holm{
169bce30c89SPeter Holm  uint64_t start = current_time_ms();
170bce30c89SPeter Holm  uint64_t now = start;
171bce30c89SPeter Holm  pthread_mutex_lock(&ev->mu);
172bce30c89SPeter Holm  for (;;) {
173bce30c89SPeter Holm    if (ev->state)
174bce30c89SPeter Holm      break;
175bce30c89SPeter Holm    uint64_t remain = timeout - (now - start);
176bce30c89SPeter Holm    struct timespec ts;
177bce30c89SPeter Holm    ts.tv_sec = remain / 1000;
178bce30c89SPeter Holm    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
179bce30c89SPeter Holm    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
180bce30c89SPeter Holm    now = current_time_ms();
181bce30c89SPeter Holm    if (now - start > timeout)
182bce30c89SPeter Holm      break;
183bce30c89SPeter Holm  }
184bce30c89SPeter Holm  int res = ev->state;
185bce30c89SPeter Holm  pthread_mutex_unlock(&ev->mu);
186bce30c89SPeter Holm  return res;
187bce30c89SPeter Holm}
188bce30c89SPeter Holm
189bce30c89SPeter Holmstatic void sandbox_common()
190bce30c89SPeter Holm{
191bce30c89SPeter Holm  struct rlimit rlim;
192bce30c89SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 128 << 20;
193bce30c89SPeter Holm  setrlimit(RLIMIT_AS, &rlim);
194bce30c89SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 8 << 20;
195bce30c89SPeter Holm  setrlimit(RLIMIT_MEMLOCK, &rlim);
196bce30c89SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
197bce30c89SPeter Holm  setrlimit(RLIMIT_FSIZE, &rlim);
198bce30c89SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
199bce30c89SPeter Holm  setrlimit(RLIMIT_STACK, &rlim);
200bce30c89SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 0;
201bce30c89SPeter Holm  setrlimit(RLIMIT_CORE, &rlim);
202bce30c89SPeter Holm  rlim.rlim_cur = rlim.rlim_max = 256;
203bce30c89SPeter Holm  setrlimit(RLIMIT_NOFILE, &rlim);
204bce30c89SPeter Holm}
205bce30c89SPeter Holm
206bce30c89SPeter Holmstatic void loop();
207bce30c89SPeter Holm
208bce30c89SPeter Holmstatic int do_sandbox_none(void)
209bce30c89SPeter Holm{
210bce30c89SPeter Holm  sandbox_common();
211bce30c89SPeter Holm  loop();
212bce30c89SPeter Holm  return 0;
213bce30c89SPeter Holm}
214bce30c89SPeter Holm
215bce30c89SPeter Holmstruct thread_t {
216bce30c89SPeter Holm  int created, call;
217bce30c89SPeter Holm  event_t ready, done;
218bce30c89SPeter Holm};
219bce30c89SPeter Holm
220bce30c89SPeter Holmstatic struct thread_t threads[16];
221bce30c89SPeter Holmstatic void execute_call(int call);
222bce30c89SPeter Holmstatic int running;
223bce30c89SPeter Holm
224bce30c89SPeter Holmstatic void* thr(void* arg)
225bce30c89SPeter Holm{
226bce30c89SPeter Holm  struct thread_t* th = (struct thread_t*)arg;
227bce30c89SPeter Holm  for (;;) {
228bce30c89SPeter Holm    event_wait(&th->ready);
229bce30c89SPeter Holm    event_reset(&th->ready);
230bce30c89SPeter Holm    execute_call(th->call);
231bce30c89SPeter Holm    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
232bce30c89SPeter Holm    event_set(&th->done);
233bce30c89SPeter Holm  }
234bce30c89SPeter Holm  return 0;
235bce30c89SPeter Holm}
236bce30c89SPeter Holm
237bce30c89SPeter Holmstatic void execute_one(void)
238bce30c89SPeter Holm{
239bce30c89SPeter Holm  int i, call, thread;
240bce30c89SPeter Holm  for (call = 0; call < 5; call++) {
241bce30c89SPeter Holm    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
242bce30c89SPeter Holm         thread++) {
243bce30c89SPeter Holm      struct thread_t* th = &threads[thread];
244bce30c89SPeter Holm      if (!th->created) {
245bce30c89SPeter Holm        th->created = 1;
246bce30c89SPeter Holm        event_init(&th->ready);
247bce30c89SPeter Holm        event_init(&th->done);
248bce30c89SPeter Holm        event_set(&th->done);
249bce30c89SPeter Holm        thread_start(thr, th);
250bce30c89SPeter Holm      }
251bce30c89SPeter Holm      if (!event_isset(&th->done))
252bce30c89SPeter Holm        continue;
253bce30c89SPeter Holm      event_reset(&th->done);
254bce30c89SPeter Holm      th->call = call;
255bce30c89SPeter Holm      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
256bce30c89SPeter Holm      event_set(&th->ready);
257bce30c89SPeter Holm      event_timedwait(&th->done, 50);
258bce30c89SPeter Holm      break;
259bce30c89SPeter Holm    }
260bce30c89SPeter Holm  }
261bce30c89SPeter Holm  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
262bce30c89SPeter Holm    sleep_ms(1);
263bce30c89SPeter Holm}
264bce30c89SPeter Holm
265bce30c89SPeter Holmstatic void execute_one(void);
266bce30c89SPeter Holm
267bce30c89SPeter Holm#define WAIT_FLAGS 0
268bce30c89SPeter Holm
269bce30c89SPeter Holmstatic void loop(void)
270bce30c89SPeter Holm{
271*7f658f99SPeter Holm  int iter __unused = 0;
272bce30c89SPeter Holm  for (;; iter++) {
273bce30c89SPeter Holm    int pid = fork();
274bce30c89SPeter Holm    if (pid < 0)
275bce30c89SPeter Holm      exit(1);
276bce30c89SPeter Holm    if (pid == 0) {
277bce30c89SPeter Holm      execute_one();
278bce30c89SPeter Holm      exit(0);
279bce30c89SPeter Holm    }
280bce30c89SPeter Holm    int status = 0;
281bce30c89SPeter Holm    uint64_t start = current_time_ms();
282bce30c89SPeter Holm    for (;;) {
283bce30c89SPeter Holm      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
284bce30c89SPeter Holm        break;
285bce30c89SPeter Holm      sleep_ms(1);
286bce30c89SPeter Holm      if (current_time_ms() - start < 5000)
287bce30c89SPeter Holm        continue;
288bce30c89SPeter Holm      kill_and_wait(pid, &status);
289bce30c89SPeter Holm      break;
290bce30c89SPeter Holm    }
291bce30c89SPeter Holm  }
292bce30c89SPeter Holm}
293bce30c89SPeter Holm
294bce30c89SPeter Holmvoid execute_call(int call)
295bce30c89SPeter Holm{
296bce30c89SPeter Holm  switch (call) {
297bce30c89SPeter Holm  case 0:
298bce30c89SPeter Holm    syscall(SYS_thr_new, 0ul, 0ul);
299bce30c89SPeter Holm    break;
300bce30c89SPeter Holm  case 1:
301bce30c89SPeter Holm    syscall(SYS_setloginclass, 0ul);
302bce30c89SPeter Holm    break;
303bce30c89SPeter Holm  case 2:
304bce30c89SPeter Holm    syscall(SYS_vfork);
305bce30c89SPeter Holm    break;
306bce30c89SPeter Holm  case 3:
307bce30c89SPeter Holm    NONFAILING(*(uint32_t*)0x20001880 = 4);
308bce30c89SPeter Holm    syscall(SYS_sysarch, 8ul, 0x20001880ul);
309bce30c89SPeter Holm    break;
310bce30c89SPeter Holm  case 4:
311bce30c89SPeter Holm    syscall(SYS_getsid, 0);
312bce30c89SPeter Holm    break;
313bce30c89SPeter Holm  }
314bce30c89SPeter Holm}
315bce30c89SPeter Holmint main(void)
316bce30c89SPeter Holm{
317bce30c89SPeter Holm  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
318bce30c89SPeter Holm  install_segv_handler();
319bce30c89SPeter Holm  do_sandbox_none();
320bce30c89SPeter Holm  return 0;
321bce30c89SPeter Holm}
322bce30c89SPeter HolmEOF
323bce30c89SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1
324bce30c89SPeter Holm
325bce30c89SPeter Holm(cd /tmp; timeout 2m ./$prog)
326bce30c89SPeter Holm
327bce30c89SPeter Holmrm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.*
328bce30c89SPeter Holmexit 0
329