xref: /freebsd/tools/test/stress2/misc/syzkaller53.sh (revision 4543ef516683042d46f3bd3bb8a4f3f746e00499)
1#!/bin/sh
2
3# panic: Thread not suspended
4# cpuid = 9
5# time = 1651215111
6# KDB: stack backtrace:
7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe018701d9c0
8# vpanic() at vpanic+0x17f/frame 0xfffffe018701da10
9# panic() at panic+0x43/frame 0xfffffe018701da70
10# thread_unsuspend_one() at thread_unsuspend_one+0xc5/frame 0xfffffe018701daa0
11# thread_suspend_check() at thread_suspend_check+0x1f8/frame 0xfffffe018701dae0
12# exit1() at exit1+0xb7/frame 0xfffffe018701db50
13# sigexit() at sigexit+0x157/frame 0xfffffe018701de20
14# postsig() at postsig+0x1aa/frame 0xfffffe018701def0
15# ast() at ast+0x4fb/frame 0xfffffe018701df30
16# doreti_ast() at doreti_ast+0x1f/frame 0x820bf50f0
17# KDB: enter: panic
18# [ thread pid 8379 tid 100392 ]
19# Stopped at      kdb_enter+0x32: movq    $0,0x12790b3(%rip)
20# db> x/s version
21# FreeBSD 14.0-CURRENT #0 main-n255099-0923ff82fb383: Thu Apr 28 09:48:48 CEST 2022
22# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO
23# db>
24
25[ `uname -p` != "amd64" ] && exit 0
26
27. ../default.cfg
28cat > /tmp/syzkaller53.c <<EOF
29// https://syzkaller.appspot.com/bug?id=3b00c85aa7a7a1bad3bf0af3abde3c16b543f2a0
30// autogenerated by syzkaller (https://github.com/google/syzkaller)
31// Reported-by: syzbot+7789d9923f58fa08ecba@syzkaller.appspotmail.com
32
33#define _GNU_SOURCE
34
35#include <sys/types.h>
36
37#include <pwd.h>
38#include <setjmp.h>
39#include <signal.h>
40#include <stdarg.h>
41#include <stdbool.h>
42#include <stdint.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <sys/endian.h>
47#include <sys/syscall.h>
48#include <sys/wait.h>
49#include <time.h>
50#include <unistd.h>
51
52static __thread int clone_ongoing;
53static __thread int skip_segv;
54static __thread jmp_buf segv_env;
55
56static void segv_handler(int sig, siginfo_t* info, void* ctx __unused)
57{
58  if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
59    exit(sig);
60  }
61  uintptr_t addr = (uintptr_t)info->si_addr;
62  const uintptr_t prog_start = 1 << 20;
63  const uintptr_t prog_end = 100 << 20;
64  int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
65  int valid = addr < prog_start || addr > prog_end;
66  if (sig == SIGBUS)
67    valid = 1;
68  if (skip && valid) {
69    _longjmp(segv_env, 1);
70  }
71  exit(sig);
72}
73
74static void install_segv_handler(void)
75{
76  struct sigaction sa;
77  memset(&sa, 0, sizeof(sa));
78  sa.sa_sigaction = segv_handler;
79  sa.sa_flags = SA_NODEFER | SA_SIGINFO;
80  sigaction(SIGSEGV, &sa, NULL);
81  sigaction(SIGBUS, &sa, NULL);
82}
83
84#define NONFAILING(...)                                                        \
85  ({                                                                           \
86    int ok = 1;                                                                \
87    __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
88    if (_setjmp(segv_env) == 0) {                                              \
89      __VA_ARGS__;                                                             \
90    } else                                                                     \
91      ok = 0;                                                                  \
92    __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST);                       \
93    ok;                                                                        \
94  })
95
96static void kill_and_wait(int pid, int* status)
97{
98  kill(pid, SIGKILL);
99  while (waitpid(-1, status, 0) != pid) {
100  }
101}
102
103static void sleep_ms(uint64_t ms)
104{
105  usleep(ms * 1000);
106}
107
108static uint64_t current_time_ms(void)
109{
110  struct timespec ts;
111  if (clock_gettime(CLOCK_MONOTONIC, &ts))
112    exit(1);
113  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
114}
115
116static void execute_one(void);
117
118#define WAIT_FLAGS 0
119
120static void loop(void)
121{
122  int iter __unused = 0;
123  for (;; iter++) {
124    int pid = fork();
125    if (pid < 0)
126      exit(1);
127    if (pid == 0) {
128      execute_one();
129      exit(0);
130    }
131    int status = 0;
132    uint64_t start = current_time_ms();
133    for (;;) {
134      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
135        break;
136      sleep_ms(1);
137      if (current_time_ms() - start < 5000)
138        continue;
139      kill_and_wait(pid, &status);
140      break;
141    }
142  }
143}
144
145void execute_one(void)
146{
147  NONFAILING(*(uint32_t*)0x20000080 = 0x13);
148  NONFAILING(*(uint32_t*)0x20000084 = 0);
149  NONFAILING(*(uint32_t*)0x20000088 = 0);
150  NONFAILING(*(uint32_t*)0x2000008c = 0);
151  NONFAILING(*(uint32_t*)0x20000090 = -1);
152  NONFAILING(memset((void*)0x20000094, 0, 60));
153  syscall(SYS_procctl, 0ul, 0, 6ul, 0x20000080ul);
154}
155int main(void)
156{
157  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
158  install_segv_handler();
159  loop();
160  return 0;
161}
162EOF
163mycc -o /tmp/syzkaller53 -Wall -Wextra -O0 /tmp/syzkaller53.c ||
164    exit 1
165
166for i in `jot 20`; do
167	(cd /tmp; timeout 3m ./syzkaller53) &
168done
169wait
170
171rm -rf /tmp/syzkaller53 /tmp/syzkaller53.c /tmp/syzkaller53.*
172exit 0
173