xref: /freebsd/tools/test/stress2/misc/syzkaller11.sh (revision 7f658f99f7ed5d1d0e0802073bb22eb8a0a784fb)
18a272653SPeter Holm#!/bin/sh
28a272653SPeter Holm
38a272653SPeter Holm# panic: mtx_lock() of spin mutex (null) @ ../../../netinet/tcp_output.c:350
48a272653SPeter Holm# cpuid = 1
58a272653SPeter Holm# time = 1587276361
68a272653SPeter Holm# KDB: stack backtrace:
78a272653SPeter Holm# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01388956f0
88a272653SPeter Holm# vpanic() at vpanic+0x182/frame 0xfffffe0138895740
98a272653SPeter Holm# panic() at panic+0x43/frame 0xfffffe01388957a0
108a272653SPeter Holm# __mtx_lock_flags() at __mtx_lock_flags+0x13c/frame 0xfffffe01388957f0
118a272653SPeter Holm# tcp_output() at tcp_output+0x34e/frame 0xfffffe0138895980
128a272653SPeter Holm# tcp_usr_connect() at tcp_usr_connect+0x123/frame 0xfffffe01388959e0
138a272653SPeter Holm# soconnectat() at soconnectat+0xd0/frame 0xfffffe0138895a30
148a272653SPeter Holm# kern_connectat() at kern_connectat+0xe2/frame 0xfffffe0138895a90
158a272653SPeter Holm# sys_connect() at sys_connect+0x75/frame 0xfffffe0138895ad0
168a272653SPeter Holm# amd64_syscall() at amd64_syscall+0x159/frame 0xfffffe0138895bf0
178a272653SPeter Holm# fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe0138895bf0
188a272653SPeter Holm
198a272653SPeter Holm# Reproduced on r358885
208a272653SPeter Holm
218a272653SPeter Holm[ `uname -p` = "i386" ] && exit 0
228a272653SPeter Holm
238a272653SPeter Holm. ../default.cfg
248a272653SPeter Holmcat > /tmp/syzkaller11.c <<EOF
258a272653SPeter Holm// https://syzkaller.appspot.com/bug?id=f81a41d30e772445b13de6dcf07fc1afaf122a61
268a272653SPeter Holm// autogenerated by syzkaller (https://github.com/google/syzkaller)
278a272653SPeter Holm
288a272653SPeter Holm#define _GNU_SOURCE
298a272653SPeter Holm
308a272653SPeter Holm#include <sys/types.h>
318a272653SPeter Holm
328a272653SPeter Holm#include <errno.h>
338a272653SPeter Holm#include <pthread.h>
348a272653SPeter Holm#include <pwd.h>
358a272653SPeter Holm#include <signal.h>
368a272653SPeter Holm#include <stdarg.h>
378a272653SPeter Holm#include <stdbool.h>
388a272653SPeter Holm#include <stdint.h>
398a272653SPeter Holm#include <stdio.h>
408a272653SPeter Holm#include <stdlib.h>
418a272653SPeter Holm#include <string.h>
428a272653SPeter Holm#include <sys/endian.h>
438a272653SPeter Holm#include <sys/syscall.h>
448a272653SPeter Holm#include <sys/wait.h>
458a272653SPeter Holm#include <time.h>
468a272653SPeter Holm#include <unistd.h>
478a272653SPeter Holm
488a272653SPeter Holmstatic void kill_and_wait(int pid, int* status)
498a272653SPeter Holm{
508a272653SPeter Holm  kill(pid, SIGKILL);
518a272653SPeter Holm  while (waitpid(-1, status, 0) != pid) {
528a272653SPeter Holm  }
538a272653SPeter Holm}
548a272653SPeter Holm
558a272653SPeter Holmstatic void sleep_ms(uint64_t ms)
568a272653SPeter Holm{
578a272653SPeter Holm  usleep(ms * 1000);
588a272653SPeter Holm}
598a272653SPeter Holm
608a272653SPeter Holmstatic uint64_t current_time_ms(void)
618a272653SPeter Holm{
628a272653SPeter Holm  struct timespec ts;
638a272653SPeter Holm  if (clock_gettime(CLOCK_MONOTONIC, &ts))
648a272653SPeter Holm    exit(1);
658a272653SPeter Holm  return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
668a272653SPeter Holm}
678a272653SPeter Holm
688a272653SPeter Holmstatic void thread_start(void* (*fn)(void*), void* arg)
698a272653SPeter Holm{
708a272653SPeter Holm  pthread_t th;
718a272653SPeter Holm  pthread_attr_t attr;
728a272653SPeter Holm  pthread_attr_init(&attr);
738a272653SPeter Holm  pthread_attr_setstacksize(&attr, 128 << 10);
748a272653SPeter Holm  int i;
758a272653SPeter Holm  for (i = 0; i < 100; i++) {
768a272653SPeter Holm    if (pthread_create(&th, &attr, fn, arg) == 0) {
778a272653SPeter Holm      pthread_attr_destroy(&attr);
788a272653SPeter Holm      return;
798a272653SPeter Holm    }
808a272653SPeter Holm    if (errno == EAGAIN) {
818a272653SPeter Holm      usleep(50);
828a272653SPeter Holm      continue;
838a272653SPeter Holm    }
848a272653SPeter Holm    break;
858a272653SPeter Holm  }
868a272653SPeter Holm  exit(1);
878a272653SPeter Holm}
888a272653SPeter Holm
898a272653SPeter Holmtypedef struct {
908a272653SPeter Holm  pthread_mutex_t mu;
918a272653SPeter Holm  pthread_cond_t cv;
928a272653SPeter Holm  int state;
938a272653SPeter Holm} event_t;
948a272653SPeter Holm
958a272653SPeter Holmstatic void event_init(event_t* ev)
968a272653SPeter Holm{
978a272653SPeter Holm  if (pthread_mutex_init(&ev->mu, 0))
988a272653SPeter Holm    exit(1);
998a272653SPeter Holm  if (pthread_cond_init(&ev->cv, 0))
1008a272653SPeter Holm    exit(1);
1018a272653SPeter Holm  ev->state = 0;
1028a272653SPeter Holm}
1038a272653SPeter Holm
1048a272653SPeter Holmstatic void event_reset(event_t* ev)
1058a272653SPeter Holm{
1068a272653SPeter Holm  ev->state = 0;
1078a272653SPeter Holm}
1088a272653SPeter Holm
1098a272653SPeter Holmstatic void event_set(event_t* ev)
1108a272653SPeter Holm{
1118a272653SPeter Holm  pthread_mutex_lock(&ev->mu);
1128a272653SPeter Holm  if (ev->state)
1138a272653SPeter Holm    exit(1);
1148a272653SPeter Holm  ev->state = 1;
1158a272653SPeter Holm  pthread_mutex_unlock(&ev->mu);
1168a272653SPeter Holm  pthread_cond_broadcast(&ev->cv);
1178a272653SPeter Holm}
1188a272653SPeter Holm
1198a272653SPeter Holmstatic void event_wait(event_t* ev)
1208a272653SPeter Holm{
1218a272653SPeter Holm  pthread_mutex_lock(&ev->mu);
1228a272653SPeter Holm  while (!ev->state)
1238a272653SPeter Holm    pthread_cond_wait(&ev->cv, &ev->mu);
1248a272653SPeter Holm  pthread_mutex_unlock(&ev->mu);
1258a272653SPeter Holm}
1268a272653SPeter Holm
1278a272653SPeter Holmstatic int event_isset(event_t* ev)
1288a272653SPeter Holm{
1298a272653SPeter Holm  pthread_mutex_lock(&ev->mu);
1308a272653SPeter Holm  int res = ev->state;
1318a272653SPeter Holm  pthread_mutex_unlock(&ev->mu);
1328a272653SPeter Holm  return res;
1338a272653SPeter Holm}
1348a272653SPeter Holm
1358a272653SPeter Holmstatic int event_timedwait(event_t* ev, uint64_t timeout)
1368a272653SPeter Holm{
1378a272653SPeter Holm  uint64_t start = current_time_ms();
1388a272653SPeter Holm  uint64_t now = start;
1398a272653SPeter Holm  pthread_mutex_lock(&ev->mu);
1408a272653SPeter Holm  for (;;) {
1418a272653SPeter Holm    if (ev->state)
1428a272653SPeter Holm      break;
1438a272653SPeter Holm    uint64_t remain = timeout - (now - start);
1448a272653SPeter Holm    struct timespec ts;
1458a272653SPeter Holm    ts.tv_sec = remain / 1000;
1468a272653SPeter Holm    ts.tv_nsec = (remain % 1000) * 1000 * 1000;
1478a272653SPeter Holm    pthread_cond_timedwait(&ev->cv, &ev->mu, &ts);
1488a272653SPeter Holm    now = current_time_ms();
1498a272653SPeter Holm    if (now - start > timeout)
1508a272653SPeter Holm      break;
1518a272653SPeter Holm  }
1528a272653SPeter Holm  int res = ev->state;
1538a272653SPeter Holm  pthread_mutex_unlock(&ev->mu);
1548a272653SPeter Holm  return res;
1558a272653SPeter Holm}
1568a272653SPeter Holm
1578a272653SPeter Holmstruct thread_t {
1588a272653SPeter Holm  int created, call;
1598a272653SPeter Holm  event_t ready, done;
1608a272653SPeter Holm};
1618a272653SPeter Holm
1628a272653SPeter Holmstatic struct thread_t threads[16];
1638a272653SPeter Holmstatic void execute_call(int call);
1648a272653SPeter Holmstatic int running;
1658a272653SPeter Holm
1668a272653SPeter Holmstatic void* thr(void* arg)
1678a272653SPeter Holm{
1688a272653SPeter Holm  struct thread_t* th = (struct thread_t*)arg;
1698a272653SPeter Holm  for (;;) {
1708a272653SPeter Holm    event_wait(&th->ready);
1718a272653SPeter Holm    event_reset(&th->ready);
1728a272653SPeter Holm    execute_call(th->call);
1738a272653SPeter Holm    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
1748a272653SPeter Holm    event_set(&th->done);
1758a272653SPeter Holm  }
1768a272653SPeter Holm  return 0;
1778a272653SPeter Holm}
1788a272653SPeter Holm
1798a272653SPeter Holmstatic void execute_one(void)
1808a272653SPeter Holm{
1818a272653SPeter Holm  int i, call, thread;
1828a272653SPeter Holm  int collide = 0;
1838a272653SPeter Holmagain:
1848a272653SPeter Holm  for (call = 0; call < 4; call++) {
1858a272653SPeter Holm    for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
1868a272653SPeter Holm         thread++) {
1878a272653SPeter Holm      struct thread_t* th = &threads[thread];
1888a272653SPeter Holm      if (!th->created) {
1898a272653SPeter Holm        th->created = 1;
1908a272653SPeter Holm        event_init(&th->ready);
1918a272653SPeter Holm        event_init(&th->done);
1928a272653SPeter Holm        event_set(&th->done);
1938a272653SPeter Holm        thread_start(thr, th);
1948a272653SPeter Holm      }
1958a272653SPeter Holm      if (!event_isset(&th->done))
1968a272653SPeter Holm        continue;
1978a272653SPeter Holm      event_reset(&th->done);
1988a272653SPeter Holm      th->call = call;
1998a272653SPeter Holm      __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
2008a272653SPeter Holm      event_set(&th->ready);
2018a272653SPeter Holm      if (collide && (call % 2) == 0)
2028a272653SPeter Holm        break;
2038a272653SPeter Holm      event_timedwait(&th->done, 45);
2048a272653SPeter Holm      break;
2058a272653SPeter Holm    }
2068a272653SPeter Holm  }
2078a272653SPeter Holm  for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
2088a272653SPeter Holm    sleep_ms(1);
2098a272653SPeter Holm  if (!collide) {
2108a272653SPeter Holm    collide = 1;
2118a272653SPeter Holm    goto again;
2128a272653SPeter Holm  }
2138a272653SPeter Holm}
2148a272653SPeter Holm
2158a272653SPeter Holmstatic void execute_one(void);
2168a272653SPeter Holm
2178a272653SPeter Holm#define WAIT_FLAGS 0
2188a272653SPeter Holm
2198a272653SPeter Holmstatic void loop(void)
2208a272653SPeter Holm{
221*7f658f99SPeter Holm  int iter __unused;
2228a272653SPeter Holm  for (iter = 0;; iter++) {
2238a272653SPeter Holm    int pid = fork();
2248a272653SPeter Holm    if (pid < 0)
2258a272653SPeter Holm      exit(1);
2268a272653SPeter Holm    if (pid == 0) {
2278a272653SPeter Holm      execute_one();
2288a272653SPeter Holm      exit(0);
2298a272653SPeter Holm    }
2308a272653SPeter Holm    int status = 0;
2318a272653SPeter Holm    uint64_t start = current_time_ms();
2328a272653SPeter Holm    for (;;) {
2338a272653SPeter Holm      if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
2348a272653SPeter Holm        break;
2358a272653SPeter Holm      sleep_ms(1);
2368a272653SPeter Holm      if (current_time_ms() - start < 5 * 1000)
2378a272653SPeter Holm        continue;
2388a272653SPeter Holm      kill_and_wait(pid, &status);
2398a272653SPeter Holm      break;
2408a272653SPeter Holm    }
2418a272653SPeter Holm  }
2428a272653SPeter Holm}
2438a272653SPeter Holm
2448a272653SPeter Holmuint64_t r[1] = {0xffffffffffffffff};
2458a272653SPeter Holm
2468a272653SPeter Holmvoid execute_call(int call)
2478a272653SPeter Holm{
2488a272653SPeter Holm  intptr_t res;
2498a272653SPeter Holm  switch (call) {
2508a272653SPeter Holm  case 0:
2518a272653SPeter Holm    res = syscall(SYS_socket, 2ul, 1ul, 0);
2528a272653SPeter Holm    if (res != -1)
2538a272653SPeter Holm      r[0] = res;
2548a272653SPeter Holm    break;
2558a272653SPeter Holm  case 1:
2568a272653SPeter Holm    memcpy((void*)0x20000040,
2578a272653SPeter Holm           "bbr\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
2588a272653SPeter Holm           "\000\000\000\000\000\000\000\000\000\000\000\000\000",
2598a272653SPeter Holm           32);
2608a272653SPeter Holm    *(uint32_t*)0x20000060 = 0;
2618a272653SPeter Holm    syscall(SYS_setsockopt, r[0], 6, 0x2000, 0x20000040ul, 0x24ul);
2628a272653SPeter Holm    break;
2638a272653SPeter Holm  case 2:
2648a272653SPeter Holm    *(uint8_t*)0x20000180 = 0x10;
2658a272653SPeter Holm    *(uint8_t*)0x20000181 = 2;
2668a272653SPeter Holm    *(uint16_t*)0x20000182 = htobe16(0x4e22);
2678a272653SPeter Holm    *(uint32_t*)0x20000184 = htobe32(0xfff);
2688a272653SPeter Holm    *(uint8_t*)0x20000188 = 0;
2698a272653SPeter Holm    *(uint8_t*)0x20000189 = 0;
2708a272653SPeter Holm    *(uint8_t*)0x2000018a = 0;
2718a272653SPeter Holm    *(uint8_t*)0x2000018b = 0;
2728a272653SPeter Holm    *(uint8_t*)0x2000018c = 0;
2738a272653SPeter Holm    *(uint8_t*)0x2000018d = 0;
2748a272653SPeter Holm    *(uint8_t*)0x2000018e = 0;
2758a272653SPeter Holm    *(uint8_t*)0x2000018f = 0;
2768a272653SPeter Holm    syscall(SYS_connect, r[0], 0x20000180ul, 0x10ul);
2778a272653SPeter Holm    break;
2788a272653SPeter Holm  case 3:
2798a272653SPeter Holm    syscall(SYS_listen, r[0], 0);
2808a272653SPeter Holm    break;
2818a272653SPeter Holm  }
2828a272653SPeter Holm}
2838a272653SPeter Holmint main(void)
2848a272653SPeter Holm{
2858a272653SPeter Holm  syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul);
2868a272653SPeter Holm  loop();
2878a272653SPeter Holm  return 0;
2888a272653SPeter Holm}
2898a272653SPeter HolmEOF
2908a272653SPeter Holmmycc -o /tmp/syzkaller11 -Wall -Wextra -O2 /tmp/syzkaller11.c -lpthread ||
2918a272653SPeter Holm    exit 1
2928a272653SPeter Holm
2938a272653SPeter Holm(cd /tmp; ./syzkaller11) &
2948a272653SPeter Holmsleep 60
2958a272653SPeter Holmpkill -9 syzkaller11
2968a272653SPeter Holmwait
2978a272653SPeter Holm
2988a272653SPeter Holmrm -f /tmp/syzkaller11 /tmp/syzkaller11.c /tmp/syzkaller11.core
2998a272653SPeter Holmexit 0
300