xref: /freebsd/tools/test/stress2/misc/syzkaller70.sh (revision 02e9120893770924227138ba49df1edb3896112a)
1#!/bin/sh
2
3# db:1:pho1>  bt
4# Tracing pid 5640 tid 102468 td 0xfffffe00e4d26ac0
5# kdb_enter() at kdb_enter+0x32/frame 0xfffffe010dbcf260
6# vpanic() at vpanic+0x163/frame 0xfffffe010dbcf390
7# panic() at panic+0x43/frame 0xfffffe010dbcf3f0
8# vm_map_insert1() at vm_map_insert1+0x147/frame 0xfffffe010dbcf4a0
9# vm_map_insert() at vm_map_insert+0x69/frame 0xfffffe010dbcf510
10# vm_map_growstack() at vm_map_growstack+0x90e/frame 0xfffffe010dbcf650
11# vm_map_lookup() at vm_map_lookup+0x15f/frame 0xfffffe010dbcf6e0
12# vm_fault() at vm_fault+0x12f/frame 0xfffffe010dbcf820
13# vm_fault_trap() at vm_fault_trap+0x6f/frame 0xfffffe010dbcf860
14# trap_pfault() at trap_pfault+0x24a/frame 0xfffffe010dbcf8d0
15# calltrap() at calltrap+0x8/frame 0xfffffe010dbcf8d0
16# --- trap 0xc, rip = 0xffffffff81057a06, rsp = 0xfffffe010dbcf9a0, rbp = 0xfffffe010dbcf9a0 ---
17# copyin_nosmap_erms() at copyin_nosmap_erms+0x156/frame 0xfffffe010dbcf9a0
18# uiomove_fromphys() at uiomove_fromphys+0x145/frame 0xfffffe010dbcfa10
19# uiomove_object_page() at uiomove_object_page+0x1dc/frame 0xfffffe010dbcfa70
20# uiomove_object() at uiomove_object+0xa4/frame 0xfffffe010dbcfac0
21# tmpfs_write() at tmpfs_write+0xe4/frame 0xfffffe010dbcfb10
22# VOP_WRITE_APV() at VOP_WRITE_APV+0xcf/frame 0xfffffe010dbcfc20
23# vn_write() at vn_write+0x2f4/frame 0xfffffe010dbcfcb0
24# vn_io_fault() at vn_io_fault+0x1e2/frame 0xfffffe010dbcfd40
25# dofilewrite() at dofilewrite+0x82/frame 0xfffffe010dbcfd90
26# kern_pwritev() at kern_pwritev+0x64/frame 0xfffffe010dbcfdd0
27# sys_pwritev() at sys_pwritev+0x3a/frame 0xfffffe010dbcfe00
28# amd64_syscall() at amd64_syscall+0x14f/frame 0xfffffe010dbcff30
29# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe010dbcff30
30# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x822d56fca, rsp = 0x824255f58, rbp = 0x824255f90 ---
31# FreeBSD 14.0-ALPHA1 #1 main-n264742-81b41b2ef5bfd5-dirty: Tue Aug 15 19:52:50 CEST 2023
32
33uname -p | grep -Eq "amd64" || exit 0
34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
35
36. ../default.cfg
37prog=$(basename "$0" .sh)
38cat > /tmp/$prog.c <<EOF
39// https://syzkaller.appspot.com/bug?id=4c33ed3d5a9072d2ccaec3b2ef7a129f0997f477
40// autogenerated by syzkaller (https://github.com/google/syzkaller)
41// Reported-by: syzbot+c325d6a75e4fd0a68714@syzkaller.appspotmail.com
42
43#define _GNU_SOURCE
44
45#include <sys/types.h>
46
47#include <errno.h>
48#include <pthread.h>
49#include <pwd.h>
50#include <signal.h>
51#include <stdarg.h>
52#include <stdbool.h>
53#include <stdint.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57#include <sys/endian.h>
58#include <sys/syscall.h>
59#include <sys/wait.h>
60#include <time.h>
61#include <unistd.h>
62
63static void kill_and_wait(int pid, int* status)
64{
65  kill(pid, SIGKILL);
66  while (waitpid(-1, status, 0) != pid) {
67  }
68}
69
70static void sleep_ms(uint64_t ms)
71{
72  usleep(ms * 1000);
73}
74
75static uint64_t current_time_ms(void)
76{
77  struct timespec ts;
78  if (clock_gettime(CLOCK_MONOTONIC, &ts))
79    exit(1);
80  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
81}
82
83static void thread_start(void* (*fn)(void*), void* arg)
84{
85  pthread_t th;
86  pthread_attr_t attr;
87  pthread_attr_init(&attr);
88  pthread_attr_setstacksize(&attr, 128 << 10);
89  int i = 0;
90  for (; i < 100; i++) {
91    if (pthread_create(&th, &attr, fn, arg) == 0) {
92      pthread_attr_destroy(&attr);
93      return;
94    }
95    if (errno == EAGAIN) {
96      usleep(50);
97      continue;
98    }
99    break;
100  }
101  exit(1);
102}
103
104typedef struct {
105  pthread_mutex_t mu;
106  pthread_cond_t cv;
107  int state;
108} event_t;
109
110static void event_init(event_t* ev)
111{
112  if (pthread_mutex_init(&ev->mu, 0))
113    exit(1);
114  if (pthread_cond_init(&ev->cv, 0))
115    exit(1);
116  ev->state = 0;
117}
118
119static void event_reset(event_t* ev)
120{
121  ev->state = 0;
122}
123
124static void event_set(event_t* ev)
125{
126  pthread_mutex_lock(&ev->mu);
127  if (ev->state)
128    exit(1);
129  ev->state = 1;
130  pthread_mutex_unlock(&ev->mu);
131  pthread_cond_broadcast(&ev->cv);
132}
133
134static void event_wait(event_t* ev)
135{
136  pthread_mutex_lock(&ev->mu);
137  while (!ev->state)
138    pthread_cond_wait(&ev->cv, &ev->mu);
139  pthread_mutex_unlock(&ev->mu);
140}
141
142static int event_isset(event_t* ev)
143{
144  pthread_mutex_lock(&ev->mu);
145  int res = ev->state;
146  pthread_mutex_unlock(&ev->mu);
147  return res;
148}
149
150static int event_timedwait(event_t* ev, uint64_t timeout)
151{
152  uint64_t start = current_time_ms();
153  uint64_t now = start;
154  pthread_mutex_lock(&ev->mu);
155  for (;;) {
156    if (ev->state)
157      break;
158    uint64_t remain = timeout - (now - start);
159    struct timespec ts;
160    ts.tv_sec = remain / 1000;
161    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
162    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
163    now = current_time_ms();
164    if (now - start > timeout)
165      break;
166  }
167  int res = ev->state;
168  pthread_mutex_unlock(&ev->mu);
169  return res;
170}
171
172struct thread_t {
173  int created, call;
174  event_t ready, done;
175};
176
177static struct thread_t threads[16];
178static void execute_call(int call);
179static int running;
180
181static void* thr(void* arg)
182{
183  struct thread_t* th = (struct thread_t*)arg;
184  for (;;) {
185    event_wait(&th->ready);
186    event_reset(&th->ready);
187    execute_call(th->call);
188    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
189    event_set(&th->done);
190  }
191  return 0;
192}
193
194static void execute_one(void)
195{
196  int i, call, thread;
197  for (call = 0; call < 4; call++) {
198    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
199         thread++) {
200      struct thread_t* th = &threads[thread];
201      if (!th->created) {
202        th->created = 1;
203        event_init(&th->ready);
204        event_init(&th->done);
205        event_set(&th->done);
206        thread_start(thr, th);
207      }
208      if (!event_isset(&th->done))
209        continue;
210      event_reset(&th->done);
211      th->call = call;
212      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
213      event_set(&th->ready);
214      event_timedwait(&th->done, 50);
215      break;
216    }
217  }
218  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
219    sleep_ms(1);
220}
221
222static void execute_one(void);
223
224#define WAIT_FLAGS 0
225
226static void loop(void)
227{
228  int iter __unused = 0;
229  for (;; iter++) {
230    int pid = fork();
231    if (pid < 0)
232      exit(1);
233    if (pid == 0) {
234      execute_one();
235      exit(0);
236    }
237    int status = 0;
238    uint64_t start = current_time_ms();
239    for (;;) {
240      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
241        break;
242      sleep_ms(1);
243      if (current_time_ms() - start < 5000)
244        continue;
245      kill_and_wait(pid, &status);
246      break;
247    }
248  }
249}
250
251uint64_t r[1] = {0xffffffffffffffff};
252
253void execute_call(int call)
254{
255  intptr_t res = 0;
256  switch (call) {
257  case 0:
258    memcpy((void*)0x20000240, "./file0\000", 8);
259    res = syscall(SYS_open, /*file=*/0x20000240ul,
260                  /*flags=*/0x40000400000002c2ul, /*mode=*/0ul);
261    if (res != -1)
262      r[0] = res;
263    break;
264  case 1:
265    *(uint64_t*)0x20000080 = 0x200006c0;
266    *(uint64_t*)0x20000088 = 0x100000;
267    syscall(SYS_pwritev, /*fd=*/r[0], /*vec=*/0x20000080ul, /*vlen=*/1ul,
268            /*off=*/0ul);
269    break;
270  case 2:
271    syscall(SYS_mmap, /*addr=*/0x20000000ul, /*len=*/0x200000ul, /*prot=*/3ul,
272            /*flags=*/0x410ul, /*fd=*/-1, /*offset=*/0ul);
273    break;
274  case 3:
275    syscall(SYS_mmap, /*addr=*/0x2000c000ul, /*len=*/0x4000ul, /*prot=*/0ul,
276            /*flags=*/0x2010ul, /*fd=*/-1, /*offset=*/0ul);
277    break;
278  }
279}
280int main(void)
281{
282  syscall(SYS_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul,
283          /*flags=*/0x1012ul, /*fd=*/-1, /*offset=*/0ul);
284  loop();
285  return 0;
286}
287EOF
288mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1
289
290mount | grep -q "on $mntpoint " && umount $mntpoint
291mount -o size=10m -t tmpfs dummy $mntpoint
292
293cd $mntpoint
294for i in `jot 20`; do
295	timeout 3m /tmp/$prog &
296done
297wait
298cd -
299
300umount $mntpoint
301rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core
302exit 0
303