xref: /freebsd/tools/test/stress2/misc/syzkaller52.sh (revision 4d0adee4e678d1e1b973fd7cf0650950f609a44b)
1#!/bin/sh
2
3# panic: already suspended
4# cpuid = 6
5# time = 1651176216
6# KDB: stack backtrace:
7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe014194ea70
8# vpanic() at vpanic+0x17f/frame 0xfffffe014194eac0
9# panic() at panic+0x43/frame 0xfffffe014194eb20
10# thread_single() at thread_single+0x774/frame 0xfffffe014194eb90
11# reap_kill_proc() at reap_kill_proc+0x296/frame 0xfffffe014194ebf0
12# reap_kill() at reap_kill+0x371/frame 0xfffffe014194ed00
13# kern_procctl() at kern_procctl+0x30b/frame 0xfffffe014194ed70
14# sys_procctl() at sys_procctl+0x11e/frame 0xfffffe014194ee00
15# amd64_syscall() at amd64_syscall+0x145/frame 0xfffffe014194ef30
16# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe014194ef30
17# --- syscall (0, FreeBSD ELF64, nosys), rip = 0x8226f27aa, rsp = 0x82803ef48, rbp = 0x82803ef70 ---
18# KDB: enter: panic
19# [ thread pid 3074 tid 100404 ]
20# Stopped at      kdb_enter+0x32: movq    $0,0x12790b3(%rip)
21# db> x/s version
22# FreeBSD 14.0-CURRENT #0 main-n255099-0923ff82fb383: Thu Apr 28 09:48:48 CEST 2022
23# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO
24# db>
25
26[ `uname -p` != "amd64" ] && exit 0
27
28. ../default.cfg
29cat > /tmp/syzkaller52.c <<EOF
30// https://syzkaller.appspot.com/bug?id=20185b6047d7371885412b56ff188be88f740eab
31// autogenerated by syzkaller (https://github.com/google/syzkaller)
32// Reported-by: syzbot+79cd12371d417441b175@syzkaller.appspotmail.com
33
34#define _GNU_SOURCE
35
36#include <sys/types.h>
37
38#include <dirent.h>
39#include <errno.h>
40#include <pthread.h>
41#include <pwd.h>
42#include <signal.h>
43#include <stdarg.h>
44#include <stdbool.h>
45#include <stdint.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <sys/endian.h>
50#include <sys/resource.h>
51#include <sys/stat.h>
52#include <sys/syscall.h>
53#include <sys/wait.h>
54#include <time.h>
55#include <unistd.h>
56
57static unsigned long long procid;
58
59static void kill_and_wait(int pid, int* status)
60{
61  kill(pid, SIGKILL);
62  while (waitpid(-1, status, 0) != pid) {
63  }
64}
65
66static void sleep_ms(uint64_t ms)
67{
68  usleep(ms * 1000);
69}
70
71static uint64_t current_time_ms(void)
72{
73  struct timespec ts;
74  if (clock_gettime(CLOCK_MONOTONIC, &ts))
75    exit(1);
76  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
77}
78
79static void use_temporary_dir(void)
80{
81  char tmpdir_template[] = "./syzkaller.XXXXXX";
82  char* tmpdir = mkdtemp(tmpdir_template);
83  if (!tmpdir)
84    exit(1);
85  if (chmod(tmpdir, 0777))
86    exit(1);
87  if (chdir(tmpdir))
88    exit(1);
89}
90
91static void __attribute__((noinline)) remove_dir(const char* dir)
92{
93  DIR* dp = opendir(dir);
94  if (dp == NULL) {
95    if (errno == EACCES) {
96      if (rmdir(dir))
97        exit(1);
98      return;
99    }
100    exit(1);
101  }
102  struct dirent* ep = 0;
103  while ((ep = readdir(dp))) {
104    if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
105      continue;
106    char filename[FILENAME_MAX];
107    snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
108    struct stat st;
109    if (lstat(filename, &st))
110      exit(1);
111    if (S_ISDIR(st.st_mode)) {
112      remove_dir(filename);
113      continue;
114    }
115    if (unlink(filename))
116      exit(1);
117  }
118  closedir(dp);
119  if (rmdir(dir))
120    exit(1);
121}
122
123static void thread_start(void* (*fn)(void*), void* arg)
124{
125  pthread_t th;
126  pthread_attr_t attr;
127  pthread_attr_init(&attr);
128  pthread_attr_setstacksize(&attr, 128 << 10);
129  int i = 0;
130  for (; i < 100; i++) {
131    if (pthread_create(&th, &attr, fn, arg) == 0) {
132      pthread_attr_destroy(&attr);
133      return;
134    }
135    if (errno == EAGAIN) {
136      usleep(50);
137      continue;
138    }
139    break;
140  }
141  exit(1);
142}
143
144typedef struct {
145  pthread_mutex_t mu;
146  pthread_cond_t cv;
147  int state;
148} event_t;
149
150static void event_init(event_t* ev)
151{
152  if (pthread_mutex_init(&ev->mu, 0))
153    exit(1);
154  if (pthread_cond_init(&ev->cv, 0))
155    exit(1);
156  ev->state = 0;
157}
158
159static void event_reset(event_t* ev)
160{
161  ev->state = 0;
162}
163
164static void event_set(event_t* ev)
165{
166  pthread_mutex_lock(&ev->mu);
167  if (ev->state)
168    exit(1);
169  ev->state = 1;
170  pthread_mutex_unlock(&ev->mu);
171  pthread_cond_broadcast(&ev->cv);
172}
173
174static void event_wait(event_t* ev)
175{
176  pthread_mutex_lock(&ev->mu);
177  while (!ev->state)
178    pthread_cond_wait(&ev->cv, &ev->mu);
179  pthread_mutex_unlock(&ev->mu);
180}
181
182static int event_isset(event_t* ev)
183{
184  pthread_mutex_lock(&ev->mu);
185  int res = ev->state;
186  pthread_mutex_unlock(&ev->mu);
187  return res;
188}
189
190static int event_timedwait(event_t* ev, uint64_t timeout)
191{
192  uint64_t start = current_time_ms();
193  uint64_t now = start;
194  pthread_mutex_lock(&ev->mu);
195  for (;;) {
196    if (ev->state)
197      break;
198    uint64_t remain = timeout - (now - start);
199    struct timespec ts;
200    ts.tv_sec = remain / 1000;
201    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
202    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
203    now = current_time_ms();
204    if (now - start > timeout)
205      break;
206  }
207  int res = ev->state;
208  pthread_mutex_unlock(&ev->mu);
209  return res;
210}
211
212static void sandbox_common()
213{
214  struct rlimit rlim;
215  rlim.rlim_cur = rlim.rlim_max = 128 << 20;
216  setrlimit(RLIMIT_AS, &rlim);
217  rlim.rlim_cur = rlim.rlim_max = 8 << 20;
218  setrlimit(RLIMIT_MEMLOCK, &rlim);
219  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
220  setrlimit(RLIMIT_FSIZE, &rlim);
221  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
222  setrlimit(RLIMIT_STACK, &rlim);
223  rlim.rlim_cur = rlim.rlim_max = 0;
224  setrlimit(RLIMIT_CORE, &rlim);
225  rlim.rlim_cur = rlim.rlim_max = 256;
226  setrlimit(RLIMIT_NOFILE, &rlim);
227}
228
229static void loop();
230
231static int do_sandbox_none(void)
232{
233  sandbox_common();
234  loop();
235  return 0;
236}
237
238struct thread_t {
239  int created, call;
240  event_t ready, done;
241};
242
243static struct thread_t threads[16];
244static void execute_call(int call);
245static int running;
246
247static void* thr(void* arg)
248{
249  struct thread_t* th = (struct thread_t*)arg;
250  for (;;) {
251    event_wait(&th->ready);
252    event_reset(&th->ready);
253    execute_call(th->call);
254    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
255    event_set(&th->done);
256  }
257  return 0;
258}
259
260static void execute_one(void)
261{
262  int i, call, thread;
263  for (call = 0; call < 14; call++) {
264    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
265         thread++) {
266      struct thread_t* th = &threads[thread];
267      if (!th->created) {
268        th->created = 1;
269        event_init(&th->ready);
270        event_init(&th->done);
271        event_set(&th->done);
272        thread_start(thr, th);
273      }
274      if (!event_isset(&th->done))
275        continue;
276      event_reset(&th->done);
277      th->call = call;
278      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
279      event_set(&th->ready);
280      event_timedwait(&th->done, 50);
281      break;
282    }
283  }
284  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
285    sleep_ms(1);
286}
287
288static void execute_one(void);
289
290#define WAIT_FLAGS 0
291
292static void loop(void)
293{
294  int iter = 0;
295  for (;; iter++) {
296    char cwdbuf[32];
297    sprintf(cwdbuf, "./%d", iter);
298    if (mkdir(cwdbuf, 0777))
299      exit(1);
300    int pid = fork();
301    if (pid < 0)
302      exit(1);
303    if (pid == 0) {
304      if (chdir(cwdbuf))
305        exit(1);
306      execute_one();
307      exit(0);
308    }
309    int status = 0;
310    uint64_t start = current_time_ms();
311    for (;;) {
312      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
313        break;
314      sleep_ms(1);
315      if (current_time_ms() - start < 5000)
316        continue;
317      kill_and_wait(pid, &status);
318      break;
319    }
320    remove_dir(cwdbuf);
321  }
322}
323
324uint64_t r[4] = {0x0, 0x0, 0x0, 0x0};
325
326void execute_call(int call)
327{
328  intptr_t res = 0;
329  switch (call) {
330  case 0:
331    *(uint32_t*)0x20000000 = 0x3f;
332    *(uint32_t*)0x20000004 = 8;
333    *(uint32_t*)0x20000008 = 0x1000;
334    *(uint32_t*)0x2000000c = 7;
335    syscall(SYS_sigsuspend, 0x20000000ul);
336    break;
337  case 1:
338    syscall(SYS_setgid, 0);
339    break;
340  case 2:
341    syscall(SYS_getgroups, 0ul, 0ul);
342    break;
343  case 3:
344    syscall(SYS_setegid, 0);
345    break;
346  case 4:
347    res = syscall(SYS_shmget, 0ul, 0x2000ul, 0x420ul, 0x20ffd000ul);
348    if (res != -1)
349      r[0] = res;
350    break;
351  case 5:
352    res = syscall(SYS_getpid);
353    if (res != -1)
354      r[1] = res;
355    break;
356  case 6:
357    *(uint32_t*)0x20000200 = -1;
358    *(uint32_t*)0x20000204 = 0;
359    *(uint32_t*)0x20000208 = -1;
360    *(uint32_t*)0x2000020c = 0;
361    *(uint16_t*)0x20000210 = 0xf965;
362    *(uint16_t*)0x20000212 = 0x2000;
363    *(uint32_t*)0x20000214 = 0;
364    *(uint64_t*)0x20000218 = 0x2d;
365    *(uint32_t*)0x20000220 = 0x1f;
366    *(uint64_t*)0x20000228 = 2;
367    *(uint64_t*)0x20000230 = 4;
368    *(uint64_t*)0x20000238 = 0;
369    *(uint32_t*)0x20000240 = r[1];
370    *(uint32_t*)0x20000244 = -1;
371    *(uint16_t*)0x20000248 = 7;
372    *(uint16_t*)0x2000024a = 0;
373    *(uint64_t*)0x20000250 = 0;
374    *(uint64_t*)0x20000258 = 0;
375    syscall(SYS_shmctl, r[0], 1ul, 0x20000200ul);
376    break;
377  case 7:
378    syscall(SYS_getgid);
379    break;
380  case 8:
381    syscall(SYS___semctl, 0, 0ul, 1ul, 0ul);
382    break;
383  case 9:
384    *(uint32_t*)0x20000300 = 4;
385    *(uint32_t*)0x20000304 = 0;
386    *(uint16_t*)0x20000308 = 7;
387    *(uint16_t*)0x2000030a = 6;
388    memcpy((void*)0x2000030c,
389           "\x26\xb9\x52\x60\x70\xe1\xb8\x97\x99\x4b\x39\xd3\xea\x42\xe7\xed",
390           16);
391    syscall(SYS_fhstat, 0x20000300ul, 0ul);
392    break;
393  case 10:
394    res = syscall(SYS_getgid);
395    if (res != -1)
396      r[2] = res;
397    break;
398  case 11:
399    *(uint32_t*)0x20000440 = 3;
400    *(uint32_t*)0x20000444 = 0;
401    *(uint32_t*)0x20000448 = r[1];
402    *(uint32_t*)0x2000044c = 0x81;
403    *(uint32_t*)0x20000450 = r[1];
404    memset((void*)0x20000454, 0, 60);
405    res = syscall(SYS_procctl, 0ul, r[1], 6ul, 0x20000440ul);
406    if (res != -1)
407      r[3] = *(uint32_t*)0x20000450;
408    break;
409  case 12:
410    *(uint32_t*)0x200004c0 = 0;
411    *(uint32_t*)0x200004c4 = 0;
412    *(uint32_t*)0x200004c8 = 0;
413    *(uint32_t*)0x200004cc = r[2];
414    *(uint16_t*)0x200004d0 = 0x100;
415    *(uint16_t*)0x200004d2 = 8;
416    *(uint32_t*)0x200004d4 = 0;
417    *(uint64_t*)0x200004d8 = 0x7ff;
418    *(uint64_t*)0x200004e0 = 0x7f;
419    *(uint64_t*)0x200004e8 = 0x81;
420    *(uint64_t*)0x200004f0 = 0xfff;
421    *(uint64_t*)0x200004f8 = 0x3a;
422    *(uint64_t*)0x20000500 = 0x100000000;
423    *(uint64_t*)0x20000508 = 9;
424    *(uint32_t*)0x20000510 = r[1];
425    *(uint32_t*)0x20000514 = r[3];
426    *(uint64_t*)0x20000518 = 0;
427    *(uint64_t*)0x20000520 = 0;
428    syscall(SYS_msgctl, -1, 1ul, 0x200004c0ul);
429    break;
430  case 13:
431    syscall(SYS_ioctl, -1, 0xc0f24425ul, 0ul);
432    break;
433  }
434}
435int main(void)
436{
437  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
438  for (procid = 0; procid < 4; procid++) {
439    if (fork() == 0) {
440      use_temporary_dir();
441      do_sandbox_none();
442    }
443  }
444  sleep(1000000);
445  return 0;
446}
447EOF
448mycc -o /tmp/syzkaller52 -Wall -Wextra -O0 /tmp/syzkaller52.c -l pthread ||
449    exit 1
450
451start=`date +%s`
452while [ $((`date +%s` - start)) -lt 120 ]; do
453	(cd /tmp; timeout 3m ./syzkaller52)
454done
455
456rm -rf /tmp/syzkaller52 /tmp/syzkaller52.c /tmp/syzkaller52.core \
457    /tmp/syzkaller.??????
458exit 0
459