1#!/bin/sh 2 3# panic: Assertion done != job_total_nbytes failed at ../../../kern/sys_socket.c:672 4# cpuid = 6 5# time = 1630912129 6# KDB: stack backtrace: 7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00e4f2fa10 8# vpanic() at vpanic+0x187/frame 0xfffffe00e4f2fa70 9# panic() at panic+0x43/frame 0xfffffe00e4f2fad0 10# soaio_process_sb() at soaio_process_sb+0x79a/frame 0xfffffe00e4f2fb70 11# soaio_kproc_loop() at soaio_kproc_loop+0x96/frame 0xfffffe00e4f2fbb0 12# fork_exit() at fork_exit+0x80/frame 0xfffffe00e4f2fbf0 13# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00e4f2fbf0 14# --- trap 0, rip = 0, rsp = 0, rbp = 0 --- 15# KDB: enter: panic 16# [ thread pid 26 tid 100163 ] 17# Stopped at kdb_enter+0x37: movq $0,0x127297e(%rip) 18# db> x/s version 19# version: FreeBSD 14.0-CURRENT #0 main-n249158-1f7a6325fe1b: Sun Sep 5 09:12:58 CEST 2021 20# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO 21# db> 22 23[ `uname -p` != "amd64" ] && exit 0 24[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 25 26. ../default.cfg 27cat > /tmp/syzkaller43.c <<EOF 28// https://syzkaller.appspot.com/bug?id=0ecbaedb9a54dd1af01c400dabe774e5c6c6fb6c 29// autogenerated by syzkaller (https://github.com/google/syzkaller) 30// Reported-by: syzbot+c7d22dbbb9aef509421d@syzkaller.appspotmail.com 31 32#define _GNU_SOURCE 33 34#include <sys/types.h> 35 36#include <errno.h> 37#include <pthread.h> 38#include <pwd.h> 39#include <signal.h> 40#include <stdarg.h> 41#include <stdbool.h> 42#include <stdint.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <sys/endian.h> 47#include <sys/syscall.h> 48#include <sys/wait.h> 49#include <time.h> 50#include <unistd.h> 51 52static void kill_and_wait(int pid, int* status) 53{ 54 kill(pid, SIGKILL); 55 while (waitpid(-1, status, 0) != pid) { 56 } 57} 58 59static void sleep_ms(uint64_t ms) 60{ 61 usleep(ms * 1000); 62} 63 64static uint64_t current_time_ms(void) 65{ 66 struct timespec ts; 67 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 68 exit(1); 69 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 70} 71 72static void thread_start(void* (*fn)(void*), void* arg) 73{ 74 pthread_t th; 75 pthread_attr_t attr; 76 pthread_attr_init(&attr); 77 pthread_attr_setstacksize(&attr, 128 << 10); 78 int i = 0; 79 for (; i < 100; i++) { 80 if (pthread_create(&th, &attr, fn, arg) == 0) { 81 pthread_attr_destroy(&attr); 82 return; 83 } 84 if (errno == EAGAIN) { 85 usleep(50); 86 continue; 87 } 88 break; 89 } 90 exit(1); 91} 92 93typedef struct { 94 pthread_mutex_t mu; 95 pthread_cond_t cv; 96 int state; 97} event_t; 98 99static void event_init(event_t* ev) 100{ 101 if (pthread_mutex_init(&ev->mu, 0)) 102 exit(1); 103 if (pthread_cond_init(&ev->cv, 0)) 104 exit(1); 105 ev->state = 0; 106} 107 108static void event_reset(event_t* ev) 109{ 110 ev->state = 0; 111} 112 113static void event_set(event_t* ev) 114{ 115 pthread_mutex_lock(&ev->mu); 116 if (ev->state) 117 exit(1); 118 ev->state = 1; 119 pthread_mutex_unlock(&ev->mu); 120 pthread_cond_broadcast(&ev->cv); 121} 122 123static void event_wait(event_t* ev) 124{ 125 pthread_mutex_lock(&ev->mu); 126 while (!ev->state) 127 pthread_cond_wait(&ev->cv, &ev->mu); 128 pthread_mutex_unlock(&ev->mu); 129} 130 131static int event_isset(event_t* ev) 132{ 133 pthread_mutex_lock(&ev->mu); 134 int res = ev->state; 135 pthread_mutex_unlock(&ev->mu); 136 return res; 137} 138 139static int event_timedwait(event_t* ev, uint64_t timeout) 140{ 141 uint64_t start = current_time_ms(); 142 uint64_t now = start; 143 pthread_mutex_lock(&ev->mu); 144 for (;;) { 145 if (ev->state) 146 break; 147 uint64_t remain = timeout - (now - start); 148 struct timespec ts; 149 ts.tv_sec = remain / 1000; 150 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 151 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 152 now = current_time_ms(); 153 if (now - start > timeout) 154 break; 155 } 156 int res = ev->state; 157 pthread_mutex_unlock(&ev->mu); 158 return res; 159} 160 161struct thread_t { 162 int created, call; 163 event_t ready, done; 164}; 165 166static struct thread_t threads[16]; 167static void execute_call(int call); 168static int running; 169 170static void* thr(void* arg) 171{ 172 struct thread_t* th = (struct thread_t*)arg; 173 for (;;) { 174 event_wait(&th->ready); 175 event_reset(&th->ready); 176 execute_call(th->call); 177 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 178 event_set(&th->done); 179 } 180 return 0; 181} 182 183static void execute_one(void) 184{ 185 int i, call, thread; 186 for (call = 0; call < 5; call++) { 187 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 188 thread++) { 189 struct thread_t* th = &threads[thread]; 190 if (!th->created) { 191 th->created = 1; 192 event_init(&th->ready); 193 event_init(&th->done); 194 event_set(&th->done); 195 thread_start(thr, th); 196 } 197 if (!event_isset(&th->done)) 198 continue; 199 event_reset(&th->done); 200 th->call = call; 201 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 202 event_set(&th->ready); 203 event_timedwait(&th->done, 50); 204 break; 205 } 206 } 207 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 208 sleep_ms(1); 209} 210 211static void execute_one(void); 212 213#define WAIT_FLAGS 0 214 215static void loop(void) 216{ 217 int iter = 0; 218 for (;; iter++) { 219 int pid = fork(); 220 if (pid < 0) 221 exit(1); 222 if (pid == 0) { 223 execute_one(); 224 exit(0); 225 } 226 int status = 0; 227 uint64_t start = current_time_ms(); 228 for (;;) { 229 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 230 break; 231 sleep_ms(1); 232 if (current_time_ms() - start < 5000) { 233 continue; 234 } 235 kill_and_wait(pid, &status); 236 break; 237 } 238 } 239} 240 241#ifndef SYS_aio_readv 242#define SYS_aio_readv 579 243#endif 244 245uint64_t r[1] = {0xffffffffffffffff}; 246 247void execute_call(int call) 248{ 249 intptr_t res = 0; 250 switch (call) { 251 case 0: 252 res = syscall(SYS_socket, 0x1cul, 5ul, 0x84); 253 if (res != -1) 254 r[0] = res; 255 break; 256 case 1: 257 *(uint64_t*)0x20000440 = 0; 258 *(uint32_t*)0x20000448 = 0; 259 *(uint64_t*)0x20000450 = 0; 260 *(uint64_t*)0x20000458 = 0; 261 *(uint64_t*)0x20000460 = 0; 262 *(uint64_t*)0x20000468 = 0; 263 *(uint32_t*)0x20000470 = 0; 264 syscall(SYS_recvmsg, r[0], 0x20000440ul, 0x40040ul); 265 break; 266 case 2: 267 *(uint32_t*)0x200006c0 = r[0]; 268 *(uint64_t*)0x200006c8 = 0x800; 269 *(uint64_t*)0x200006d0 = 0; 270 *(uint64_t*)0x200006d8 = 0; 271 *(uint32_t*)0x200006e0 = -1; 272 *(uint32_t*)0x200006e4 = 8; 273 *(uint64_t*)0x200006e8 = 0xffffffffffff658c; 274 *(uint32_t*)0x200006f0 = 4; 275 *(uint32_t*)0x200006f4 = 0x1ff; 276 *(uint64_t*)0x200006f8 = 0x40; 277 *(uint64_t*)0x20000700 = 0; 278 *(uint64_t*)0x20000708 = 0; 279 *(uint32_t*)0x20000710 = 4; 280 *(uint32_t*)0x20000714 = 8; 281 *(uint32_t*)0x20000718 = 6; 282 *(uint64_t*)0x20000720 = 0; 283 *(uint64_t*)0x20000728 = 0; 284 syscall(SYS_aio_readv, 0x200006c0ul); 285 break; 286 case 3: 287 *(uint32_t*)0x20000140 = 0; 288 *(uint16_t*)0x20000144 = 4; 289 *(uint8_t*)0x20000146 = 1; 290 syscall(SYS_setsockopt, r[0], 0x84, 0x1e, 0x20000140ul, 8ul); 291 break; 292 case 4: 293 *(uint64_t*)0x20000580 = 0x20000080; 294 *(uint8_t*)0x20000080 = 0x1c; 295 *(uint8_t*)0x20000081 = 0x1c; 296 *(uint16_t*)0x20000082 = htobe16(0x4e22); 297 *(uint32_t*)0x20000084 = 0; 298 *(uint64_t*)0x20000088 = htobe64(0); 299 *(uint64_t*)0x20000090 = htobe64(1); 300 *(uint32_t*)0x20000098 = 0; 301 *(uint32_t*)0x20000588 = 0x1c; 302 *(uint64_t*)0x20000590 = 0x20000400; 303 *(uint64_t*)0x20000400 = 0x200000c0; 304 memset((void*)0x200000c0, 239, 1); 305 *(uint64_t*)0x20000408 = 1; 306 *(uint32_t*)0x20000598 = 1; 307 *(uint64_t*)0x200005a0 = 0; 308 *(uint32_t*)0x200005a8 = 0xd0; 309 *(uint32_t*)0x200005ac = 0; 310 syscall(SYS_sendmsg, r[0], 0x20000580ul, 0ul); 311 break; 312 } 313} 314int main(void) 315{ 316 syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 317 loop(); 318 return 0; 319} 320EOF 321mycc -o /tmp/syzkaller43 -Wall -Wextra -O0 /tmp/syzkaller43.c -lpthread || 322 exit 1 323 324(cd /tmp; timeout 3m ./syzkaller43) 325 326rm -rf /tmp/syzkaller43 syzkaller43.c /tmp/syzkaller.* 327exit 0 328