15b42ac29SPeter Holm#!/bin/sh 25b42ac29SPeter Holm 35b42ac29SPeter Holm# Seen: 45b42ac29SPeter Holm# [root@mercat1 /usr/src/tools/test/stress2/misc]# pgrep syzkaller61 | xargs procstat -k 55b42ac29SPeter Holm# PID TID COMM TDNAME KSTACK 65b42ac29SPeter Holm# 13332 106396 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast 75b42ac29SPeter Holm# 13332 560662 syzkaller61 - mi_switch sleepq_switch sleepq_catch_signals sleepq_wait_sig _sleep umtxq_sleep do_wait __umtx_op_wait_uint_private sys__umtx_op amd64_syscall fast_syscall_common 85b42ac29SPeter Holm# 13332 560776 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common 95b42ac29SPeter Holm# 13662 356440 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast 105b42ac29SPeter Holm# 13662 561098 syzkaller61 - mi_switch sleepq_switch sleepq_catch_signals sleepq_wait_sig _sleep umtxq_sleep do_wait __umtx_op_wait_uint_private sys__umtx_op amd64_syscall fast_syscall_common 115b42ac29SPeter Holm# 13662 561160 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common 125b42ac29SPeter Holm# [root@mercat1 /usr/src/tools/test/stress2/misc]# 135b42ac29SPeter Holm 145b42ac29SPeter Holm[ `uname -p` != "amd64" ] && exit 0 155b42ac29SPeter Holm 165b42ac29SPeter Holm. ../default.cfg 175b42ac29SPeter Holmcat > /tmp/syzkaller61.c <<EOF 185b42ac29SPeter Holm// https://syzkaller.appspot.com/bug?id=00d8ca63243899ffb67b15ec93aee4ffa2f06637 195b42ac29SPeter Holm// autogenerated by syzkaller (https://github.com/google/syzkaller) 205b42ac29SPeter Holm// Reported-by: syzbot+647212368c3f32c6f13f@syzkaller.appspotmail.com 215b42ac29SPeter Holm 225b42ac29SPeter Holm#define _GNU_SOURCE 235b42ac29SPeter Holm 245b42ac29SPeter Holm#include <sys/types.h> 255b42ac29SPeter Holm 265b42ac29SPeter Holm#include <errno.h> 275b42ac29SPeter Holm#include <pthread.h> 285b42ac29SPeter Holm#include <pwd.h> 295b42ac29SPeter Holm#include <setjmp.h> 305b42ac29SPeter Holm#include <signal.h> 315b42ac29SPeter Holm#include <stdarg.h> 325b42ac29SPeter Holm#include <stdbool.h> 335b42ac29SPeter Holm#include <stdint.h> 345b42ac29SPeter Holm#include <stdio.h> 355b42ac29SPeter Holm#include <stdlib.h> 365b42ac29SPeter Holm#include <string.h> 375b42ac29SPeter Holm#include <sys/endian.h> 385b42ac29SPeter Holm#include <sys/syscall.h> 395b42ac29SPeter Holm#include <sys/wait.h> 405b42ac29SPeter Holm#include <time.h> 415b42ac29SPeter Holm#include <unistd.h> 425b42ac29SPeter Holm 435b42ac29SPeter Holmstatic __thread int clone_ongoing; 445b42ac29SPeter Holmstatic __thread int skip_segv; 455b42ac29SPeter Holmstatic __thread jmp_buf segv_env; 465b42ac29SPeter Holm 475b42ac29SPeter Holmstatic void segv_handler(int sig, siginfo_t* info, void* ctx __unused) 485b42ac29SPeter Holm{ 495b42ac29SPeter Holm if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { 505b42ac29SPeter Holm exit(sig); 515b42ac29SPeter Holm } 525b42ac29SPeter Holm uintptr_t addr = (uintptr_t)info->si_addr; 535b42ac29SPeter Holm const uintptr_t prog_start = 1 << 20; 545b42ac29SPeter Holm const uintptr_t prog_end = 100 << 20; 555b42ac29SPeter Holm int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; 565b42ac29SPeter Holm int valid = addr < prog_start || addr > prog_end; 575b42ac29SPeter Holm if (sig == SIGBUS) 585b42ac29SPeter Holm valid = 1; 595b42ac29SPeter Holm if (skip && valid) { 605b42ac29SPeter Holm _longjmp(segv_env, 1); 615b42ac29SPeter Holm } 625b42ac29SPeter Holm exit(sig); 635b42ac29SPeter Holm} 645b42ac29SPeter Holm 655b42ac29SPeter Holmstatic void install_segv_handler(void) 665b42ac29SPeter Holm{ 675b42ac29SPeter Holm struct sigaction sa; 685b42ac29SPeter Holm memset(&sa, 0, sizeof(sa)); 695b42ac29SPeter Holm sa.sa_sigaction = segv_handler; 705b42ac29SPeter Holm sa.sa_flags = SA_NODEFER | SA_SIGINFO; 715b42ac29SPeter Holm sigaction(SIGSEGV, &sa, NULL); 725b42ac29SPeter Holm sigaction(SIGBUS, &sa, NULL); 735b42ac29SPeter Holm} 745b42ac29SPeter Holm 755b42ac29SPeter Holm#define NONFAILING(...) \ 765b42ac29SPeter Holm ({ \ 775b42ac29SPeter Holm int ok = 1; \ 785b42ac29SPeter Holm __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 795b42ac29SPeter Holm if (_setjmp(segv_env) == 0) { \ 805b42ac29SPeter Holm __VA_ARGS__; \ 815b42ac29SPeter Holm } else \ 825b42ac29SPeter Holm ok = 0; \ 835b42ac29SPeter Holm __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 845b42ac29SPeter Holm ok; \ 855b42ac29SPeter Holm }) 865b42ac29SPeter Holm 875b42ac29SPeter Holmstatic void kill_and_wait(int pid, int* status) 885b42ac29SPeter Holm{ 895b42ac29SPeter Holm kill(pid, SIGKILL); 905b42ac29SPeter Holm while (waitpid(-1, status, 0) != pid) { 915b42ac29SPeter Holm } 925b42ac29SPeter Holm} 935b42ac29SPeter Holm 945b42ac29SPeter Holmstatic void sleep_ms(uint64_t ms) 955b42ac29SPeter Holm{ 965b42ac29SPeter Holm usleep(ms * 1000); 975b42ac29SPeter Holm} 985b42ac29SPeter Holm 995b42ac29SPeter Holmstatic uint64_t current_time_ms(void) 1005b42ac29SPeter Holm{ 1015b42ac29SPeter Holm struct timespec ts; 1025b42ac29SPeter Holm if (clock_gettime(CLOCK_MONOTONIC, &ts)) 1035b42ac29SPeter Holm exit(1); 1045b42ac29SPeter Holm return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 1055b42ac29SPeter Holm} 1065b42ac29SPeter Holm 1075b42ac29SPeter Holmstatic void thread_start(void* (*fn)(void*), void* arg) 1085b42ac29SPeter Holm{ 1095b42ac29SPeter Holm pthread_t th; 1105b42ac29SPeter Holm pthread_attr_t attr; 1115b42ac29SPeter Holm pthread_attr_init(&attr); 1125b42ac29SPeter Holm pthread_attr_setstacksize(&attr, 128 << 10); 1135b42ac29SPeter Holm int i = 0; 1145b42ac29SPeter Holm for (; i < 100; i++) { 1155b42ac29SPeter Holm if (pthread_create(&th, &attr, fn, arg) == 0) { 1165b42ac29SPeter Holm pthread_attr_destroy(&attr); 1175b42ac29SPeter Holm return; 1185b42ac29SPeter Holm } 1195b42ac29SPeter Holm if (errno == EAGAIN) { 1205b42ac29SPeter Holm usleep(50); 1215b42ac29SPeter Holm continue; 1225b42ac29SPeter Holm } 1235b42ac29SPeter Holm break; 1245b42ac29SPeter Holm } 1255b42ac29SPeter Holm exit(1); 1265b42ac29SPeter Holm} 1275b42ac29SPeter Holm 1285b42ac29SPeter Holmtypedef struct { 1295b42ac29SPeter Holm pthread_mutex_t mu; 1305b42ac29SPeter Holm pthread_cond_t cv; 1315b42ac29SPeter Holm int state; 1325b42ac29SPeter Holm} event_t; 1335b42ac29SPeter Holm 1345b42ac29SPeter Holmstatic void event_init(event_t* ev) 1355b42ac29SPeter Holm{ 1365b42ac29SPeter Holm if (pthread_mutex_init(&ev->mu, 0)) 1375b42ac29SPeter Holm exit(1); 1385b42ac29SPeter Holm if (pthread_cond_init(&ev->cv, 0)) 1395b42ac29SPeter Holm exit(1); 1405b42ac29SPeter Holm ev->state = 0; 1415b42ac29SPeter Holm} 1425b42ac29SPeter Holm 1435b42ac29SPeter Holmstatic void event_reset(event_t* ev) 1445b42ac29SPeter Holm{ 1455b42ac29SPeter Holm ev->state = 0; 1465b42ac29SPeter Holm} 1475b42ac29SPeter Holm 1485b42ac29SPeter Holmstatic void event_set(event_t* ev) 1495b42ac29SPeter Holm{ 1505b42ac29SPeter Holm pthread_mutex_lock(&ev->mu); 1515b42ac29SPeter Holm if (ev->state) 1525b42ac29SPeter Holm exit(1); 1535b42ac29SPeter Holm ev->state = 1; 1545b42ac29SPeter Holm pthread_mutex_unlock(&ev->mu); 1555b42ac29SPeter Holm pthread_cond_broadcast(&ev->cv); 1565b42ac29SPeter Holm} 1575b42ac29SPeter Holm 1585b42ac29SPeter Holmstatic void event_wait(event_t* ev) 1595b42ac29SPeter Holm{ 1605b42ac29SPeter Holm pthread_mutex_lock(&ev->mu); 1615b42ac29SPeter Holm while (!ev->state) 1625b42ac29SPeter Holm pthread_cond_wait(&ev->cv, &ev->mu); 1635b42ac29SPeter Holm pthread_mutex_unlock(&ev->mu); 1645b42ac29SPeter Holm} 1655b42ac29SPeter Holm 1665b42ac29SPeter Holmstatic int event_isset(event_t* ev) 1675b42ac29SPeter Holm{ 1685b42ac29SPeter Holm pthread_mutex_lock(&ev->mu); 1695b42ac29SPeter Holm int res = ev->state; 1705b42ac29SPeter Holm pthread_mutex_unlock(&ev->mu); 1715b42ac29SPeter Holm return res; 1725b42ac29SPeter Holm} 1735b42ac29SPeter Holm 1745b42ac29SPeter Holmstatic int event_timedwait(event_t* ev, uint64_t timeout) 1755b42ac29SPeter Holm{ 1765b42ac29SPeter Holm uint64_t start = current_time_ms(); 1775b42ac29SPeter Holm uint64_t now = start; 1785b42ac29SPeter Holm pthread_mutex_lock(&ev->mu); 1795b42ac29SPeter Holm for (;;) { 1805b42ac29SPeter Holm if (ev->state) 1815b42ac29SPeter Holm break; 1825b42ac29SPeter Holm uint64_t remain = timeout - (now - start); 1835b42ac29SPeter Holm struct timespec ts; 1845b42ac29SPeter Holm ts.tv_sec = remain / 1000; 1855b42ac29SPeter Holm ts.tv_nsec = (remain % 1000) * 1000 * 1000; 1865b42ac29SPeter Holm pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 1875b42ac29SPeter Holm now = current_time_ms(); 1885b42ac29SPeter Holm if (now - start > timeout) 1895b42ac29SPeter Holm break; 1905b42ac29SPeter Holm } 1915b42ac29SPeter Holm int res = ev->state; 1925b42ac29SPeter Holm pthread_mutex_unlock(&ev->mu); 1935b42ac29SPeter Holm return res; 1945b42ac29SPeter Holm} 1955b42ac29SPeter Holm 1965b42ac29SPeter Holmstruct thread_t { 1975b42ac29SPeter Holm int created, call; 1985b42ac29SPeter Holm event_t ready, done; 1995b42ac29SPeter Holm}; 2005b42ac29SPeter Holm 2015b42ac29SPeter Holmstatic struct thread_t threads[16]; 2025b42ac29SPeter Holmstatic void execute_call(int call); 2035b42ac29SPeter Holmstatic int running; 2045b42ac29SPeter Holm 2055b42ac29SPeter Holmstatic void* thr(void* arg) 2065b42ac29SPeter Holm{ 2075b42ac29SPeter Holm struct thread_t* th = (struct thread_t*)arg; 2085b42ac29SPeter Holm for (;;) { 2095b42ac29SPeter Holm event_wait(&th->ready); 2105b42ac29SPeter Holm event_reset(&th->ready); 2115b42ac29SPeter Holm execute_call(th->call); 2125b42ac29SPeter Holm __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 2135b42ac29SPeter Holm event_set(&th->done); 2145b42ac29SPeter Holm } 2155b42ac29SPeter Holm return 0; 2165b42ac29SPeter Holm} 2175b42ac29SPeter Holm 2185b42ac29SPeter Holmstatic void execute_one(void) 2195b42ac29SPeter Holm{ 2205b42ac29SPeter Holm int i, call, thread; 2215b42ac29SPeter Holm for (call = 0; call < 2; call++) { 2225b42ac29SPeter Holm for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 2235b42ac29SPeter Holm thread++) { 2245b42ac29SPeter Holm struct thread_t* th = &threads[thread]; 2255b42ac29SPeter Holm if (!th->created) { 2265b42ac29SPeter Holm th->created = 1; 2275b42ac29SPeter Holm event_init(&th->ready); 2285b42ac29SPeter Holm event_init(&th->done); 2295b42ac29SPeter Holm event_set(&th->done); 2305b42ac29SPeter Holm thread_start(thr, th); 2315b42ac29SPeter Holm } 2325b42ac29SPeter Holm if (!event_isset(&th->done)) 2335b42ac29SPeter Holm continue; 2345b42ac29SPeter Holm event_reset(&th->done); 2355b42ac29SPeter Holm th->call = call; 2365b42ac29SPeter Holm __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 2375b42ac29SPeter Holm event_set(&th->ready); 2385b42ac29SPeter Holm event_timedwait(&th->done, 50); 2395b42ac29SPeter Holm break; 2405b42ac29SPeter Holm } 2415b42ac29SPeter Holm } 2425b42ac29SPeter Holm for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 2435b42ac29SPeter Holm sleep_ms(1); 2445b42ac29SPeter Holm} 2455b42ac29SPeter Holm 2465b42ac29SPeter Holmstatic void execute_one(void); 2475b42ac29SPeter Holm 2485b42ac29SPeter Holm#define WAIT_FLAGS 0 2495b42ac29SPeter Holm 2505b42ac29SPeter Holmstatic void loop(void) 2515b42ac29SPeter Holm{ 252*7f658f99SPeter Holm int iter __unused = 0; 2535b42ac29SPeter Holm for (;; iter++) { 2545b42ac29SPeter Holm int pid = fork(); 2555b42ac29SPeter Holm if (pid < 0) 2565b42ac29SPeter Holm exit(1); 2575b42ac29SPeter Holm if (pid == 0) { 2585b42ac29SPeter Holm execute_one(); 2595b42ac29SPeter Holm exit(0); 2605b42ac29SPeter Holm } 2615b42ac29SPeter Holm int status = 0; 2625b42ac29SPeter Holm uint64_t start = current_time_ms(); 2635b42ac29SPeter Holm for (;;) { 2645b42ac29SPeter Holm if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 2655b42ac29SPeter Holm break; 2665b42ac29SPeter Holm sleep_ms(1); 2675b42ac29SPeter Holm if (current_time_ms() - start < 5000) 2685b42ac29SPeter Holm continue; 2695b42ac29SPeter Holm kill_and_wait(pid, &status); 2705b42ac29SPeter Holm break; 2715b42ac29SPeter Holm } 2725b42ac29SPeter Holm } 2735b42ac29SPeter Holm} 2745b42ac29SPeter Holm 2755b42ac29SPeter Holmvoid execute_call(int call) 2765b42ac29SPeter Holm{ 2775b42ac29SPeter Holm switch (call) { 2785b42ac29SPeter Holm case 0: 2795b42ac29SPeter Holm NONFAILING(*(uint32_t*)0x20001f00 = 0x16); 2805b42ac29SPeter Holm NONFAILING(*(uint32_t*)0x20001f04 = 0); 2815b42ac29SPeter Holm NONFAILING(*(uint32_t*)0x20001f08 = 0); 2825b42ac29SPeter Holm NONFAILING(*(uint32_t*)0x20001f0c = 0); 2835b42ac29SPeter Holm NONFAILING(*(uint32_t*)0x20001f10 = 0); 2845b42ac29SPeter Holm NONFAILING(memset((void*)0x20001f14, 0, 60)); 2855b42ac29SPeter Holm syscall(SYS_procctl, 0ul, 0, 6ul, 0x20001f00ul); 2865b42ac29SPeter Holm break; 2875b42ac29SPeter Holm case 1: 2885b42ac29SPeter Holm syscall(SYS_rfork, 0x85000ul); 2895b42ac29SPeter Holm break; 2905b42ac29SPeter Holm } 2915b42ac29SPeter Holm} 2925b42ac29SPeter Holmint main(void) 2935b42ac29SPeter Holm{ 2945b42ac29SPeter Holm syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 2955b42ac29SPeter Holm install_segv_handler(); 2965b42ac29SPeter Holm loop(); 2975b42ac29SPeter Holm return 0; 2985b42ac29SPeter Holm} 2995b42ac29SPeter HolmEOF 3005b42ac29SPeter Holmmycc -o /tmp/syzkaller61 -Wall -Wextra -O0 /tmp/syzkaller61.c -lpthread || 3015b42ac29SPeter Holm exit 1 3025b42ac29SPeter Holm 3035b42ac29SPeter Holm(cd ../testcases/swap; ./swap -t 3m -i 10 -l 100 > /dev/null 2>&1) & 3045b42ac29SPeter Holmfor i in `jot 300`; do 3055b42ac29SPeter Holm (cd /tmp; timeout -k 3s 2s ./syzkaller61) & 3065b42ac29SPeter Holm pids="$pids $!" 3075b42ac29SPeter Holmdone 3085b42ac29SPeter Holmsleep 5 3095b42ac29SPeter Holmpkill -9 syzkaller61 swap; sleep 1 3105b42ac29SPeter Holmpgrep -q syzkaller61 && { pgrep syzkaller61 | xargs ps -lHp; exit 1; } 3115b42ac29SPeter Holmfor pid in $pids; do 3125b42ac29SPeter Holm wait $pid 3135b42ac29SPeter Holmdone 3145b42ac29SPeter Holmwhile pkill swap; do :; done 3155b42ac29SPeter Holmwait 3165b42ac29SPeter Holm 3175b42ac29SPeter Holmrm -rf /tmp/syzkaller61 /tmp/syzkaller61.c /tmp/syzkaller61.core \ 3185b42ac29SPeter Holm /tmp/syzkaller.?????? 3195b42ac29SPeter Holmexit 0 320