1#!/bin/sh 2 3# Fatal trap 12: page fault while in kernel mode 4# cpuid = 1; apic id = 01 5# fault virtual address = 0x18 6# fault code = supervisor read data, page not present 7# instruction pointer = 0x20:0xffffffff80b69835 8# stack pointer = 0x28:0xfffffe00ff8e7d90 9# frame pointer = 0x28:0xfffffe00ff8e7d90 10# code segment = base 0x0, limit 0xfffff, type 0x1b 11# = DPL 0, pres 1, long 1, def32 0, gran 1 12# processor eflags = interrupt enabled, resume, IOPL = 0 13# current process = 0 (thread taskq) 14# rdi: 0000000000000018 rsi: 0000000000000004 rdx: ffffffff812b3f65 15# rcx: 00000000000008ba r8: fffff800044b8780 r9: fffff80003397000 16# rax: 0000000000000001 rbx: fffff8004221fa00 rbp: fffffe00ff8e7d90 17# r10: 0000000000000001 r11: fffffe00dc47b000 r12: fffffe0177ed0000 18# r13: fffff800044b8780 r14: fffff8004221f800 r15: fffff8004221f800 19# trap number = 12 20# panic: page fault 21# cpuid = 1 22# time = 1759322830 23# KDB: stack backtrace: 24# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00ff8e7ac0 25# vpanic() at vpanic+0x136/frame 0xfffffe00ff8e7bf0 26# panic() at panic+0x43/frame 0xfffffe00ff8e7c50 27# trap_pfault() at trap_pfault+0x47c/frame 0xfffffe00ff8e7cc0 28# calltrap() at calltrap+0x8/frame 0xfffffe00ff8e7cc0 29# --- trap 0xc, rip = 0xffffffff80b69835, rsp = 0xfffffe00ff8e7d90, rbp = 0xfffffe00ff8e7d90 --- 30# __mtx_assert() at __mtx_assert+0x35/frame 0xfffffe00ff8e7d90 31# ktls_check_rx() at ktls_check_rx+0x2f/frame 0xfffffe00ff8e7dd0 32# socantrcvmore() at socantrcvmore+0x5e/frame 0xfffffe00ff8e7df0 33# unp_gc() at unp_gc+0x5df/frame 0xfffffe00ff8e7e40 34# taskqueue_run_locked() at taskqueue_run_locked+0x1c2/frame 0xfffffe00ff8e7ec0 35# taskqueue_thread_loop() at taskqueue_thread_loop+0xd3/frame 0xfffffe00ff8e7ef0 36# fork_exit() at fork_exit+0x82/frame 0xfffffe00ff8e7f30 37# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00ff8e7f30 38# --- trap 0, rip = 0, rsp = 0, rbp = 0 --- 39# KDB: enter: panic 40# [ thread pid 0 tid 100045 ] 41# Stopped at kdb_enter+0x33: movq $0,0x121a9e2(%rip) 42# db> x/s version 43# version: FreeBSD 16.0-CURRENT #0 vmfqe-n280784-b7f165e45d6d: Wed Oct 1 13:48:43 CEST 2025 44# pho@mercat1.netperf.freebsd.org:/var/tmp/deviant3/sys/amd64/compile/PHO 45# db> 46 47[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 48 49. ../default.cfg 50set -u 51prog=$(basename "$0" .sh) 52cat > /tmp/$prog.c <<EOF 53// https://syzkaller.appspot.com/bug?id=ec40fe3e3e2b41218d1d417bc10d0be2517bf751 54// autogenerated by syzkaller (https://github.com/google/syzkaller) 55// syzbot+a62883292a5c257703be@syzkaller.appspotmail.com 56 57#define _GNU_SOURCE 58 59#include <sys/types.h> 60 61#include <dirent.h> 62#include <errno.h> 63#include <pthread.h> 64#include <pwd.h> 65#include <signal.h> 66#include <stdarg.h> 67#include <stdbool.h> 68#include <stdint.h> 69#include <stdio.h> 70#include <stdlib.h> 71#include <string.h> 72#include <sys/endian.h> 73#include <sys/resource.h> 74#include <sys/stat.h> 75#include <sys/syscall.h> 76#include <sys/wait.h> 77#include <time.h> 78#include <unistd.h> 79 80static unsigned long long procid; 81 82static void kill_and_wait(int pid, int* status) 83{ 84 kill(pid, SIGKILL); 85 while (waitpid(-1, status, 0) != pid) { 86 } 87} 88 89static void sleep_ms(uint64_t ms) 90{ 91 usleep(ms * 1000); 92} 93 94static uint64_t current_time_ms(void) 95{ 96 struct timespec ts; 97 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 98 exit(1); 99 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 100} 101 102static void use_temporary_dir(void) 103{ 104 char tmpdir_template[] = "./syzkaller.XXXXXX"; 105 char* tmpdir = mkdtemp(tmpdir_template); 106 if (!tmpdir) 107 exit(1); 108 if (chmod(tmpdir, 0777)) 109 exit(1); 110 if (chdir(tmpdir)) 111 exit(1); 112} 113 114static void reset_flags(const char* filename) 115{ 116 struct stat st; 117 if (lstat(filename, &st)) 118 exit(1); 119 st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | 120 SF_APPEND | UF_APPEND); 121 if (lchflags(filename, st.st_flags)) 122 exit(1); 123} 124static void __attribute__((noinline)) remove_dir(const char* dir) 125{ 126 DIR* dp = opendir(dir); 127 if (dp == NULL) { 128 if (errno == EACCES) { 129 if (rmdir(dir)) 130 exit(1); 131 return; 132 } 133 exit(1); 134 } 135 struct dirent* ep = 0; 136 while ((ep = readdir(dp))) { 137 if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) 138 continue; 139 char filename[FILENAME_MAX]; 140 snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); 141 struct stat st; 142 if (lstat(filename, &st)) 143 exit(1); 144 if (S_ISDIR(st.st_mode)) { 145 remove_dir(filename); 146 continue; 147 } 148 if (unlink(filename)) { 149 if (errno == EPERM) { 150 reset_flags(filename); 151 reset_flags(dir); 152 if (unlink(filename) == 0) 153 continue; 154 } 155 exit(1); 156 } 157 } 158 closedir(dp); 159 while (rmdir(dir)) { 160 if (errno == EPERM) { 161 reset_flags(dir); 162 if (rmdir(dir) == 0) 163 break; 164 } 165 exit(1); 166 } 167} 168 169static void thread_start(void* (*fn)(void*), void* arg) 170{ 171 pthread_t th; 172 pthread_attr_t attr; 173 pthread_attr_init(&attr); 174 pthread_attr_setstacksize(&attr, 128 << 10); 175 int i = 0; 176 for (; i < 100; i++) { 177 if (pthread_create(&th, &attr, fn, arg) == 0) { 178 pthread_attr_destroy(&attr); 179 return; 180 } 181 if (errno == EAGAIN) { 182 usleep(50); 183 continue; 184 } 185 break; 186 } 187 exit(1); 188} 189 190typedef struct { 191 pthread_mutex_t mu; 192 pthread_cond_t cv; 193 int state; 194} event_t; 195 196static void event_init(event_t* ev) 197{ 198 if (pthread_mutex_init(&ev->mu, 0)) 199 exit(1); 200 if (pthread_cond_init(&ev->cv, 0)) 201 exit(1); 202 ev->state = 0; 203} 204 205static void event_reset(event_t* ev) 206{ 207 ev->state = 0; 208} 209 210static void event_set(event_t* ev) 211{ 212 pthread_mutex_lock(&ev->mu); 213 if (ev->state) 214 exit(1); 215 ev->state = 1; 216 pthread_mutex_unlock(&ev->mu); 217 pthread_cond_broadcast(&ev->cv); 218} 219 220static void event_wait(event_t* ev) 221{ 222 pthread_mutex_lock(&ev->mu); 223 while (!ev->state) 224 pthread_cond_wait(&ev->cv, &ev->mu); 225 pthread_mutex_unlock(&ev->mu); 226} 227 228static int event_isset(event_t* ev) 229{ 230 pthread_mutex_lock(&ev->mu); 231 int res = ev->state; 232 pthread_mutex_unlock(&ev->mu); 233 return res; 234} 235 236static int event_timedwait(event_t* ev, uint64_t timeout) 237{ 238 uint64_t start = current_time_ms(); 239 uint64_t now = start; 240 pthread_mutex_lock(&ev->mu); 241 for (;;) { 242 if (ev->state) 243 break; 244 uint64_t remain = timeout - (now - start); 245 struct timespec ts; 246 ts.tv_sec = remain / 1000; 247 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 248 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 249 now = current_time_ms(); 250 if (now - start > timeout) 251 break; 252 } 253 int res = ev->state; 254 pthread_mutex_unlock(&ev->mu); 255 return res; 256} 257 258static void sandbox_common() 259{ 260 struct rlimit rlim; 261 rlim.rlim_cur = rlim.rlim_max = 128 << 20; 262 setrlimit(RLIMIT_AS, &rlim); 263 rlim.rlim_cur = rlim.rlim_max = 8 << 20; 264 setrlimit(RLIMIT_MEMLOCK, &rlim); 265 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 266 setrlimit(RLIMIT_FSIZE, &rlim); 267 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 268 setrlimit(RLIMIT_STACK, &rlim); 269 rlim.rlim_cur = rlim.rlim_max = 0; 270 setrlimit(RLIMIT_CORE, &rlim); 271 rlim.rlim_cur = rlim.rlim_max = 256; 272 setrlimit(RLIMIT_NOFILE, &rlim); 273} 274 275static void loop(); 276 277static int do_sandbox_none(void) 278{ 279 sandbox_common(); 280 loop(); 281 return 0; 282} 283 284struct thread_t { 285 int created, call; 286 event_t ready, done; 287}; 288 289static struct thread_t threads[16]; 290static void execute_call(int call); 291static int running; 292 293static void* thr(void* arg) 294{ 295 struct thread_t* th = (struct thread_t*)arg; 296 for (;;) { 297 event_wait(&th->ready); 298 event_reset(&th->ready); 299 execute_call(th->call); 300 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 301 event_set(&th->done); 302 } 303 return 0; 304} 305 306static void execute_one(void) 307{ 308 if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { 309 } 310 int i, call, thread; 311 for (call = 0; call < 8; call++) { 312 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 313 thread++) { 314 struct thread_t* th = &threads[thread]; 315 if (!th->created) { 316 th->created = 1; 317 event_init(&th->ready); 318 event_init(&th->done); 319 event_set(&th->done); 320 thread_start(thr, th); 321 } 322 if (!event_isset(&th->done)) 323 continue; 324 event_reset(&th->done); 325 th->call = call; 326 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 327 event_set(&th->ready); 328 event_timedwait(&th->done, 50); 329 break; 330 } 331 } 332 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 333 sleep_ms(1); 334} 335 336static void execute_one(void); 337 338#define WAIT_FLAGS 0 339 340static void loop(void) 341{ 342 int iter = 0; 343 for (;; iter++) { 344 char cwdbuf[32]; 345 sprintf(cwdbuf, "./%d", iter); 346 if (mkdir(cwdbuf, 0777)) 347 exit(1); 348 int pid = fork(); 349 if (pid < 0) 350 exit(1); 351 if (pid == 0) { 352 if (chdir(cwdbuf)) 353 exit(1); 354 execute_one(); 355 exit(0); 356 } 357 int status = 0; 358 uint64_t start = current_time_ms(); 359 for (;;) { 360 sleep_ms(10); 361 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 362 break; 363 if (current_time_ms() - start < 5000) 364 continue; 365 kill_and_wait(pid, &status); 366 break; 367 } 368 remove_dir(cwdbuf); 369 } 370} 371 372uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; 373 374void execute_call(int call) 375{ 376 intptr_t res = 0; 377 switch (call) { 378 case 0: 379 // freebsd10_pipe arguments: [ 380 // pipefd: ptr[out, pipefd] { 381 // pipefd { 382 // rfd: fd (resource) 383 // wfd: fd (resource) 384 // } 385 // } 386 // ] 387 res = syscall(SYS_freebsd10_pipe, /*pipefd=*/0x2000000001c0ul); 388 if (res != -1) 389 r[0] = *(uint32_t*)0x2000000001c4; 390 break; 391 case 1: 392 // close arguments: [ 393 // fd: fd (resource) 394 // ] 395 syscall(SYS_close, /*fd=*/r[0]); 396 break; 397 case 2: 398 // socket\$unix arguments: [ 399 // domain: const = 0x1 (8 bytes) 400 // type: unix_socket_type = 0x5 (8 bytes) 401 // proto: const = 0x0 (1 bytes) 402 // ] 403 // returns sock_unix 404 res = syscall(SYS_socket, /*domain=*/1ul, /*type=SOCK_SEQPACKET*/ 5ul, 405 /*proto=*/0); 406 if (res != -1) 407 r[1] = res; 408 break; 409 case 3: 410 // bind\$unix arguments: [ 411 // fd: sock_unix (resource) 412 // addr: ptr[in, sockaddr_un] { 413 // union sockaddr_un { 414 // file: sockaddr_un_file { 415 // len: len = 0xa (1 bytes) 416 // family: unix_socket_family = 0x1 (1 bytes) 417 // path: buffer: {2e 2f 66 69 6c 65 31 00} (length 0x8) 418 // } 419 // } 420 // } 421 // addrlen: len = 0xa (8 bytes) 422 // ] 423 *(uint8_t*)0x2000000002c0 = 0xa; 424 *(uint8_t*)0x2000000002c1 = 1; 425 memcpy((void*)0x2000000002c2, "./file1\000", 8); 426 syscall(SYS_bind, /*fd=*/r[1], /*addr=*/0x2000000002c0ul, 427 /*addrlen=*/0xaul); 428 break; 429 case 4: 430 // listen arguments: [ 431 // fd: sock (resource) 432 // backlog: int32 = 0xfffffffe (4 bytes) 433 // ] 434 syscall(SYS_listen, /*fd=*/r[1], /*backlog=*/0xfffffffe); 435 break; 436 case 5: 437 // sendmsg\$unix arguments: [ 438 // fd: sock_unix (resource) 439 // msg: ptr[in, msghdr_un] { 440 // msghdr_un { 441 // addr: nil 442 // addrlen: len = 0x0 (4 bytes) 443 // pad = 0x0 (4 bytes) 444 // vec: nil 445 // vlen: len = 0x0 (8 bytes) 446 // ctrl: ptr[inout, array[ANYUNION]] { 447 // array[ANYUNION] { 448 // union ANYUNION { 449 // ANYBLOB: buffer: {89 00 00 00 ff ff 00 00 01} (length 0x9) 450 // } 451 // } 452 // } 453 // ctrllen: bytesize = 0x9 (8 bytes) 454 // f: send_flags = 0x0 (4 bytes) 455 // pad = 0x0 (4 bytes) 456 // } 457 // } 458 // f: send_flags = 0x0 (8 bytes) 459 // ] 460 *(uint64_t*)0x200000000080 = 0; 461 *(uint32_t*)0x200000000088 = 0; 462 *(uint64_t*)0x200000000090 = 0; 463 *(uint64_t*)0x200000000098 = 0; 464 *(uint64_t*)0x2000000000a0 = 0x200000000000; 465 memcpy((void*)0x200000000000, "\x89\x00\x00\x00\xff\xff\x00\x00\x01", 9); 466 *(uint64_t*)0x2000000000a8 = 9; 467 *(uint32_t*)0x2000000000b0 = 0; 468 syscall(SYS_sendmsg, /*fd=*/(intptr_t)-1, /*msg=*/0x200000000080ul, 469 /*f=*/0ul); 470 break; 471 case 6: 472 // socketpair\$unix arguments: [ 473 // domain: const = 0x1 (8 bytes) 474 // type: unix_socket_type = 0x2 (8 bytes) 475 // proto: const = 0x0 (1 bytes) 476 // fds: ptr[out, unix_pair] { 477 // unix_pair { 478 // fd0: sock_unix (resource) 479 // fd1: sock_unix (resource) 480 // } 481 // } 482 // ] 483 res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_DGRAM*/ 2ul, 484 /*proto=*/0, /*fds=*/0x200000000040ul); 485 if (res != -1) 486 r[2] = *(uint32_t*)0x200000000040; 487 break; 488 case 7: 489 // sendmsg arguments: [ 490 // fd: sock (resource) 491 // msg: ptr[in, send_msghdr] { 492 // send_msghdr { 493 // msg_name: nil 494 // msg_namelen: len = 0x32c (4 bytes) 495 // pad = 0x0 (4 bytes) 496 // msg_iov: nil 497 // msg_iovlen: len = 0x0 (8 bytes) 498 // msg_control: ptr[in, array[cmsghdr]] { 499 // array[cmsghdr] { 500 // } 501 // } 502 // msg_controllen: bytesize = 0x90 (8 bytes) 503 // msg_flags: const = 0x0 (4 bytes) 504 // pad = 0x0 (4 bytes) 505 // } 506 // } 507 // f: send_flags = 0x0 (8 bytes) 508 // ] 509 *(uint64_t*)0x200000000380 = 0; 510 *(uint32_t*)0x200000000388 = 0x32c; 511 *(uint64_t*)0x200000000390 = 0; 512 *(uint64_t*)0x200000000398 = 0; 513 *(uint64_t*)0x2000000003a0 = 0x200000000000; 514 *(uint64_t*)0x2000000003a8 = 0x90; 515 *(uint32_t*)0x2000000003b0 = 0; 516 syscall(SYS_sendmsg, /*fd=*/r[2], /*msg=*/0x200000000380ul, /*f=*/0ul); 517 break; 518 } 519} 520int main(void) 521{ 522 syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, 523 /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, 524 /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, 525 /*fd=*/(intptr_t)-1, /*offset=*/0ul); 526 const char* reason; 527 (void)reason; 528 for (procid = 0; procid < 4; procid++) { 529 if (fork() == 0) { 530 use_temporary_dir(); 531 do_sandbox_none(); 532 } 533 } 534 sleep(1000000); 535 return 0; 536} 537EOF 538mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -pthread || exit 1 539 540work=/tmp/$prog.dir 541rm -rf $work 542mkdir $work 543cd /tmp/$prog.dir 544for i in `jot 30`; do 545 ( 546 mkdir d$i 547 cd d$i 548 timeout 3m /tmp/$prog > /dev/null 2>&1 & 549 ) 550done 551while pgrep -q $prog; do sleep 2; done 552wait 553 554rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core $work 555exit 0 556