1#!/bin/sh 2 3# Seen: 4# [root@mercat1 /usr/src/tools/test/stress2/misc]# pgrep syzkaller61 | xargs procstat -k 5# PID TID COMM TDNAME KSTACK 6# 13332 106396 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast 7# 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 8# 13332 560776 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common 9# 13662 356440 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast 10# 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 11# 13662 561160 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common 12# [root@mercat1 /usr/src/tools/test/stress2/misc]# 13 14[ `uname -p` != "amd64" ] && exit 0 15 16. ../default.cfg 17cat > /tmp/syzkaller61.c <<EOF 18// https://syzkaller.appspot.com/bug?id=00d8ca63243899ffb67b15ec93aee4ffa2f06637 19// autogenerated by syzkaller (https://github.com/google/syzkaller) 20// Reported-by: syzbot+647212368c3f32c6f13f@syzkaller.appspotmail.com 21 22#define _GNU_SOURCE 23 24#include <sys/types.h> 25 26#include <errno.h> 27#include <pthread.h> 28#include <pwd.h> 29#include <setjmp.h> 30#include <signal.h> 31#include <stdarg.h> 32#include <stdbool.h> 33#include <stdint.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <sys/endian.h> 38#include <sys/syscall.h> 39#include <sys/wait.h> 40#include <time.h> 41#include <unistd.h> 42 43static __thread int clone_ongoing; 44static __thread int skip_segv; 45static __thread jmp_buf segv_env; 46 47static void segv_handler(int sig, siginfo_t* info, void* ctx __unused) 48{ 49 if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { 50 exit(sig); 51 } 52 uintptr_t addr = (uintptr_t)info->si_addr; 53 const uintptr_t prog_start = 1 << 20; 54 const uintptr_t prog_end = 100 << 20; 55 int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; 56 int valid = addr < prog_start || addr > prog_end; 57 if (sig == SIGBUS) 58 valid = 1; 59 if (skip && valid) { 60 _longjmp(segv_env, 1); 61 } 62 exit(sig); 63} 64 65static void install_segv_handler(void) 66{ 67 struct sigaction sa; 68 memset(&sa, 0, sizeof(sa)); 69 sa.sa_sigaction = segv_handler; 70 sa.sa_flags = SA_NODEFER | SA_SIGINFO; 71 sigaction(SIGSEGV, &sa, NULL); 72 sigaction(SIGBUS, &sa, NULL); 73} 74 75#define NONFAILING(...) \ 76 ({ \ 77 int ok = 1; \ 78 __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 79 if (_setjmp(segv_env) == 0) { \ 80 __VA_ARGS__; \ 81 } else \ 82 ok = 0; \ 83 __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 84 ok; \ 85 }) 86 87static void kill_and_wait(int pid, int* status) 88{ 89 kill(pid, SIGKILL); 90 while (waitpid(-1, status, 0) != pid) { 91 } 92} 93 94static void sleep_ms(uint64_t ms) 95{ 96 usleep(ms * 1000); 97} 98 99static uint64_t current_time_ms(void) 100{ 101 struct timespec ts; 102 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 103 exit(1); 104 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 105} 106 107static void thread_start(void* (*fn)(void*), void* arg) 108{ 109 pthread_t th; 110 pthread_attr_t attr; 111 pthread_attr_init(&attr); 112 pthread_attr_setstacksize(&attr, 128 << 10); 113 int i = 0; 114 for (; i < 100; i++) { 115 if (pthread_create(&th, &attr, fn, arg) == 0) { 116 pthread_attr_destroy(&attr); 117 return; 118 } 119 if (errno == EAGAIN) { 120 usleep(50); 121 continue; 122 } 123 break; 124 } 125 exit(1); 126} 127 128typedef struct { 129 pthread_mutex_t mu; 130 pthread_cond_t cv; 131 int state; 132} event_t; 133 134static void event_init(event_t* ev) 135{ 136 if (pthread_mutex_init(&ev->mu, 0)) 137 exit(1); 138 if (pthread_cond_init(&ev->cv, 0)) 139 exit(1); 140 ev->state = 0; 141} 142 143static void event_reset(event_t* ev) 144{ 145 ev->state = 0; 146} 147 148static void event_set(event_t* ev) 149{ 150 pthread_mutex_lock(&ev->mu); 151 if (ev->state) 152 exit(1); 153 ev->state = 1; 154 pthread_mutex_unlock(&ev->mu); 155 pthread_cond_broadcast(&ev->cv); 156} 157 158static void event_wait(event_t* ev) 159{ 160 pthread_mutex_lock(&ev->mu); 161 while (!ev->state) 162 pthread_cond_wait(&ev->cv, &ev->mu); 163 pthread_mutex_unlock(&ev->mu); 164} 165 166static int event_isset(event_t* ev) 167{ 168 pthread_mutex_lock(&ev->mu); 169 int res = ev->state; 170 pthread_mutex_unlock(&ev->mu); 171 return res; 172} 173 174static int event_timedwait(event_t* ev, uint64_t timeout) 175{ 176 uint64_t start = current_time_ms(); 177 uint64_t now = start; 178 pthread_mutex_lock(&ev->mu); 179 for (;;) { 180 if (ev->state) 181 break; 182 uint64_t remain = timeout - (now - start); 183 struct timespec ts; 184 ts.tv_sec = remain / 1000; 185 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 186 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 187 now = current_time_ms(); 188 if (now - start > timeout) 189 break; 190 } 191 int res = ev->state; 192 pthread_mutex_unlock(&ev->mu); 193 return res; 194} 195 196struct thread_t { 197 int created, call; 198 event_t ready, done; 199}; 200 201static struct thread_t threads[16]; 202static void execute_call(int call); 203static int running; 204 205static void* thr(void* arg) 206{ 207 struct thread_t* th = (struct thread_t*)arg; 208 for (;;) { 209 event_wait(&th->ready); 210 event_reset(&th->ready); 211 execute_call(th->call); 212 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 213 event_set(&th->done); 214 } 215 return 0; 216} 217 218static void execute_one(void) 219{ 220 int i, call, thread; 221 for (call = 0; call < 2; call++) { 222 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 223 thread++) { 224 struct thread_t* th = &threads[thread]; 225 if (!th->created) { 226 th->created = 1; 227 event_init(&th->ready); 228 event_init(&th->done); 229 event_set(&th->done); 230 thread_start(thr, th); 231 } 232 if (!event_isset(&th->done)) 233 continue; 234 event_reset(&th->done); 235 th->call = call; 236 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 237 event_set(&th->ready); 238 event_timedwait(&th->done, 50); 239 break; 240 } 241 } 242 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 243 sleep_ms(1); 244} 245 246static void execute_one(void); 247 248#define WAIT_FLAGS 0 249 250static void loop(void) 251{ 252 int iter = 0; 253 for (;; iter++) { 254 int pid = fork(); 255 if (pid < 0) 256 exit(1); 257 if (pid == 0) { 258 execute_one(); 259 exit(0); 260 } 261 int status = 0; 262 uint64_t start = current_time_ms(); 263 for (;;) { 264 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 265 break; 266 sleep_ms(1); 267 if (current_time_ms() - start < 5000) 268 continue; 269 kill_and_wait(pid, &status); 270 break; 271 } 272 } 273} 274 275void execute_call(int call) 276{ 277 switch (call) { 278 case 0: 279 NONFAILING(*(uint32_t*)0x20001f00 = 0x16); 280 NONFAILING(*(uint32_t*)0x20001f04 = 0); 281 NONFAILING(*(uint32_t*)0x20001f08 = 0); 282 NONFAILING(*(uint32_t*)0x20001f0c = 0); 283 NONFAILING(*(uint32_t*)0x20001f10 = 0); 284 NONFAILING(memset((void*)0x20001f14, 0, 60)); 285 syscall(SYS_procctl, 0ul, 0, 6ul, 0x20001f00ul); 286 break; 287 case 1: 288 syscall(SYS_rfork, 0x85000ul); 289 break; 290 } 291} 292int main(void) 293{ 294 syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 295 install_segv_handler(); 296 loop(); 297 return 0; 298} 299EOF 300mycc -o /tmp/syzkaller61 -Wall -Wextra -O0 /tmp/syzkaller61.c -lpthread || 301 exit 1 302 303(cd ../testcases/swap; ./swap -t 3m -i 10 -l 100 > /dev/null 2>&1) & 304for i in `jot 300`; do 305 (cd /tmp; timeout -k 3s 2s ./syzkaller61) & 306 pids="$pids $!" 307done 308sleep 5 309pkill -9 syzkaller61 swap; sleep 1 310pgrep -q syzkaller61 && { pgrep syzkaller61 | xargs ps -lHp; exit 1; } 311for pid in $pids; do 312 wait $pid 313done 314while pkill swap; do :; done 315wait 316 317rm -rf /tmp/syzkaller61 /tmp/syzkaller61.c /tmp/syzkaller61.core \ 318 /tmp/syzkaller.?????? 319exit 0 320