xref: /freebsd/tools/test/stress2/misc/syzkaller86.sh (revision 257a750c60f14f83dff7bf5d2189089b1e74870b)
1#!/bin/sh
2
3# Fatal trap 12: page fault while in kernel mode
4# cpuid = 1; apic id = 01
5# fault virtual address   = 0x18
6# fault code              = supervisor read data, page not present
7# instruction pointer     = 0x20:0xffffffff80b69835
8# stack pointer           = 0x28:0xfffffe00ff8e7d90
9# frame pointer           = 0x28:0xfffffe00ff8e7d90
10# code segment            = base 0x0, limit 0xfffff, type 0x1b
11#                         = DPL 0, pres 1, long 1, def32 0, gran 1
12# processor eflags        = interrupt enabled, resume, IOPL = 0
13# current process         = 0 (thread taskq)
14# rdi: 0000000000000018 rsi: 0000000000000004 rdx: ffffffff812b3f65
15# rcx: 00000000000008ba  r8: fffff800044b8780  r9: fffff80003397000
16# rax: 0000000000000001 rbx: fffff8004221fa00 rbp: fffffe00ff8e7d90
17# r10: 0000000000000001 r11: fffffe00dc47b000 r12: fffffe0177ed0000
18# r13: fffff800044b8780 r14: fffff8004221f800 r15: fffff8004221f800
19# trap number             = 12
20# panic: page fault
21# cpuid = 1
22# time = 1759322830
23# KDB: stack backtrace:
24# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00ff8e7ac0
25# vpanic() at vpanic+0x136/frame 0xfffffe00ff8e7bf0
26# panic() at panic+0x43/frame 0xfffffe00ff8e7c50
27# trap_pfault() at trap_pfault+0x47c/frame 0xfffffe00ff8e7cc0
28# calltrap() at calltrap+0x8/frame 0xfffffe00ff8e7cc0
29# --- trap 0xc, rip = 0xffffffff80b69835, rsp = 0xfffffe00ff8e7d90, rbp = 0xfffffe00ff8e7d90 ---
30# __mtx_assert() at __mtx_assert+0x35/frame 0xfffffe00ff8e7d90
31# ktls_check_rx() at ktls_check_rx+0x2f/frame 0xfffffe00ff8e7dd0
32# socantrcvmore() at socantrcvmore+0x5e/frame 0xfffffe00ff8e7df0
33# unp_gc() at unp_gc+0x5df/frame 0xfffffe00ff8e7e40
34# taskqueue_run_locked() at taskqueue_run_locked+0x1c2/frame 0xfffffe00ff8e7ec0
35# taskqueue_thread_loop() at taskqueue_thread_loop+0xd3/frame 0xfffffe00ff8e7ef0
36# fork_exit() at fork_exit+0x82/frame 0xfffffe00ff8e7f30
37# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00ff8e7f30
38# --- trap 0, rip = 0, rsp = 0, rbp = 0 ---
39# KDB: enter: panic
40# [ thread pid 0 tid 100045 ]
41# Stopped at      kdb_enter+0x33: movq    $0,0x121a9e2(%rip)
42# db> x/s version
43# version: FreeBSD 16.0-CURRENT #0 vmfqe-n280784-b7f165e45d6d: Wed Oct  1 13:48:43 CEST 2025
44# pho@mercat1.netperf.freebsd.org:/var/tmp/deviant3/sys/amd64/compile/PHO
45# db>
46
47[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
48
49. ../default.cfg
50set -u
51prog=$(basename "$0" .sh)
52cat > /tmp/$prog.c <<EOF
53// https://syzkaller.appspot.com/bug?id=ec40fe3e3e2b41218d1d417bc10d0be2517bf751
54// autogenerated by syzkaller (https://github.com/google/syzkaller)
55// syzbot+a62883292a5c257703be@syzkaller.appspotmail.com
56
57#define _GNU_SOURCE
58
59#include <sys/types.h>
60
61#include <dirent.h>
62#include <errno.h>
63#include <pthread.h>
64#include <pwd.h>
65#include <signal.h>
66#include <stdarg.h>
67#include <stdbool.h>
68#include <stdint.h>
69#include <stdio.h>
70#include <stdlib.h>
71#include <string.h>
72#include <sys/endian.h>
73#include <sys/resource.h>
74#include <sys/stat.h>
75#include <sys/syscall.h>
76#include <sys/wait.h>
77#include <time.h>
78#include <unistd.h>
79
80static unsigned long long procid;
81
82static void kill_and_wait(int pid, int* status)
83{
84  kill(pid, SIGKILL);
85  while (waitpid(-1, status, 0) != pid) {
86  }
87}
88
89static void sleep_ms(uint64_t ms)
90{
91  usleep(ms * 1000);
92}
93
94static uint64_t current_time_ms(void)
95{
96  struct timespec ts;
97  if (clock_gettime(CLOCK_MONOTONIC, &ts))
98    exit(1);
99  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
100}
101
102static void use_temporary_dir(void)
103{
104  char tmpdir_template[] = "./syzkaller.XXXXXX";
105  char* tmpdir = mkdtemp(tmpdir_template);
106  if (!tmpdir)
107    exit(1);
108  if (chmod(tmpdir, 0777))
109    exit(1);
110  if (chdir(tmpdir))
111    exit(1);
112}
113
114static void reset_flags(const char* filename)
115{
116  struct stat st;
117  if (lstat(filename, &st))
118    exit(1);
119  st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE |
120                   SF_APPEND | UF_APPEND);
121  if (lchflags(filename, st.st_flags))
122    exit(1);
123}
124static void __attribute__((noinline)) remove_dir(const char* dir)
125{
126  DIR* dp = opendir(dir);
127  if (dp == NULL) {
128    if (errno == EACCES) {
129      if (rmdir(dir))
130        exit(1);
131      return;
132    }
133    exit(1);
134  }
135  struct dirent* ep = 0;
136  while ((ep = readdir(dp))) {
137    if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
138      continue;
139    char filename[FILENAME_MAX];
140    snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
141    struct stat st;
142    if (lstat(filename, &st))
143      exit(1);
144    if (S_ISDIR(st.st_mode)) {
145      remove_dir(filename);
146      continue;
147    }
148    if (unlink(filename)) {
149      if (errno == EPERM) {
150        reset_flags(filename);
151        reset_flags(dir);
152        if (unlink(filename) == 0)
153          continue;
154      }
155      exit(1);
156    }
157  }
158  closedir(dp);
159  while (rmdir(dir)) {
160    if (errno == EPERM) {
161      reset_flags(dir);
162      if (rmdir(dir) == 0)
163        break;
164    }
165    exit(1);
166  }
167}
168
169static void thread_start(void* (*fn)(void*), void* arg)
170{
171  pthread_t th;
172  pthread_attr_t attr;
173  pthread_attr_init(&attr);
174  pthread_attr_setstacksize(&attr, 128 << 10);
175  int i = 0;
176  for (; i < 100; i++) {
177    if (pthread_create(&th, &attr, fn, arg) == 0) {
178      pthread_attr_destroy(&attr);
179      return;
180    }
181    if (errno == EAGAIN) {
182      usleep(50);
183      continue;
184    }
185    break;
186  }
187  exit(1);
188}
189
190typedef struct {
191  pthread_mutex_t mu;
192  pthread_cond_t cv;
193  int state;
194} event_t;
195
196static void event_init(event_t* ev)
197{
198  if (pthread_mutex_init(&ev->mu, 0))
199    exit(1);
200  if (pthread_cond_init(&ev->cv, 0))
201    exit(1);
202  ev->state = 0;
203}
204
205static void event_reset(event_t* ev)
206{
207  ev->state = 0;
208}
209
210static void event_set(event_t* ev)
211{
212  pthread_mutex_lock(&ev->mu);
213  if (ev->state)
214    exit(1);
215  ev->state = 1;
216  pthread_mutex_unlock(&ev->mu);
217  pthread_cond_broadcast(&ev->cv);
218}
219
220static void event_wait(event_t* ev)
221{
222  pthread_mutex_lock(&ev->mu);
223  while (!ev->state)
224    pthread_cond_wait(&ev->cv, &ev->mu);
225  pthread_mutex_unlock(&ev->mu);
226}
227
228static int event_isset(event_t* ev)
229{
230  pthread_mutex_lock(&ev->mu);
231  int res = ev->state;
232  pthread_mutex_unlock(&ev->mu);
233  return res;
234}
235
236static int event_timedwait(event_t* ev, uint64_t timeout)
237{
238  uint64_t start = current_time_ms();
239  uint64_t now = start;
240  pthread_mutex_lock(&ev->mu);
241  for (;;) {
242    if (ev->state)
243      break;
244    uint64_t remain = timeout - (now - start);
245    struct timespec ts;
246    ts.tv_sec = remain / 1000;
247    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
248    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
249    now = current_time_ms();
250    if (now - start > timeout)
251      break;
252  }
253  int res = ev->state;
254  pthread_mutex_unlock(&ev->mu);
255  return res;
256}
257
258static void sandbox_common()
259{
260  struct rlimit rlim;
261  rlim.rlim_cur = rlim.rlim_max = 128 << 20;
262  setrlimit(RLIMIT_AS, &rlim);
263  rlim.rlim_cur = rlim.rlim_max = 8 << 20;
264  setrlimit(RLIMIT_MEMLOCK, &rlim);
265  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
266  setrlimit(RLIMIT_FSIZE, &rlim);
267  rlim.rlim_cur = rlim.rlim_max = 1 << 20;
268  setrlimit(RLIMIT_STACK, &rlim);
269  rlim.rlim_cur = rlim.rlim_max = 0;
270  setrlimit(RLIMIT_CORE, &rlim);
271  rlim.rlim_cur = rlim.rlim_max = 256;
272  setrlimit(RLIMIT_NOFILE, &rlim);
273}
274
275static void loop();
276
277static int do_sandbox_none(void)
278{
279  sandbox_common();
280  loop();
281  return 0;
282}
283
284struct thread_t {
285  int created, call;
286  event_t ready, done;
287};
288
289static struct thread_t threads[16];
290static void execute_call(int call);
291static int running;
292
293static void* thr(void* arg)
294{
295  struct thread_t* th = (struct thread_t*)arg;
296  for (;;) {
297    event_wait(&th->ready);
298    event_reset(&th->ready);
299    execute_call(th->call);
300    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
301    event_set(&th->done);
302  }
303  return 0;
304}
305
306static void execute_one(void)
307{
308  if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
309  }
310  int i, call, thread;
311  for (call = 0; call < 8; call++) {
312    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
313         thread++) {
314      struct thread_t* th = &threads[thread];
315      if (!th->created) {
316        th->created = 1;
317        event_init(&th->ready);
318        event_init(&th->done);
319        event_set(&th->done);
320        thread_start(thr, th);
321      }
322      if (!event_isset(&th->done))
323        continue;
324      event_reset(&th->done);
325      th->call = call;
326      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
327      event_set(&th->ready);
328      event_timedwait(&th->done, 50);
329      break;
330    }
331  }
332  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
333    sleep_ms(1);
334}
335
336static void execute_one(void);
337
338#define WAIT_FLAGS 0
339
340static void loop(void)
341{
342  int iter = 0;
343  for (;; iter++) {
344    char cwdbuf[32];
345    sprintf(cwdbuf, "./%d", iter);
346    if (mkdir(cwdbuf, 0777))
347      exit(1);
348    int pid = fork();
349    if (pid < 0)
350      exit(1);
351    if (pid == 0) {
352      if (chdir(cwdbuf))
353        exit(1);
354      execute_one();
355      exit(0);
356    }
357    int status = 0;
358    uint64_t start = current_time_ms();
359    for (;;) {
360      sleep_ms(10);
361      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
362        break;
363      if (current_time_ms() - start < 5000)
364        continue;
365      kill_and_wait(pid, &status);
366      break;
367    }
368    remove_dir(cwdbuf);
369  }
370}
371
372uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff};
373
374void execute_call(int call)
375{
376  intptr_t res = 0;
377  switch (call) {
378  case 0:
379    //  freebsd10_pipe arguments: [
380    //    pipefd: ptr[out, pipefd] {
381    //      pipefd {
382    //        rfd: fd (resource)
383    //        wfd: fd (resource)
384    //      }
385    //    }
386    //  ]
387    res = syscall(SYS_freebsd10_pipe, /*pipefd=*/0x2000000001c0ul);
388    if (res != -1)
389      r[0] = *(uint32_t*)0x2000000001c4;
390    break;
391  case 1:
392    //  close arguments: [
393    //    fd: fd (resource)
394    //  ]
395    syscall(SYS_close, /*fd=*/r[0]);
396    break;
397  case 2:
398    //  socket\$unix arguments: [
399    //    domain: const = 0x1 (8 bytes)
400    //    type: unix_socket_type = 0x5 (8 bytes)
401    //    proto: const = 0x0 (1 bytes)
402    //  ]
403    //  returns sock_unix
404    res = syscall(SYS_socket, /*domain=*/1ul, /*type=SOCK_SEQPACKET*/ 5ul,
405                  /*proto=*/0);
406    if (res != -1)
407      r[1] = res;
408    break;
409  case 3:
410    //  bind\$unix arguments: [
411    //    fd: sock_unix (resource)
412    //    addr: ptr[in, sockaddr_un] {
413    //      union sockaddr_un {
414    //        file: sockaddr_un_file {
415    //          len: len = 0xa (1 bytes)
416    //          family: unix_socket_family = 0x1 (1 bytes)
417    //          path: buffer: {2e 2f 66 69 6c 65 31 00} (length 0x8)
418    //        }
419    //      }
420    //    }
421    //    addrlen: len = 0xa (8 bytes)
422    //  ]
423    *(uint8_t*)0x2000000002c0 = 0xa;
424    *(uint8_t*)0x2000000002c1 = 1;
425    memcpy((void*)0x2000000002c2, "./file1\000", 8);
426    syscall(SYS_bind, /*fd=*/r[1], /*addr=*/0x2000000002c0ul,
427            /*addrlen=*/0xaul);
428    break;
429  case 4:
430    //  listen arguments: [
431    //    fd: sock (resource)
432    //    backlog: int32 = 0xfffffffe (4 bytes)
433    //  ]
434    syscall(SYS_listen, /*fd=*/r[1], /*backlog=*/0xfffffffe);
435    break;
436  case 5:
437    //  sendmsg\$unix arguments: [
438    //    fd: sock_unix (resource)
439    //    msg: ptr[in, msghdr_un] {
440    //      msghdr_un {
441    //        addr: nil
442    //        addrlen: len = 0x0 (4 bytes)
443    //        pad = 0x0 (4 bytes)
444    //        vec: nil
445    //        vlen: len = 0x0 (8 bytes)
446    //        ctrl: ptr[inout, array[ANYUNION]] {
447    //          array[ANYUNION] {
448    //            union ANYUNION {
449    //              ANYBLOB: buffer: {89 00 00 00 ff ff 00 00 01} (length 0x9)
450    //            }
451    //          }
452    //        }
453    //        ctrllen: bytesize = 0x9 (8 bytes)
454    //        f: send_flags = 0x0 (4 bytes)
455    //        pad = 0x0 (4 bytes)
456    //      }
457    //    }
458    //    f: send_flags = 0x0 (8 bytes)
459    //  ]
460    *(uint64_t*)0x200000000080 = 0;
461    *(uint32_t*)0x200000000088 = 0;
462    *(uint64_t*)0x200000000090 = 0;
463    *(uint64_t*)0x200000000098 = 0;
464    *(uint64_t*)0x2000000000a0 = 0x200000000000;
465    memcpy((void*)0x200000000000, "\x89\x00\x00\x00\xff\xff\x00\x00\x01", 9);
466    *(uint64_t*)0x2000000000a8 = 9;
467    *(uint32_t*)0x2000000000b0 = 0;
468    syscall(SYS_sendmsg, /*fd=*/(intptr_t)-1, /*msg=*/0x200000000080ul,
469            /*f=*/0ul);
470    break;
471  case 6:
472    //  socketpair\$unix arguments: [
473    //    domain: const = 0x1 (8 bytes)
474    //    type: unix_socket_type = 0x2 (8 bytes)
475    //    proto: const = 0x0 (1 bytes)
476    //    fds: ptr[out, unix_pair] {
477    //      unix_pair {
478    //        fd0: sock_unix (resource)
479    //        fd1: sock_unix (resource)
480    //      }
481    //    }
482    //  ]
483    res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_DGRAM*/ 2ul,
484                  /*proto=*/0, /*fds=*/0x200000000040ul);
485    if (res != -1)
486      r[2] = *(uint32_t*)0x200000000040;
487    break;
488  case 7:
489    //  sendmsg arguments: [
490    //    fd: sock (resource)
491    //    msg: ptr[in, send_msghdr] {
492    //      send_msghdr {
493    //        msg_name: nil
494    //        msg_namelen: len = 0x32c (4 bytes)
495    //        pad = 0x0 (4 bytes)
496    //        msg_iov: nil
497    //        msg_iovlen: len = 0x0 (8 bytes)
498    //        msg_control: ptr[in, array[cmsghdr]] {
499    //          array[cmsghdr] {
500    //          }
501    //        }
502    //        msg_controllen: bytesize = 0x90 (8 bytes)
503    //        msg_flags: const = 0x0 (4 bytes)
504    //        pad = 0x0 (4 bytes)
505    //      }
506    //    }
507    //    f: send_flags = 0x0 (8 bytes)
508    //  ]
509    *(uint64_t*)0x200000000380 = 0;
510    *(uint32_t*)0x200000000388 = 0x32c;
511    *(uint64_t*)0x200000000390 = 0;
512    *(uint64_t*)0x200000000398 = 0;
513    *(uint64_t*)0x2000000003a0 = 0x200000000000;
514    *(uint64_t*)0x2000000003a8 = 0x90;
515    *(uint32_t*)0x2000000003b0 = 0;
516    syscall(SYS_sendmsg, /*fd=*/r[2], /*msg=*/0x200000000380ul, /*f=*/0ul);
517    break;
518  }
519}
520int main(void)
521{
522  syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul,
523          /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
524          /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul,
525          /*fd=*/(intptr_t)-1, /*offset=*/0ul);
526  const char* reason;
527  (void)reason;
528  for (procid = 0; procid < 4; procid++) {
529    if (fork() == 0) {
530      use_temporary_dir();
531      do_sandbox_none();
532    }
533  }
534  sleep(1000000);
535  return 0;
536}
537EOF
538mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -pthread || exit 1
539
540work=/tmp/$prog.dir
541rm -rf $work
542mkdir $work
543cd /tmp/$prog.dir
544for i in `jot 30`; do
545	(
546		mkdir d$i
547		cd d$i
548		timeout 3m /tmp/$prog > /dev/null 2>&1 &
549	)
550done
551while pgrep -q $prog; do sleep 2; done
552wait
553
554rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core $work
555exit 0
556