xref: /freebsd/tools/test/stress2/misc/syzkaller80.sh (revision d6ee73e5ad271638d54932479b7f2a31e74e78ad)
1#!/bin/sh
2
3# panic: ../../../kern/uipc_usrreq.c:1256: uipc_sosend_stream_or_seqpacket: Empty stailq 0xfffffe00ffe5fc88->stqh_last is 0xfffffe00ffe5fcd0, not head's first field address
4# cpuid = 5
5# time = 1749593630
6# KDB: stack backtrace:
7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00ffe5fab0
8# vpanic() at vpanic+0x136/frame 0xfffffe00ffe5fbe0
9# panic() at panic+0x43/frame 0xfffffe00ffe5fc40
10# uipc_sosend_stream_or_seqpacket() at uipc_sosend_stream_or_seqpacket+0xa39/frame 0xfffffe00ffe5fd10
11# sousrsend() at sousrsend+0x79/frame 0xfffffe00ffe5fd70
12# dofilewrite() at dofilewrite+0x81/frame 0xfffffe00ffe5fdc0
13# sys_writev() at sys_writev+0x69/frame 0xfffffe00ffe5fe00
14# amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe00ffe5ff30
15# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00ffe5ff30
16# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x82330181a, rsp = 0x8238dbf68, rbp = 0x8238dbf90 ---
17# KDB: enter: panic
18# [ thread pid 4484 tid 101524 ]
19# Stopped at      kdb_enter+0x33: movq    $0,0x122ebc2(%rip)
20# db> x/s version
21# version: FreeBSD 15.0-CURRENT #0 main-n277833-948078b65c27-dirty: Tue Jun 10 06:01:36 CEST 2025
22# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO
23# db>
24
25[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
26
27. ../default.cfg
28set -u
29prog=$(basename "$0" .sh)
30cat > /tmp/$prog.c <<EOF
31// https://syzkaller.appspot.com/bug?id=210ae0bfcef6324abfffbfaf10120b767106a990
32// autogenerated by syzkaller (https://github.com/google/syzkaller)
33// syzbot+cfcb8520b0071b548fba@syzkaller.appspotmail.com
34
35#define _GNU_SOURCE
36
37#include <sys/types.h>
38
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/syscall.h>
51#include <sys/wait.h>
52#include <time.h>
53#include <unistd.h>
54
55static unsigned long long procid;
56
57static void kill_and_wait(int pid, int* status)
58{
59  kill(pid, SIGKILL);
60  while (waitpid(-1, status, 0) != pid) {
61  }
62}
63
64static void sleep_ms(uint64_t ms)
65{
66  usleep(ms * 1000);
67}
68
69static uint64_t current_time_ms(void)
70{
71  struct timespec ts;
72  if (clock_gettime(CLOCK_MONOTONIC, &ts))
73    exit(1);
74  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
75}
76
77static void thread_start(void* (*fn)(void*), void* arg)
78{
79  pthread_t th;
80  pthread_attr_t attr;
81  pthread_attr_init(&attr);
82  pthread_attr_setstacksize(&attr, 128 << 10);
83  int i = 0;
84  for (; i < 100; i++) {
85    if (pthread_create(&th, &attr, fn, arg) == 0) {
86      pthread_attr_destroy(&attr);
87      return;
88    }
89    if (errno == EAGAIN) {
90      usleep(50);
91      continue;
92    }
93    break;
94  }
95  exit(1);
96}
97
98typedef struct {
99  pthread_mutex_t mu;
100  pthread_cond_t cv;
101  int state;
102} event_t;
103
104static void event_init(event_t* ev)
105{
106  if (pthread_mutex_init(&ev->mu, 0))
107    exit(1);
108  if (pthread_cond_init(&ev->cv, 0))
109    exit(1);
110  ev->state = 0;
111}
112
113static void event_reset(event_t* ev)
114{
115  ev->state = 0;
116}
117
118static void event_set(event_t* ev)
119{
120  pthread_mutex_lock(&ev->mu);
121  if (ev->state)
122    exit(1);
123  ev->state = 1;
124  pthread_mutex_unlock(&ev->mu);
125  pthread_cond_broadcast(&ev->cv);
126}
127
128static void event_wait(event_t* ev)
129{
130  pthread_mutex_lock(&ev->mu);
131  while (!ev->state)
132    pthread_cond_wait(&ev->cv, &ev->mu);
133  pthread_mutex_unlock(&ev->mu);
134}
135
136static int event_isset(event_t* ev)
137{
138  pthread_mutex_lock(&ev->mu);
139  int res = ev->state;
140  pthread_mutex_unlock(&ev->mu);
141  return res;
142}
143
144static int event_timedwait(event_t* ev, uint64_t timeout)
145{
146  uint64_t start = current_time_ms();
147  uint64_t now = start;
148  pthread_mutex_lock(&ev->mu);
149  for (;;) {
150    if (ev->state)
151      break;
152    uint64_t remain = timeout - (now - start);
153    struct timespec ts;
154    ts.tv_sec = remain / 1000;
155    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
156    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
157    now = current_time_ms();
158    if (now - start > timeout)
159      break;
160  }
161  int res = ev->state;
162  pthread_mutex_unlock(&ev->mu);
163  return res;
164}
165
166struct thread_t {
167  int created, call;
168  event_t ready, done;
169};
170
171static struct thread_t threads[16];
172static void execute_call(int call);
173static int running;
174
175static void* thr(void* arg)
176{
177  struct thread_t* th = (struct thread_t*)arg;
178  for (;;) {
179    event_wait(&th->ready);
180    event_reset(&th->ready);
181    execute_call(th->call);
182    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
183    event_set(&th->done);
184  }
185  return 0;
186}
187
188static void execute_one(void)
189{
190  if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
191  }
192  int i, call, thread;
193  for (call = 0; call < 5; call++) {
194    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
195         thread++) {
196      struct thread_t* th = &threads[thread];
197      if (!th->created) {
198        th->created = 1;
199        event_init(&th->ready);
200        event_init(&th->done);
201        event_set(&th->done);
202        thread_start(thr, th);
203      }
204      if (!event_isset(&th->done))
205        continue;
206      event_reset(&th->done);
207      th->call = call;
208      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
209      event_set(&th->ready);
210      if (call == 2)
211        break;
212      event_timedwait(&th->done, 50);
213      break;
214    }
215  }
216  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
217    sleep_ms(1);
218}
219
220static void execute_one(void);
221
222#define WAIT_FLAGS 0
223
224static void loop(void)
225{
226  int iter = 0;
227  for (;; iter++) {
228    int pid = fork();
229    if (pid < 0)
230      exit(1);
231    if (pid == 0) {
232      execute_one();
233      exit(0);
234    }
235    int status = 0;
236    uint64_t start = current_time_ms();
237    for (;;) {
238      sleep_ms(10);
239      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
240        break;
241      if (current_time_ms() - start < 5000)
242        continue;
243      kill_and_wait(pid, &status);
244      break;
245    }
246  }
247}
248
249uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
250
251void execute_call(int call)
252{
253  intptr_t res = 0;
254  switch (call) {
255  case 0:
256    res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_STREAM*/ 1ul,
257                  /*proto=*/0, /*fds=*/0x200000000040ul);
258    if (res != -1) {
259      r[0] = *(uint32_t*)0x200000000040;
260      r[1] = *(uint32_t*)0x200000000044;
261    }
262    break;
263  case 1:
264    memcpy((void*)0x200000000100, "\x09\x00\x10\x00", 4);
265    syscall(SYS_setsockopt, /*fd=*/r[1], /*level=*/0, /*optname=*/3,
266            /*optval=*/0x200000000100ul, /*optlen=*/4ul);
267    break;
268  case 2:
269    *(uint64_t*)0x2000000018c0 = 0;
270    *(uint32_t*)0x2000000018c8 = 0;
271    *(uint64_t*)0x2000000018d0 = 0;
272    *(uint64_t*)0x2000000018d8 = 0;
273    *(uint64_t*)0x2000000018e0 = 0x200000001880;
274    memcpy((void*)0x200000001880, "\x10\x00\x00\x00\xff\xff\x00\x00\x06", 9);
275    *(uint64_t*)0x2000000018e8 = 0x10;
276    *(uint32_t*)0x2000000018f0 = 0;
277    syscall(SYS_sendmsg, /*fd=*/r[0], /*msg=*/0x2000000018c0ul, /*f=*/0ul);
278    for (int i = 0; i < 64; i++) {
279      syscall(SYS_sendmsg, /*fd=*/r[0], /*msg=*/0x2000000018c0ul, /*f=*/0ul);
280    }
281    break;
282  case 3:
283    syscall(SYS_writev, /*fd=*/r[0], /*vec=*/0ul, /*vlen=*/0ul);
284    for (int i = 0; i < 64; i++) {
285      syscall(SYS_writev, /*fd=*/r[0], /*vec=*/0ul, /*vlen=*/0ul);
286    }
287    break;
288  case 4:
289    syscall(SYS_setsockopt, /*fd=*/(intptr_t)-1, /*level=*/0, /*optname=*/0xa,
290            /*optval=*/0ul, /*optlen=*/0ul);
291    break;
292  }
293}
294int main(void)
295{
296  syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul,
297          /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
298          /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul,
299          /*fd=*/(intptr_t)-1, /*offset=*/0ul);
300  const char* reason;
301  (void)reason;
302  for (procid = 0; procid < 4; procid++) {
303    if (fork() == 0) {
304      loop();
305    }
306  }
307  sleep(1000000);
308  return 0;
309}
310EOF
311mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1
312
313work=/tmp/$prog.dir
314rm -rf $work
315mkdir $work
316cd /tmp/$prog.dir
317timeout 3m /tmp/$prog > /dev/null 2>&1
318
319rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work
320exit 0
321