1#!/bin/sh 2 3# panic: Assertion !(sb->sb_state & SBS_CANTRCVMORE) failed at ../../../kern/uipc_usrreq.c:1549 4# cpuid = 6 5# time = 1754809105 6# KDB: stack backtrace: 7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0176ef6a80 8# vpanic() at vpanic+0x136/frame 0xfffffe0176ef6bb0 9# panic() at panic+0x43/frame 0xfffffe0176ef6c10 10# uipc_soreceive_stream_or_seqpacket() at uipc_soreceive_stream_or_seqpacket+0x968/frame 0xfffffe0176ef6cd0 11# soreceive() at soreceive+0x45/frame 0xfffffe0176ef6cf0 12# kern_recvit() at kern_recvit+0x181/frame 0xfffffe0176ef6da0 13# sys_recvmsg() at sys_recvmsg+0x67/frame 0xfffffe0176ef6e00 14# amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe0176ef6f30 15# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0176ef6f30 16# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x821d3da8a, rsp = 0x824440f68, rbp = 0x824440f90 --- 17# KDB: enter: panic 18# [ thread pid 17448 tid 292963 ] 19# Stopped at kdb_enter+0x33: movq $0,0x12304a2(%rip) 20# db> x/s version 21# version: FreeBSD 15.0-PRERELEASE #0 main-n279510-db7c0e32a05d-dirty: Sat Aug 9 17:21:54 CEST 2025 22# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO 23# db> 24 25[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 26 27. ../default.cfg 28set -u 29prog=$(basename "$0" .sh) 30cat > /tmp/$prog.c <<EOF 31// https://syzkaller.appspot.com/bug?id=79d6de939eb5c7de69e8e4993b6239aa0ae67335 32// autogenerated by syzkaller (https://github.com/google/syzkaller) 33// syzbot+ffcc3612ea266e36604e@syzkaller.appspotmail.com 34 35#define _GNU_SOURCE 36 37#include <sys/types.h> 38 39#include <errno.h> 40#include <pthread.h> 41#include <pwd.h> 42#include <signal.h> 43#include <stdarg.h> 44#include <stdbool.h> 45#include <stdint.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <sys/endian.h> 50#include <sys/resource.h> 51#include <sys/syscall.h> 52#include <sys/wait.h> 53#include <time.h> 54#include <unistd.h> 55 56static unsigned long long procid; 57 58static void kill_and_wait(int pid, int* status) 59{ 60 kill(pid, SIGKILL); 61 while (waitpid(-1, status, 0) != pid) { 62 } 63} 64 65static void sleep_ms(uint64_t ms) 66{ 67 usleep(ms * 1000); 68} 69 70static uint64_t current_time_ms(void) 71{ 72 struct timespec ts; 73 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 74 exit(1); 75 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 76} 77 78static void thread_start(void* (*fn)(void*), void* arg) 79{ 80 pthread_t th; 81 pthread_attr_t attr; 82 pthread_attr_init(&attr); 83 pthread_attr_setstacksize(&attr, 128 << 10); 84 int i = 0; 85 for (; i < 100; i++) { 86 if (pthread_create(&th, &attr, fn, arg) == 0) { 87 pthread_attr_destroy(&attr); 88 return; 89 } 90 if (errno == EAGAIN) { 91 usleep(50); 92 continue; 93 } 94 break; 95 } 96 exit(1); 97} 98 99typedef struct { 100 pthread_mutex_t mu; 101 pthread_cond_t cv; 102 int state; 103} event_t; 104 105static void event_init(event_t* ev) 106{ 107 if (pthread_mutex_init(&ev->mu, 0)) 108 exit(1); 109 if (pthread_cond_init(&ev->cv, 0)) 110 exit(1); 111 ev->state = 0; 112} 113 114static void event_reset(event_t* ev) 115{ 116 ev->state = 0; 117} 118 119static void event_set(event_t* ev) 120{ 121 pthread_mutex_lock(&ev->mu); 122 if (ev->state) 123 exit(1); 124 ev->state = 1; 125 pthread_mutex_unlock(&ev->mu); 126 pthread_cond_broadcast(&ev->cv); 127} 128 129static void event_wait(event_t* ev) 130{ 131 pthread_mutex_lock(&ev->mu); 132 while (!ev->state) 133 pthread_cond_wait(&ev->cv, &ev->mu); 134 pthread_mutex_unlock(&ev->mu); 135} 136 137static int event_isset(event_t* ev) 138{ 139 pthread_mutex_lock(&ev->mu); 140 int res = ev->state; 141 pthread_mutex_unlock(&ev->mu); 142 return res; 143} 144 145static int event_timedwait(event_t* ev, uint64_t timeout) 146{ 147 uint64_t start = current_time_ms(); 148 uint64_t now = start; 149 pthread_mutex_lock(&ev->mu); 150 for (;;) { 151 if (ev->state) 152 break; 153 uint64_t remain = timeout - (now - start); 154 struct timespec ts; 155 ts.tv_sec = remain / 1000; 156 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 157 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 158 now = current_time_ms(); 159 if (now - start > timeout) 160 break; 161 } 162 int res = ev->state; 163 pthread_mutex_unlock(&ev->mu); 164 return res; 165} 166 167static void sandbox_common() 168{ 169 struct rlimit rlim; 170 rlim.rlim_cur = rlim.rlim_max = 128 << 20; 171 setrlimit(RLIMIT_AS, &rlim); 172 rlim.rlim_cur = rlim.rlim_max = 8 << 20; 173 setrlimit(RLIMIT_MEMLOCK, &rlim); 174 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 175 setrlimit(RLIMIT_FSIZE, &rlim); 176 rlim.rlim_cur = rlim.rlim_max = 1 << 20; 177 setrlimit(RLIMIT_STACK, &rlim); 178 rlim.rlim_cur = rlim.rlim_max = 0; 179 setrlimit(RLIMIT_CORE, &rlim); 180 rlim.rlim_cur = rlim.rlim_max = 256; 181 setrlimit(RLIMIT_NOFILE, &rlim); 182} 183 184static void loop(); 185 186static int do_sandbox_none(void) 187{ 188 sandbox_common(); 189 loop(); 190 return 0; 191} 192 193struct thread_t { 194 int created, call; 195 event_t ready, done; 196}; 197 198static struct thread_t threads[16]; 199static void execute_call(int call); 200static int running; 201 202static void* thr(void* arg) 203{ 204 struct thread_t* th = (struct thread_t*)arg; 205 for (;;) { 206 event_wait(&th->ready); 207 event_reset(&th->ready); 208 execute_call(th->call); 209 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 210 event_set(&th->done); 211 } 212 return 0; 213} 214 215static void execute_one(void) 216{ 217 if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { 218 } 219 int i, call, thread; 220 for (call = 0; call < 4; call++) { 221 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 222 thread++) { 223 struct thread_t* th = &threads[thread]; 224 if (!th->created) { 225 th->created = 1; 226 event_init(&th->ready); 227 event_init(&th->done); 228 event_set(&th->done); 229 thread_start(thr, th); 230 } 231 if (!event_isset(&th->done)) 232 continue; 233 event_reset(&th->done); 234 th->call = call; 235 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 236 event_set(&th->ready); 237 event_timedwait(&th->done, 50); 238 break; 239 } 240 } 241 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 242 sleep_ms(1); 243} 244 245static void execute_one(void); 246 247#define WAIT_FLAGS 0 248 249static void loop(void) 250{ 251// int iter = 0; 252 for (;; /*iter++*/) { 253 int pid = fork(); 254 if (pid < 0) 255 exit(1); 256 if (pid == 0) { 257 execute_one(); 258 exit(0); 259 } 260 int status = 0; 261 uint64_t start = current_time_ms(); 262 for (;;) { 263 sleep_ms(10); 264 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 265 break; 266 if (current_time_ms() - start < 5000) 267 continue; 268 kill_and_wait(pid, &status); 269 break; 270 } 271 } 272} 273 274uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; 275 276void execute_call(int call) 277{ 278 intptr_t res = 0; 279 switch (call) { 280 case 0: 281 // socketpair\$unix arguments: [ 282 // domain: const = 0x1 (8 bytes) 283 // type: unix_socket_type = 0x5 (8 bytes) 284 // proto: const = 0x0 (1 bytes) 285 // fds: ptr[out, unix_pair] { 286 // unix_pair { 287 // fd0: sock_unix (resource) 288 // fd1: sock_unix (resource) 289 // } 290 // } 291 // ] 292 res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_SEQPACKET*/ 5ul, 293 /*proto=*/0, /*fds=*/0x200000000440ul); 294 if (res != -1) { 295 r[0] = *(uint32_t*)0x200000000440; 296 r[1] = *(uint32_t*)0x200000000444; 297 } 298 break; 299 case 1: 300 // sendmsg arguments: [ 301 // fd: sock (resource) 302 // msg: ptr[in, send_msghdr] { 303 // send_msghdr { 304 // msg_name: nil 305 // msg_namelen: len = 0x0 (4 bytes) 306 // pad = 0x0 (4 bytes) 307 // msg_iov: nil 308 // msg_iovlen: len = 0x0 (8 bytes) 309 // msg_control: ptr[inout, array[ANYUNION]] { 310 // array[ANYUNION] { 311 // union ANYUNION { 312 // ANYBLOB: buffer: {04 01 00 00 ff ff 00 00 01} (length 0x9) 313 // } 314 // } 315 // } 316 // msg_controllen: bytesize = 0x104 (8 bytes) 317 // msg_flags: const = 0x0 (4 bytes) 318 // pad = 0x0 (4 bytes) 319 // } 320 // } 321 // f: send_flags = 0x0 (8 bytes) 322 // ] 323 *(uint64_t*)0x200000000000 = 0; 324 *(uint32_t*)0x200000000008 = 0; 325 *(uint64_t*)0x200000000010 = 0; 326 *(uint64_t*)0x200000000018 = 0; 327 *(uint64_t*)0x200000000020 = 0x2000000007c0; 328 memcpy((void*)0x2000000007c0, "\x04\x01\x00\x00\xff\xff\x00\x00\x01", 9); 329 *(uint64_t*)0x200000000028 = 0x104; 330 *(uint32_t*)0x200000000030 = 0; 331 syscall(SYS_sendmsg, /*fd=*/r[1], /*msg=*/0x200000000000ul, /*f=*/0ul); 332 for (int i = 0; i < 32; i++) { 333 syscall(SYS_sendmsg, /*fd=*/r[1], /*msg=*/0x200000000000ul, /*f=*/0ul); 334 } 335 break; 336 case 2: 337 // close arguments: [ 338 // fd: fd (resource) 339 // ] 340 syscall(SYS_close, /*fd=*/r[1]); 341 break; 342 case 3: 343 // recvmsg arguments: [ 344 // fd: sock (resource) 345 // msg: ptr[inout, recv_msghdr] { 346 // recv_msghdr { 347 // msg_name: nil 348 // msg_namelen: len = 0x0 (4 bytes) 349 // pad = 0x0 (4 bytes) 350 // msg_iov: nil 351 // msg_iovlen: len = 0x0 (8 bytes) 352 // msg_control: ptr[out, buffer] { 353 // buffer: (DirOut) 354 // } 355 // msg_controllen: len = 0x19 (8 bytes) 356 // msg_flags: const = 0x0 (4 bytes) 357 // pad = 0x0 (4 bytes) 358 // } 359 // } 360 // f: recv_flags = 0x80 (8 bytes) 361 // ] 362 *(uint64_t*)0x2000000005c0 = 0; 363 *(uint32_t*)0x2000000005c8 = 0; 364 *(uint64_t*)0x2000000005d0 = 0; 365 *(uint64_t*)0x2000000005d8 = 0; 366 *(uint64_t*)0x2000000005e0 = 0x200000000580; 367 *(uint64_t*)0x2000000005e8 = 0x19; 368 *(uint32_t*)0x2000000005f0 = 0; 369 syscall(SYS_recvmsg, /*fd=*/r[0], /*msg=*/0x2000000005c0ul, 370 /*f=MSG_DONTWAIT*/ 0x80ul); 371 break; 372 } 373} 374int main(void) 375{ 376 syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, 377 /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, 378 /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, 379 /*fd=*/(intptr_t)-1, /*offset=*/0ul); 380 const char* reason; 381 (void)reason; 382 for (procid = 0; procid < 4; procid++) { 383 if (fork() == 0) { 384 do_sandbox_none(); 385 } 386 } 387 sleep(1000000); 388 return 0; 389} 390EOF 391mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -pthread || exit 1 392 393work=/tmp/$prog.dir 394rm -rf $work 395mkdir $work 396cd /tmp/$prog.dir 397kldstat | grep -q sctp || { kldload sctp.ko && loaded=1; } 398timeout 3m /tmp/$prog > /dev/null 2>&1 399 400rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core $work 401[ $loaded ] && kldunload sctp.ko 402exit 0 403