]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/test/stress2/misc/syzkaller14.sh
zfs: merge openzfs/zfs@4a1195ca5 (master) into main
[FreeBSD/FreeBSD.git] / tools / test / stress2 / misc / syzkaller14.sh
1 #!/bin/sh
2
3 # panic: mtx_lock() of spin mutex (null) @ ../../../kern/uipc_ktls.c:1034
4 # cpuid = 5
5 # time = 1591684934
6 # KDB: stack backtrace:
7 # db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe013a91b6c0
8 # vpanic() at vpanic+0x182/frame 0xfffffe013a91b710
9 # panic() at panic+0x43/frame 0xfffffe013a91b770
10 # __mtx_lock_flags() at __mtx_lock_flags+0x13c/frame 0xfffffe013a91b7c0
11 # ktls_get_rx_mode() at ktls_get_rx_mode+0x4e/frame 0xfffffe013a91b7f0
12 # tcp_default_ctloutput() at tcp_default_ctloutput+0x800/frame 0xfffffe013a91b960
13 # tcp_ctloutput() at tcp_ctloutput+0x1f5/frame 0xfffffe013a91b9d0
14 # sogetopt() at sogetopt+0x101/frame 0xfffffe013a91ba40
15 # kern_getsockopt() at kern_getsockopt+0xb4/frame 0xfffffe013a91baa0
16 # sys_getsockopt() at sys_getsockopt+0x52/frame 0xfffffe013a91bad0
17 # amd64_syscall() at amd64_syscall+0x159/frame 0xfffffe013a91bbf0
18 # fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe013a91bbf0
19 # --- syscall (0, FreeBSD ELF64, nosys), rip = 0x80045446a, rsp = 0x7fffdffdcf88, rbp = 0x7fffdffdcfc0 ---
20 # KDB: enter: panic
21 # [ thread pid 5313 tid 101679 ]
22 # Stopped at      kdb_enter+0x37: movq    $0,0x10c7fa6(%rip)
23 # db> x/s version
24 # version:        FreeBSD 13.0-CURRENT #0 r361886: Tue Jun  9 08:32:24 CEST 2020\012    pho@t2.osted.lan:/usr/src/sys/amd64/compile/KTLS\012
25 # db>
26
27 # Reproduced on r361886 with "options KERN_TLS"
28
29 [ `uname -p` = "i386" ] && exit 0
30
31 . ../default.cfg
32 cat > /tmp/syzkaller14.c <<EOF
33 // https://syzkaller.appspot.com/bug?id=d50164ce557a20a785510aac5d6f104d8a62e779
34 // autogenerated by syzkaller (https://github.com/google/syzkaller)
35 // Reported-by: syzbot+a8829e888a93a4a04619@syzkaller.appspotmail.com
36
37 #define _GNU_SOURCE
38
39 #include <sys/types.h>
40
41 #include <errno.h>
42 #include <pthread.h>
43 #include <pwd.h>
44 #include <signal.h>
45 #include <stdarg.h>
46 #include <stdbool.h>
47 #include <stdint.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <sys/endian.h>
52 #include <sys/syscall.h>
53 #include <sys/wait.h>
54 #include <time.h>
55 #include <unistd.h>
56
57 static unsigned long long procid;
58
59 static void kill_and_wait(int pid, int* status)
60 {
61   kill(pid, SIGKILL);
62   while (waitpid(-1, status, 0) != pid) {
63   }
64 }
65
66 static void sleep_ms(uint64_t ms)
67 {
68   usleep(ms * 1000);
69 }
70
71 static 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
79 static void thread_start(void* (*fn)(void*), void* arg)
80 {
81   pthread_t th;
82   pthread_attr_t attr;
83   pthread_attr_init(&attr);
84   pthread_attr_setstacksize(&attr, 128 << 10);
85   int i;
86   for (i = 0; i < 100; i++) {
87     if (pthread_create(&th, &attr, fn, arg) == 0) {
88       pthread_attr_destroy(&attr);
89       return;
90     }
91     if (errno == EAGAIN) {
92       usleep(50);
93       continue;
94     }
95     break;
96   }
97   exit(1);
98 }
99
100 typedef struct {
101   pthread_mutex_t mu;
102   pthread_cond_t cv;
103   int state;
104 } event_t;
105
106 static void event_init(event_t* ev)
107 {
108   if (pthread_mutex_init(&ev->mu, 0))
109     exit(1);
110   if (pthread_cond_init(&ev->cv, 0))
111     exit(1);
112   ev->state = 0;
113 }
114
115 static void event_reset(event_t* ev)
116 {
117   ev->state = 0;
118 }
119
120 static void event_set(event_t* ev)
121 {
122   pthread_mutex_lock(&ev->mu);
123   if (ev->state)
124     exit(1);
125   ev->state = 1;
126   pthread_mutex_unlock(&ev->mu);
127   pthread_cond_broadcast(&ev->cv);
128 }
129
130 static void event_wait(event_t* ev)
131 {
132   pthread_mutex_lock(&ev->mu);
133   while (!ev->state)
134     pthread_cond_wait(&ev->cv, &ev->mu);
135   pthread_mutex_unlock(&ev->mu);
136 }
137
138 static int event_isset(event_t* ev)
139 {
140   pthread_mutex_lock(&ev->mu);
141   int res = ev->state;
142   pthread_mutex_unlock(&ev->mu);
143   return res;
144 }
145
146 static int event_timedwait(event_t* ev, uint64_t timeout)
147 {
148   uint64_t start = current_time_ms();
149   uint64_t now = start;
150   pthread_mutex_lock(&ev->mu);
151   for (;;) {
152     if (ev->state)
153       break;
154     uint64_t remain = timeout - (now - start);
155     struct timespec ts;
156     ts.tv_sec = remain / 1000;
157     ts.tv_nsec = (remain % 1000) * 1000 * 1000;
158     pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
159     now = current_time_ms();
160     if (now - start > timeout)
161       break;
162   }
163   int res = ev->state;
164   pthread_mutex_unlock(&ev->mu);
165   return res;
166 }
167
168 struct thread_t {
169   int created, call;
170   event_t ready, done;
171 };
172
173 static struct thread_t threads[16];
174 static void execute_call(int call);
175 static int running;
176
177 static void* thr(void* arg)
178 {
179   struct thread_t* th = (struct thread_t*)arg;
180   for (;;) {
181     event_wait(&th->ready);
182     event_reset(&th->ready);
183     execute_call(th->call);
184     __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
185     event_set(&th->done);
186   }
187   return 0;
188 }
189
190 static void execute_one(void)
191 {
192   int i, call, thread;
193   int collide = 0;
194 again:
195   for (call = 0; call < 3; call++) {
196     for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
197          thread++) {
198       struct thread_t* th = &threads[thread];
199       if (!th->created) {
200         th->created = 1;
201         event_init(&th->ready);
202         event_init(&th->done);
203         event_set(&th->done);
204         thread_start(thr, th);
205       }
206       if (!event_isset(&th->done))
207         continue;
208       event_reset(&th->done);
209       th->call = call;
210       __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
211       event_set(&th->ready);
212       if (collide && (call % 2) == 0)
213         break;
214       event_timedwait(&th->done, 45);
215       break;
216     }
217   }
218   for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
219     sleep_ms(1);
220   if (!collide) {
221     collide = 1;
222     goto again;
223   }
224 }
225
226 static void execute_one(void);
227
228 #define WAIT_FLAGS 0
229
230 static void loop(void)
231 {
232   int iter;
233   for (iter = 0;; iter++) {
234     int pid = fork();
235     if (pid < 0)
236       exit(1);
237     if (pid == 0) {
238       execute_one();
239       exit(0);
240     }
241     int status = 0;
242     uint64_t start = current_time_ms();
243     for (;;) {
244       if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
245         break;
246       sleep_ms(1);
247       if (current_time_ms() - start < 5 * 1000)
248         continue;
249       kill_and_wait(pid, &status);
250       break;
251     }
252   }
253 }
254
255 uint64_t r[1] = {0xffffffffffffffff};
256
257 void execute_call(int call)
258 {
259   intptr_t res = 0;
260   switch (call) {
261   case 0:
262     res = syscall(SYS_socket, 0x1cul, 1ul, 0);
263     if (res != -1)
264       r[0] = res;
265     break;
266   case 1:
267     syscall(SYS_getsockopt, r[0], 6, 0x2a, 0ul, 0ul);
268     break;
269   case 2:
270     syscall(SYS_listen, r[0], 1);
271     break;
272   }
273 }
274 int main(void)
275 {
276   syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
277   for (procid = 0; procid < 4; procid++) {
278     if (fork() == 0) {
279       loop();
280     }
281   }
282   sleep(1000000);
283   return 0;
284 }
285 EOF
286 mycc -o /tmp/syzkaller14 -Wall -Wextra -O2 /tmp/syzkaller14.c -lpthread ||
287     exit 1
288
289 (cd /tmp; ./syzkaller14) &
290 sleep 60
291 pkill -9 syzkaller14
292 wait
293
294 rm -f /tmp/syzkaller14 /tmp/syzkaller14.c /tmp/syzkaller14.core
295 exit 0