xref: /freebsd/tools/test/stress2/misc/syzkaller73.sh (revision ef777be98543f7daae90bd123d4fc1ec4a54efc2)
1#!/bin/sh
2
3# No issues seen (Looks a bit like syzkaller43.sh)
4
5[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
6
7. ../default.cfg
8set -u
9prog=$(basename "$0" .sh)
10cat > /tmp/$prog.c <<EOF
11// https://syzkaller.appspot.com/bug?id=cf4c0a08d26692dc8f22b0fcc50db08fd17dd709
12// autogenerated by syzkaller (https://github.com/google/syzkaller)
13
14#define _GNU_SOURCE
15
16#include <sys/types.h>
17
18#include <dirent.h>
19#include <errno.h>
20#include <pthread.h>
21#include <pwd.h>
22#include <setjmp.h>
23#include <signal.h>
24#include <stdarg.h>
25#include <stdbool.h>
26#include <stdint.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/endian.h>
31#include <sys/resource.h>
32#include <sys/stat.h>
33#include <sys/syscall.h>
34#include <sys/wait.h>
35#include <time.h>
36#include <unistd.h>
37
38#ifndef SYS_aio_writev
39#define SYS_aio_writev 578
40#endif
41
42static __thread int clone_ongoing;
43static __thread int skip_segv;
44static __thread jmp_buf segv_env;
45
46static void segv_handler(int sig, siginfo_t* info, void* ctx __unused)
47{
48  if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
49    exit(sig);
50  }
51  uintptr_t addr = (uintptr_t)info->si_addr;
52  const uintptr_t prog_start = 1 << 20;
53  const uintptr_t prog_end = 100 << 20;
54  int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
55  int valid = addr < prog_start || addr > prog_end;
56  if (sig == SIGBUS)
57    valid = 1;
58  if (skip && valid) {
59    _longjmp(segv_env, 1);
60  }
61  exit(sig);
62}
63
64static void install_segv_handler(void)
65{
66  struct sigaction sa;
67  memset(&sa, 0, sizeof(sa));
68  sa.sa_sigaction = segv_handler;
69  sa.sa_flags = SA_NODEFER | SA_SIGINFO;
70  sigaction(SIGSEGV, &sa, NULL);
71  sigaction(SIGBUS, &sa, NULL);
72}
73
74#define NONFAILING(...)                                                        \
75  ({                                                                           \
76    int ok = 1;                                                                \
77    __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
78    if (_setjmp(segv_env) == 0) {                                              \
79      __VA_ARGS__;                                                             \
80    } else                                                                     \
81      ok = 0;                                                                  \
82    __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
83    ok;                                                                        \
84  })
85
86static void kill_and_wait(int pid, int* status)
87{
88  kill(pid, SIGKILL);
89  while (waitpid(-1, status, 0) != pid) {
90  }
91}
92
93static void sleep_ms(uint64_t ms)
94{
95  usleep(ms * 1000);
96}
97
98static uint64_t current_time_ms(void)
99{
100  struct timespec ts;
101  if (clock_gettime(CLOCK_MONOTONIC, &ts))
102    exit(1);
103  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
104}
105
106static void use_temporary_dir(void)
107{
108  char tmpdir_template[] = "./syzkaller.XXXXXX";
109  char* tmpdir = mkdtemp(tmpdir_template);
110  if (!tmpdir)
111    exit(1);
112  if (chmod(tmpdir, 0777))
113    exit(1);
114  if (chdir(tmpdir))
115    exit(1);
116}
117
118static void reset_flags(const char* filename)
119{
120  struct stat st;
121  if (lstat(filename, &st))
122    exit(1);
123  st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE |
124                   SF_APPEND | UF_APPEND);
125  if (lchflags(filename, st.st_flags))
126    exit(1);
127}
128static void __attribute__((noinline)) remove_dir(const char* dir)
129{
130  DIR* dp = opendir(dir);
131  if (dp == NULL) {
132    if (errno == EACCES) {
133      if (rmdir(dir))
134        exit(1);
135      return;
136    }
137    exit(1);
138  }
139  struct dirent* ep = 0;
140  while ((ep = readdir(dp))) {
141    if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
142      continue;
143    char filename[FILENAME_MAX];
144    snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
145    struct stat st;
146    if (lstat(filename, &st))
147      exit(1);
148    if (S_ISDIR(st.st_mode)) {
149      remove_dir(filename);
150      continue;
151    }
152    if (unlink(filename)) {
153      if (errno == EPERM) {
154        reset_flags(filename);
155        reset_flags(dir);
156        if (unlink(filename) == 0)
157          continue;
158      }
159      exit(1);
160    }
161  }
162  closedir(dp);
163  while (rmdir(dir)) {
164    if (errno == EPERM) {
165      reset_flags(dir);
166      if (rmdir(dir) == 0)
167        break;
168    }
169    exit(1);
170  }
171}
172
173static void thread_start(void* (*fn)(void*), void* arg)
174{
175  pthread_t th;
176  pthread_attr_t attr;
177  pthread_attr_init(&attr);
178  pthread_attr_setstacksize(&attr, 128 << 10);
179  int i = 0;
180  for (; i < 100; i++) {
181    if (pthread_create(&th, &attr, fn, arg) == 0) {
182      pthread_attr_destroy(&attr);
183      return;
184    }
185    if (errno == EAGAIN) {
186      usleep(50);
187      continue;
188    }
189    break;
190  }
191  exit(1);
192}
193
194typedef struct {
195  pthread_mutex_t mu;
196  pthread_cond_t cv;
197  int state;
198} event_t;
199
200static void event_init(event_t* ev)
201{
202  if (pthread_mutex_init(&ev->mu, 0))
203    exit(1);
204  if (pthread_cond_init(&ev->cv, 0))
205    exit(1);
206  ev->state = 0;
207}
208
209static void event_reset(event_t* ev)
210{
211  ev->state = 0;
212}
213
214static void event_set(event_t* ev)
215{
216  pthread_mutex_lock(&ev->mu);
217  if (ev->state)
218    exit(1);
219  ev->state = 1;
220  pthread_mutex_unlock(&ev->mu);
221  pthread_cond_broadcast(&ev->cv);
222}
223
224static void event_wait(event_t* ev)
225{
226  pthread_mutex_lock(&ev->mu);
227  while (!ev->state)
228    pthread_cond_wait(&ev->cv, &ev->mu);
229  pthread_mutex_unlock(&ev->mu);
230}
231
232static int event_isset(event_t* ev)
233{
234  pthread_mutex_lock(&ev->mu);
235  int res = ev->state;
236  pthread_mutex_unlock(&ev->mu);
237  return res;
238}
239
240static int event_timedwait(event_t* ev, uint64_t timeout)
241{
242  uint64_t start = current_time_ms();
243  uint64_t now = start;
244  pthread_mutex_lock(&ev->mu);
245  for (;;) {
246    if (ev->state)
247      break;
248    uint64_t remain = timeout - (now - start);
249    struct timespec ts;
250    ts.tv_sec = remain / 1000;
251    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
252    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
253    now = current_time_ms();
254    if (now - start > timeout)
255      break;
256  }
257  int res = ev->state;
258  pthread_mutex_unlock(&ev->mu);
259  return res;
260}
261
262static void sandbox_common()
263{
264  struct rlimit rlim;
265  rlim.rlim_cur = rlim.rlim_max = 128 << 20;
266  setrlimit(RLIMIT_AS, &rlim);
267  rlim.rlim_cur = rlim.rlim_max = 8 << 20;
268  setrlimit(RLIMIT_MEMLOCK, &rlim);
269  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
270  setrlimit(RLIMIT_FSIZE, &rlim);
271  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
272  setrlimit(RLIMIT_STACK, &rlim);
273  rlim.rlim_cur = rlim.rlim_max = 0;
274  setrlimit(RLIMIT_CORE, &rlim);
275  rlim.rlim_cur = rlim.rlim_max = 256;
276  setrlimit(RLIMIT_NOFILE, &rlim);
277}
278
279static void loop();
280
281static int do_sandbox_none(void)
282{
283  sandbox_common();
284  loop();
285  return 0;
286}
287
288struct thread_t {
289  int created, call;
290  event_t ready, done;
291};
292
293static struct thread_t threads[16];
294static void execute_call(int call);
295static int running;
296
297static void* thr(void* arg)
298{
299  struct thread_t* th = (struct thread_t*)arg;
300  for (;;) {
301    event_wait(&th->ready);
302    event_reset(&th->ready);
303    execute_call(th->call);
304    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
305    event_set(&th->done);
306  }
307  return 0;
308}
309
310static void execute_one(void)
311{
312  if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
313  }
314  int i, call, thread;
315  for (call = 0; call < 24; call++) {
316    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
317         thread++) {
318      struct thread_t* th = &threads[thread];
319      if (!th->created) {
320        th->created = 1;
321        event_init(&th->ready);
322        event_init(&th->done);
323        event_set(&th->done);
324        thread_start(thr, th);
325      }
326      if (!event_isset(&th->done))
327        continue;
328      event_reset(&th->done);
329      th->call = call;
330      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
331      event_set(&th->ready);
332      event_timedwait(&th->done, 50);
333      break;
334    }
335  }
336  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
337    sleep_ms(1);
338}
339
340static void execute_one(void);
341
342#define WAIT_FLAGS 0
343
344static void loop(void)
345{
346  int iter = 0;
347  for (;; iter++) {
348    char cwdbuf[32];
349    sprintf(cwdbuf, "./%d", iter);
350    if (mkdir(cwdbuf, 0777))
351      exit(1);
352    int pid = fork();
353    if (pid < 0)
354      exit(1);
355    if (pid == 0) {
356      if (chdir(cwdbuf))
357        exit(1);
358      execute_one();
359      exit(0);
360    }
361    int status = 0;
362    uint64_t start = current_time_ms();
363    for (;;) {
364      sleep_ms(10);
365      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
366        break;
367      if (current_time_ms() - start < 5000)
368        continue;
369      kill_and_wait(pid, &status);
370      break;
371    }
372    remove_dir(cwdbuf);
373  }
374}
375
376uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff};
377
378void execute_call(int call)
379{
380  intptr_t res = 0;
381  switch (call) {
382  case 0:
383    res = syscall(SYS_socket, /*domain=AF_INET6*/ 0x1cul,
384                  /*type=SOCK_STREAM*/ 1ul, /*proto=*/0);
385    if (res != -1)
386      r[0] = res;
387    break;
388  case 1:
389    NONFAILING(*(uint32_t*)0x200000c0 = 0x101);
390    syscall(SYS_setsockopt, /*fd=*/r[0], /*level=*/0xffff,
391            /*optname=SO_SNDBUF*/ 0x1001, /*optval=*/0x200000c0ul,
392            /*optlen=*/4ul);
393    break;
394  case 2:
395    NONFAILING(*(uint8_t*)0x20000140 = 0x1c);
396    NONFAILING(*(uint8_t*)0x20000141 = 0x1c);
397    NONFAILING(*(uint16_t*)0x20000142 = htobe16(0x4e23));
398    NONFAILING(*(uint32_t*)0x20000144 = 0);
399    NONFAILING(memset((void*)0x20000148, 0, 16));
400    NONFAILING(*(uint32_t*)0x20000158 = 0);
401    syscall(SYS_bind, /*fd=*/r[0], /*addr=*/0x20000140ul, /*addrlen=*/0x1cul);
402    break;
403  case 3:
404    NONFAILING(*(uint32_t*)0x20000500 = r[0]);
405    NONFAILING(*(uint64_t*)0x20000508 = 0);
406    NONFAILING(*(uint64_t*)0x20000510 = 0);
407    NONFAILING(*(uint64_t*)0x20000518 = 0);
408    NONFAILING(*(uint32_t*)0x20000520 = 4);
409    NONFAILING(*(uint32_t*)0x20000524 = 0);
410    NONFAILING(*(uint64_t*)0x20000528 = 0);
411    NONFAILING(*(uint32_t*)0x20000530 = 0);
412    NONFAILING(*(uint32_t*)0x20000534 = 4);
413    NONFAILING(*(uint64_t*)0x20000538 = 0x822e);
414    NONFAILING(*(uint64_t*)0x20000540 = 0);
415    NONFAILING(*(uint64_t*)0x20000548 = 0x20000340);
416    NONFAILING(*(uint32_t*)0x20000550 = 0);
417    NONFAILING(*(uint32_t*)0x20000554 = 0);
418    NONFAILING(*(uint64_t*)0x20000558 = 0xfffffffffffffffe);
419    NONFAILING(*(uint64_t*)0x20000560 = 0);
420    NONFAILING(*(uint64_t*)0x20000568 = 0x20000380);
421    NONFAILING(memcpy((void*)0x20000380, "\x3c\x88\x80", 3));
422    syscall(SYS_aio_writev, /*iocb=*/0x20000500ul);
423    break;
424  case 4:
425    NONFAILING(*(uint8_t*)0x20000180 = 0x1c);
426    NONFAILING(*(uint8_t*)0x20000181 = 0x1c);
427    NONFAILING(*(uint16_t*)0x20000182 = htobe16(0x4e23));
428    NONFAILING(*(uint32_t*)0x20000184 = 0);
429    NONFAILING(memset((void*)0x20000188, 0, 16));
430    NONFAILING(*(uint32_t*)0x20000198 = 0);
431    syscall(SYS_connect, /*fd=*/r[0], /*addr=*/0x20000180ul,
432            /*addrlen=*/0x1cul);
433    break;
434  case 5:
435    NONFAILING(memset((void*)0x20000200, 14, 1));
436    syscall(SYS_sendto, /*fd=*/r[0], /*buf=*/0x20000200ul, /*len=*/0xff66ul,
437            /*f=*/0ul, /*addr=*/0ul, /*addrlen=*/0ul);
438    break;
439  case 6:
440    syscall(SYS_sendmsg, /*fd=*/r[0], /*msg=*/0ul, /*f=*/0ul);
441    break;
442  case 7:
443    syscall(SYS_socket, /*domain=AF_INET*/ 2ul, /*type=SOCK_STREAM*/ 1ul,
444            /*proto=*/0);
445    break;
446  case 8:
447    res = syscall(SYS_socket, /*domain=*/2ul, /*type=SOCK_SEQPACKET*/ 5ul,
448                  /*proto=*/0x84);
449    if (res != -1)
450      r[1] = res;
451    break;
452  case 9:
453    syscall(SYS_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0ul,
454            /*flags=O_RDWR*/ 2ul, /*mode=*/0ul);
455    break;
456  case 10:
457    syscall(SYS_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0ul,
458            /*flags=O_RDWR*/ 2ul, /*mode=*/0ul);
459    break;
460  case 11:
461    syscall(SYS_socket, /*domain=*/2ul, /*type=SOCK_SEQPACKET*/ 5ul,
462            /*proto=*/0x84);
463    break;
464  case 12:
465    syscall(SYS_socket, /*domain=*/0x1cul, /*type=*/1ul, /*proto=*/0);
466    break;
467  case 13:
468    syscall(SYS_shutdown, /*fd=*/-1, /*how=*/0ul);
469    break;
470  case 14:
471    syscall(SYS_shutdown, /*fd=*/-1, /*how=*/0ul);
472    break;
473  case 15:
474    syscall(SYS_sendto, /*fd=*/-1, /*buf=*/0ul, /*len=*/0ul, /*f=*/0ul,
475            /*addr=*/0ul, /*addrlen=*/0ul);
476    break;
477  case 16:
478    syscall(SYS_sendmsg, /*fd=*/-1, /*msg=*/0ul, /*f=*/0ul);
479    break;
480  case 17:
481    syscall(SYS_rfork, /*flags=RFMEM|RFTHREAD|RFCFDG|RFNOWAIT*/ 0x3060ul);
482    break;
483  case 18:
484    syscall(SYS_rfork, /*flags=RFMEM|RFTHREAD|RFCFDG|RFNOWAIT*/ 0x3060ul);
485    break;
486  case 19:
487    syscall(SYS_openat, /*fd=*/0xffffff9cul, /*file=*/0ul,
488            /*flags=O_APPEND*/ 8ul, /*mode=*/0ul);
489    break;
490  case 20:
491    syscall(SYS_openat, /*fd=*/0xffffff9cul, /*file=*/0ul,
492            /*flags=O_APPEND*/ 8ul, /*mode=*/0ul);
493    break;
494  case 21:
495    syscall(SYS_connect, /*fd=*/r[1], /*addr=*/0ul, /*addrlen=*/0ul);
496    break;
497  case 22:
498    res = syscall(SYS_socket, /*domain=*/2ul, /*type=SOCK_STREAM*/ 1ul,
499                  /*proto=*/0x84);
500    if (res != -1)
501      r[2] = res;
502    break;
503  case 23:
504    NONFAILING(*(uint32_t*)0x200001c0 = 0);
505    syscall(SYS_getsockopt, /*fd=*/r[2], /*level=*/0x84, /*opt=*/0xc,
506            /*val=*/0ul, /*len=*/0x200001c0ul);
507    break;
508  }
509}
510int main(void)
511{
512  syscall(SYS_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul,
513          /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
514          /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, /*fd=*/-1,
515          /*offset=*/0ul);
516  const char* reason;
517  (void)reason;
518  install_segv_handler();
519  use_temporary_dir();
520  do_sandbox_none();
521  return 0;
522}
523EOF
524mycc -o /tmp/$prog -m32 -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1
525
526(cd ../testcases/swap; ./swap -t 2m -i 10 -l 100 > /dev/null 2>&1) &
527sleep 1
528cd /tmp
529start=`date +%s`
530while [ $((`date +%s` - start)) -lt 120 ]; do
531	timeout 3m /tmp/$prog > /dev/null 2>&1
532done
533while pkill swap; do :; done
534wait
535
536rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core
537exit 0
538