xref: /freebsd/tools/test/stress2/misc/syzkaller13.sh (revision 7ef62cebc2f965b0f640263e179276928885e33d)
1#!/bin/sh
2
3# Kernel page fault with the following non-sleepable locks held:
4# exclusive sleep mutex so_rcv (so_rcv) r = 0 (0xfffffe012b5ee300) locked @ kern/uipc_usrreq.c:1272
5# exclusive sleep mutex socket (socket) r = 0 (0xfffffe012b5ee1a8) locked @ kern/uipc_usrreq.c:1265
6# shared rw unp_link_rwlock (unp_link_rwlock) r = 0 (0xffffffff81d99640) locked @ kern/uipc_usrreq.c:1334
7# stack backtrace:
8# #0 0xffffffff80c35701 at witness_debugger+0x71
9# #1 0xffffffff80c3669d at witness_warn+0x40d
10# #2 0xffffffff8106fb90 at trap_pfault+0x80
11# #3 0xffffffff8106f1a5 at trap+0x2a5
12# #4 0xffffffff810450d8 at calltrap+0x8
13# #5 0xffffffff80bc6fcc at sendfile_iodone+0x1ac
14# #6 0xffffffff80f3d98a at vnode_pager_generic_getpages_done_async+0x3a
15# #7 0xffffffff80c8236c at bufdone+0x6c
16# #8 0xffffffff80b0c06e at g_io_deliver+0x25e
17# #9 0xffffffff80b0c06e at g_io_deliver+0x25e
18# #10 0xffffffff80b08dfd at g_disk_done+0xed
19# #11 0xffffffff803ac1f3 at dadone+0x603
20# #12 0xffffffff8037ddf2 at xpt_done_process+0x382
21# #13 0xffffffff8037fdb5 at xpt_done_td+0xf5
22# #14 0xffffffff80b85b10 at fork_exit+0x80
23# #15 0xffffffff8104611e at fork_trampoline+0xe
24#
25#
26# Fatal trap 12: page fault while in kernel mode
27# cpuid = 23; apic id = 2b
28# fault virtual address   = 0x8
29# fault code              = supervisor read data, page not present
30# instruction pointer     = 0x20:0xffffffff80c74bc0
31# stack pointer           = 0x0:0xfffffe0126b118e0
32# frame pointer           = 0x0:0xfffffe0126b11920
33# code segment            = base 0x0, limit 0xfffff, type 0x1b
34#                         = DPL 0, pres 1, long 1, def32 0, gran 1
35# processor eflags        = interrupt enabled, resume, IOPL = 0
36# current process         = 32 (doneq0)
37# trap number             = 12
38# panic: page fault
39# cpuid = 23
40# time = 1591531029
41# KDB: stack backtrace:
42# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0126b11590
43# vpanic() at vpanic+0x182/frame 0xfffffe0126b115e0
44# panic() at panic+0x43/frame 0xfffffe0126b11640
45# trap_fatal() at trap_fatal+0x387/frame 0xfffffe0126b116a0
46# trap_pfault() at trap_pfault+0x99/frame 0xfffffe0126b11700
47# trap() at trap+0x2a5/frame 0xfffffe0126b11810
48# calltrap() at calltrap+0x8/frame 0xfffffe0126b11810
49# --- trap 0xc, rip = 0xffffffff80c74bc0, rsp = 0xfffffe0126b118e0, rbp = 0xfffffe0126b11920 ---
50# uipc_ready() at uipc_ready+0x1f0/frame 0xfffffe0126b11920
51# sendfile_iodone() at sendfile_iodone+0x1ac/frame 0xfffffe0126b11960
52# vnode_pager_generic_getpages_done_async() at vnode_pager_generic_getpages_done_async+0x3a/frame 0xfffffe0126b11980
53# bufdone() at bufdone+0x6c/frame 0xfffffe0126b119f0
54# g_io_deliver() at g_io_deliver+0x25e/frame 0xfffffe0126b11a40
55# g_io_deliver() at g_io_deliver+0x25e/frame 0xfffffe0126b11a90
56# g_disk_done() at g_disk_done+0xed/frame 0xfffffe0126b11ad0
57# dadone() at dadone+0x603/frame 0xfffffe0126b11b20
58# xpt_done_process() at xpt_done_process+0x382/frame 0xfffffe0126b11b60
59# xpt_done_td() at xpt_done_td+0xf5/frame 0xfffffe0126b11bb0
60# fork_exit() at fork_exit+0x80/frame 0xfffffe0126b11bf0
61# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe0126b11bf0
62# --- trap 0, rip = 0, rsp = 0, rbp = 0 ---
63# KDB: enter: panic
64# [ thread pid 32 tid 100163 ]
65# Stopped at      kdb_enter+0x37: movq    $0,0x10c72c6(%rip)
66# db>
67
68# Reproduced on r361889
69# Fixed by r363682
70
71[ `uname -p` = "i386" ] && exit 0
72
73. ../default.cfg
74cat > /tmp/syzkaller13.c <<EOF
75// https://syzkaller.appspot.com/bug?id=8a63fce7c52d85d6fca9aca543ce5a77cdd15f25
76// autogenerated by syzkaller (https://github.com/google/syzkaller)
77// Reported-by: syzbot+6a689cc9c27bd265237a@syzkaller.appspotmail.com
78
79#define _GNU_SOURCE
80
81#include <sys/types.h>
82
83#include <dirent.h>
84#include <pwd.h>
85#include <signal.h>
86#include <stdarg.h>
87#include <stdbool.h>
88#include <stdint.h>
89#include <stdio.h>
90#include <stdlib.h>
91#include <string.h>
92#include <sys/endian.h>
93#include <sys/stat.h>
94#include <sys/syscall.h>
95#include <sys/wait.h>
96#include <time.h>
97#include <unistd.h>
98
99static unsigned long long procid;
100
101static void kill_and_wait(int pid, int* status)
102{
103  kill(pid, SIGKILL);
104  while (waitpid(-1, status, 0) != pid) {
105  }
106}
107
108static void sleep_ms(uint64_t ms)
109{
110  usleep(ms * 1000);
111}
112
113static uint64_t current_time_ms(void)
114{
115  struct timespec ts;
116  if (clock_gettime(CLOCK_MONOTONIC, &ts))
117    exit(1);
118  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
119}
120
121static void use_temporary_dir(void)
122{
123  char tmpdir_template[] = "./syzkaller.XXXXXX";
124  char* tmpdir = mkdtemp(tmpdir_template);
125  if (!tmpdir)
126    exit(1);
127  if (chmod(tmpdir, 0777))
128    exit(1);
129  if (chdir(tmpdir))
130    exit(1);
131}
132
133static void remove_dir(const char* dir)
134{
135  DIR* dp;
136  struct dirent* ep;
137  dp = opendir(dir);
138  if (dp == NULL)
139    exit(1);
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      exit(1);
154  }
155  closedir(dp);
156  if (rmdir(dir))
157    exit(1);
158}
159
160static void execute_one(void);
161
162#define WAIT_FLAGS 0
163
164static void loop(void)
165{
166  int iter;
167  for (iter = 0;; iter++) {
168    char cwdbuf[32];
169    sprintf(cwdbuf, "./%d", iter);
170    if (mkdir(cwdbuf, 0777))
171      exit(1);
172    int pid = fork();
173    if (pid < 0)
174      exit(1);
175    if (pid == 0) {
176      if (chdir(cwdbuf))
177        exit(1);
178      execute_one();
179      exit(0);
180    }
181    int status = 0;
182    uint64_t start = current_time_ms();
183    for (;;) {
184      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
185        break;
186      sleep_ms(1);
187      if (current_time_ms() - start < 5 * 1000)
188        continue;
189      kill_and_wait(pid, &status);
190      break;
191    }
192    remove_dir(cwdbuf);
193  }
194}
195
196uint64_t r[5] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
197                 0xffffffffffffffff, 0xffffffffffffffff};
198
199void execute_one(void)
200{
201  intptr_t res = 0;
202  memcpy((void*)0x20000100, "./file0\000", 8);
203  res = syscall(SYS_open, 0x20000100ul, 0x40000400000002c2ul, 0ul);
204  if (res != -1)
205    r[0] = res;
206  syscall(SYS_fcntl, r[0], 4ul, 0x10048ul);
207  *(uint64_t*)0x20000340 = 0x20000180;
208  *(uint64_t*)0x20000348 = 0x81700;
209  syscall(SYS_writev, r[0], 0x20000340ul, 0x1000000000000013ul);
210  res = syscall(SYS_socket, 2ul, 2ul, 0x88);
211  if (res != -1)
212    r[1] = res;
213  res = syscall(SYS_socketpair, 1ul, 1ul, 0, 0x20000000ul);
214  if (res != -1)
215    r[2] = *(uint32_t*)0x20000000;
216  res = syscall(SYS_dup2, r[2], r[1]);
217  if (res != -1)
218    r[3] = res;
219  memcpy((void*)0x20000140, "./file0\000", 8);
220  res = syscall(SYS_open, 0x20000140ul, 0ul, 0ul);
221  if (res != -1)
222    r[4] = res;
223  syscall(SYS_sendfile, r[4], r[3], 0ul, 1ul, 0ul, 0ul, 0ul);
224}
225int main(void)
226{
227  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
228  for (procid = 0; procid < 4; procid++) {
229    if (fork() == 0) {
230      use_temporary_dir();
231      loop();
232    }
233  }
234  sleep(1000000);
235  return 0;
236}
237EOF
238mycc -o /tmp/syzkaller13 -Wall -Wextra -O2 /tmp/syzkaller13.c -lpthread ||
239    exit 1
240
241(cd ../testcases/swap; ./swap -t 1m -i 20 -h > /dev/null 2>&1) &
242(cd /tmp; ./syzkaller13) &
243sleep 60
244while pkill swap; do sleep .1; done
245pkill -9 syzkaller13
246wait
247
248rm -f /tmp/syzkaller13 /tmp/syzkaller13.* /tmp/file0
249exit 0
250