1#!/bin/sh 2 3# Fatal trap 9: general protection fault while in kernel mode 4# cpuid = 5; apic id = 05 5# instruction pointer = 0x20:0xffffffff8237cbac 6# stack pointer = 0x28:0xfffffe01026e4910 7# frame pointer = 0x28:0xfffffe01026e4980 8# code segment = base 0x0, limit 0xfffff, type 0x1b 9# = DPL 0, pres 1, long 1, def32 0, gran 1 10# processor eflags = interrupt enabled, resume, IOPL = 0 11# current process = 45836 (syzkaller25) 12# trap number = 9 13# panic: general protection fault 14# cpuid = 5 15# time = 1601745366 16# KDB: stack backtrace: 17# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01026e4620 18# vpanic() at vpanic+0x182/frame 0xfffffe01026e4670 19# panic() at panic+0x43/frame 0xfffffe01026e46d0 20# trap_fatal() at trap_fatal+0x387/frame 0xfffffe01026e4730 21# trap() at trap+0xa4/frame 0xfffffe01026e4840 22# calltrap() at calltrap+0x8/frame 0xfffffe01026e4840 23# --- trap 0x9, rip = 0xffffffff8237cbac, rsp = 0xfffffe01026e4910, rbp = 0xfffffe01026e4980 --- 24# sctp_inpcb_bind() at sctp_inpcb_bind+0x3cc/frame 0xfffffe01026e4980 25# sctp_connect() at sctp_connect+0x14f/frame 0xfffffe01026e49e0 26# soconnectat() at soconnectat+0xd0/frame 0xfffffe01026e4a30 27# kern_connectat() at kern_connectat+0xe2/frame 0xfffffe01026e4a90 28# sys_connect() at sys_connect+0x75/frame 0xfffffe01026e4ad0 29# amd64_syscall() at amd64_syscall+0x14e/frame 0xfffffe01026e4bf0 30# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01026e4bf0 31# --- syscall (0, FreeBSD ELF64, nosys), rip = 0x8003b0a1a, rsp = 0x7fffdfffdbb8, rbp = 0x7fffdfffdf90 --- 32# KDB: enter: panic 33# [ thread pid 45836 tid 101772 ] 34# Stopped at kdb_enter+0x37: movq $0,0x10ac846(%rip) 35# db> x/s version 36# version: FreeBSD 13.0-CURRENT #0 r366401: Sat Oct 3 19:00:37 CEST 2020 37# pho@t2.osted.lan:/usr/src/sys/amd64/compile/PHO 38# db> 39 40[ `uname -p` != "amd64" ] && exit 0 41 42. ../default.cfg 43kldstat -v | grep -q sctp || kldload sctp.ko 44 45cat > /tmp/syzkaller25.c <<EOF 46// https://syzkaller.appspot.com/bug?id=2e4fc04b5a5775777770f7244613571ca85da78a 47// autogenerated by syzkaller (https://github.com/google/syzkaller) 48// Reported-by: syzbot+77fcf6a9d28f301bc2e5@syzkaller.appspotmail.com 49 50#define _GNU_SOURCE 51 52#include <sys/types.h> 53 54#include <dirent.h> 55#include <errno.h> 56#include <pthread.h> 57#include <pwd.h> 58#include <setjmp.h> 59#include <signal.h> 60#include <stdarg.h> 61#include <stdbool.h> 62#include <stdint.h> 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include <sys/endian.h> 67#include <sys/resource.h> 68#include <sys/stat.h> 69#include <sys/syscall.h> 70#include <sys/wait.h> 71#include <time.h> 72#include <unistd.h> 73 74static unsigned long long procid; 75 76static __thread int skip_segv; 77static __thread jmp_buf segv_env; 78 79static void segv_handler(int sig, siginfo_t* info, void* ctx __unused) 80{ 81 uintptr_t addr = (uintptr_t)info->si_addr; 82 const uintptr_t prog_start = 1 << 20; 83 const uintptr_t prog_end = 100 << 20; 84 int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; 85 int valid = addr < prog_start || addr > prog_end; 86 if (sig == SIGBUS) { 87 valid = 1; 88 } 89 if (skip && valid) { 90 _longjmp(segv_env, 1); 91 } 92 exit(sig); 93} 94 95static void install_segv_handler(void) 96{ 97 struct sigaction sa; 98 memset(&sa, 0, sizeof(sa)); 99 sa.sa_sigaction = segv_handler; 100 sa.sa_flags = SA_NODEFER | SA_SIGINFO; 101 sigaction(SIGSEGV, &sa, NULL); 102 sigaction(SIGBUS, &sa, NULL); 103} 104 105#define NONFAILING(...) \ 106 ({ \ 107 int ok = 1; \ 108 __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 109 if (_setjmp(segv_env) == 0) { \ 110 __VA_ARGS__; \ 111 } else \ 112 ok = 0; \ 113 __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 114 ok; \ 115 }) 116 117static void kill_and_wait(int pid, int* status) 118{ 119 kill(pid, SIGKILL); 120 while (waitpid(-1, status, 0) != pid) { 121 } 122} 123 124static void sleep_ms(uint64_t ms) 125{ 126 usleep(ms * 1000); 127} 128 129static uint64_t current_time_ms(void) 130{ 131 struct timespec ts; 132 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 133 exit(1); 134 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 135} 136 137static void use_temporary_dir(void) 138{ 139 char tmpdir_template[] = "./syzkaller.XXXXXX"; 140 char* tmpdir = mkdtemp(tmpdir_template); 141 if (!tmpdir) 142 exit(1); 143 if (chmod(tmpdir, 0777)) 144 exit(1); 145 if (chdir(tmpdir)) 146 exit(1); 147} 148 149static void __attribute__((noinline)) remove_dir(const char* dir) 150{ 151 DIR* dp = opendir(dir); 152 if (dp == NULL) { 153 if (errno == EACCES) { 154 if (rmdir(dir)) 155 exit(1); 156 return; 157 } 158 exit(1); 159 } 160 struct dirent* ep = 0; 161 while ((ep = readdir(dp))) { 162 if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) 163 continue; 164 char filename[FILENAME_MAX]; 165 snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); 166 struct stat st; 167 if (lstat(filename, &st)) 168 exit(1); 169 if (S_ISDIR(st.st_mode)) { 170 remove_dir(filename); 171 continue; 172 } 173 if (unlink(filename)) 174 exit(1); 175 } 176 closedir(dp); 177 if (rmdir(dir)) 178 exit(1); 179} 180 181static void thread_start(void* (*fn)(void*), void* arg) 182{ 183 pthread_t th; 184 pthread_attr_t attr; 185 pthread_attr_init(&attr); 186 pthread_attr_setstacksize(&attr, 128 << 10); 187 int i = 0; 188 for (; i < 100; i++) { 189 if (pthread_create(&th, &attr, fn, arg) == 0) { 190 pthread_attr_destroy(&attr); 191 return; 192 } 193 if (errno == EAGAIN) { 194 usleep(50); 195 continue; 196 } 197 break; 198 } 199 exit(1); 200} 201 202typedef struct { 203 pthread_mutex_t mu; 204 pthread_cond_t cv; 205 int state; 206} event_t; 207 208static void event_init(event_t* ev) 209{ 210 if (pthread_mutex_init(&ev->mu, 0)) 211 exit(1); 212 if (pthread_cond_init(&ev->cv, 0)) 213 exit(1); 214 ev->state = 0; 215} 216 217static void event_reset(event_t* ev) 218{ 219 ev->state = 0; 220} 221 222static void event_set(event_t* ev) 223{ 224 pthread_mutex_lock(&ev->mu); 225 if (ev->state) 226 exit(1); 227 ev->state = 1; 228 pthread_mutex_unlock(&ev->mu); 229 pthread_cond_broadcast(&ev->cv); 230} 231 232static void event_wait(event_t* ev) 233{ 234 pthread_mutex_lock(&ev->mu); 235 while (!ev->state) 236 pthread_cond_wait(&ev->cv, &ev->mu); 237 pthread_mutex_unlock(&ev->mu); 238} 239 240static int event_isset(event_t* ev) 241{ 242 pthread_mutex_lock(&ev->mu); 243 int res = ev->state; 244 pthread_mutex_unlock(&ev->mu); 245 return res; 246} 247 248static int event_timedwait(event_t* ev, uint64_t timeout) 249{ 250 uint64_t start = current_time_ms(); 251 uint64_t now = start; 252 pthread_mutex_lock(&ev->mu); 253 for (;;) { 254 if (ev->state) 255 break; 256 uint64_t remain = timeout - (now - start); 257 struct timespec ts; 258 ts.tv_sec = remain / 1000; 259 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 260 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 261 now = current_time_ms(); 262 if (now - start > timeout) 263 break; 264 } 265 int res = ev->state; 266 pthread_mutex_unlock(&ev->mu); 267 return res; 268} 269 270static void sandbox_common() 271{ 272 if (setsid() == -1) 273 exit(1); 274 struct rlimit rlim; 275 rlim.rlim_cur = rlim.rlim_max = 128 << 20; 276 setrlimit(RLIMIT_AS, &rlim); 277 rlim.rlim_cur = rlim.rlim_max = 8 << 20; 278 setrlimit(RLIMIT_MEMLOCK, &rlim); 279 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 280 setrlimit(RLIMIT_FSIZE, &rlim); 281 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 282 setrlimit(RLIMIT_STACK, &rlim); 283 rlim.rlim_cur = rlim.rlim_max = 0; 284 setrlimit(RLIMIT_CORE, &rlim); 285 rlim.rlim_cur = rlim.rlim_max = 256; 286 setrlimit(RLIMIT_NOFILE, &rlim); 287} 288 289static void loop(); 290 291static int do_sandbox_none(void) 292{ 293 sandbox_common(); 294 loop(); 295 return 0; 296} 297 298struct thread_t { 299 int created, call; 300 event_t ready, done; 301}; 302 303static struct thread_t threads[16]; 304static void execute_call(int call); 305static int running; 306 307static void* thr(void* arg) 308{ 309 struct thread_t* th = (struct thread_t*)arg; 310 for (;;) { 311 event_wait(&th->ready); 312 event_reset(&th->ready); 313 execute_call(th->call); 314 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 315 event_set(&th->done); 316 } 317 return 0; 318} 319 320static void execute_one(void) 321{ 322 int i, call, thread; 323 int collide = 0; 324again: 325 for (call = 0; call < 4; call++) { 326 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 327 thread++) { 328 struct thread_t* th = &threads[thread]; 329 if (!th->created) { 330 th->created = 1; 331 event_init(&th->ready); 332 event_init(&th->done); 333 event_set(&th->done); 334 thread_start(thr, th); 335 } 336 if (!event_isset(&th->done)) 337 continue; 338 event_reset(&th->done); 339 th->call = call; 340 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 341 event_set(&th->ready); 342 if (collide && (call % 2) == 0) 343 break; 344 event_timedwait(&th->done, 45); 345 break; 346 } 347 } 348 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 349 sleep_ms(1); 350 if (!collide) { 351 collide = 1; 352 goto again; 353 } 354} 355 356static void execute_one(void); 357 358#define WAIT_FLAGS 0 359 360static void loop(void) 361{ 362 int iter = 0; 363 for (;; iter++) { 364 char cwdbuf[32]; 365 sprintf(cwdbuf, "./%d", iter); 366 if (mkdir(cwdbuf, 0777)) 367 exit(1); 368 int pid = fork(); 369 if (pid < 0) 370 exit(1); 371 if (pid == 0) { 372 if (chdir(cwdbuf)) 373 exit(1); 374 execute_one(); 375 exit(0); 376 } 377 int status = 0; 378 uint64_t start = current_time_ms(); 379 for (;;) { 380 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 381 break; 382 sleep_ms(1); 383 if (current_time_ms() - start < 5 * 1000) 384 continue; 385 kill_and_wait(pid, &status); 386 break; 387 } 388 remove_dir(cwdbuf); 389 } 390} 391 392uint64_t r[1] = {0xffffffffffffffff}; 393 394void execute_call(int call) 395{ 396 intptr_t res = 0; 397 switch (call) { 398 case 0: 399 res = syscall(SYS_socket, 2ul, 5ul, 0x84); 400 if (res != -1) 401 r[0] = res; 402 break; 403 case 1: 404 NONFAILING(*(uint8_t*)0x20000300 = 0x10); 405 NONFAILING(*(uint8_t*)0x20000301 = 2); 406 NONFAILING(*(uint16_t*)0x20000302 = htobe16(0x4e23 + procid * 4)); 407 NONFAILING(*(uint32_t*)0x20000304 = htobe32(0)); 408 NONFAILING(*(uint8_t*)0x20000308 = 0); 409 NONFAILING(*(uint8_t*)0x20000309 = 0); 410 NONFAILING(*(uint8_t*)0x2000030a = 0); 411 NONFAILING(*(uint8_t*)0x2000030b = 0); 412 NONFAILING(*(uint8_t*)0x2000030c = 0); 413 NONFAILING(*(uint8_t*)0x2000030d = 0); 414 NONFAILING(*(uint8_t*)0x2000030e = 0); 415 NONFAILING(*(uint8_t*)0x2000030f = 0); 416 syscall(SYS_bind, r[0], 0x20000300ul, 0x10ul); 417 break; 418 case 2: 419 NONFAILING(*(uint8_t*)0x20000040 = 0x10); 420 NONFAILING(*(uint8_t*)0x20000041 = 2); 421 NONFAILING(*(uint16_t*)0x20000042 = htobe16(0x4e23 + procid * 4)); 422 NONFAILING(*(uint32_t*)0x20000044 = htobe32(0x7f000001)); 423 NONFAILING(*(uint8_t*)0x20000048 = 0); 424 NONFAILING(*(uint8_t*)0x20000049 = 0); 425 NONFAILING(*(uint8_t*)0x2000004a = 0); 426 NONFAILING(*(uint8_t*)0x2000004b = 0); 427 NONFAILING(*(uint8_t*)0x2000004c = 0); 428 NONFAILING(*(uint8_t*)0x2000004d = 0); 429 NONFAILING(*(uint8_t*)0x2000004e = 0); 430 NONFAILING(*(uint8_t*)0x2000004f = 0); 431 syscall(SYS_connect, r[0], 0x20000040ul, 0x10ul); 432 break; 433 case 3: 434 NONFAILING(*(uint8_t*)0x20000000 = 0x10); 435 NONFAILING(*(uint8_t*)0x20000001 = 2); 436 NONFAILING(*(uint16_t*)0x20000002 = htobe16(0x4e23 + procid * 4)); 437 NONFAILING(*(uint8_t*)0x20000004 = 0xac); 438 NONFAILING(*(uint8_t*)0x20000005 = 0x14); 439 NONFAILING(*(uint8_t*)0x20000006 = 0 + procid * 1); 440 NONFAILING(*(uint8_t*)0x20000007 = 0xaa); 441 NONFAILING(*(uint8_t*)0x20000008 = 0); 442 NONFAILING(*(uint8_t*)0x20000009 = 0); 443 NONFAILING(*(uint8_t*)0x2000000a = 0); 444 NONFAILING(*(uint8_t*)0x2000000b = 0); 445 NONFAILING(*(uint8_t*)0x2000000c = 0); 446 NONFAILING(*(uint8_t*)0x2000000d = 0); 447 NONFAILING(*(uint8_t*)0x2000000e = 0); 448 NONFAILING(*(uint8_t*)0x2000000f = 0); 449 syscall(SYS_connect, r[0], 0x20000000ul, 0x10ul); 450 break; 451 } 452} 453int main(void) 454{ 455 syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 456 install_segv_handler(); 457 for (procid = 0; procid < 4; procid++) { 458 if (fork() == 0) { 459 use_temporary_dir(); 460 do_sandbox_none(); 461 } 462 } 463 sleep(1000000); 464 return 0; 465} 466EOF 467mycc -o /tmp/syzkaller25 -Wall -Wextra -O0 /tmp/syzkaller25.c -lpthread || 468 exit 1 469 470(cd ../testcases/swap; ./swap -t 1m -i 20 -h > /dev/null 2>&1) & 471(cd /tmp; timeout 3m ./syzkaller25) 472while pkill swap; do :; done 473wait 474 475rm -rf /tmp/syzkaller25 /tmp/syzkaller25.c /tmp/syzkaller.* 476exit 0 477