1#!/bin/sh 2 3# panic: mtx_lock() of spin mutex (null) @ ../../../kern/uipc_ktls.c:1034 4# cpuid = 5 5# time = 1591684934 6# KDB: stack backtrace: 7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe013a91b6c0 8# vpanic() at vpanic+0x182/frame 0xfffffe013a91b710 9# panic() at panic+0x43/frame 0xfffffe013a91b770 10# __mtx_lock_flags() at __mtx_lock_flags+0x13c/frame 0xfffffe013a91b7c0 11# ktls_get_rx_mode() at ktls_get_rx_mode+0x4e/frame 0xfffffe013a91b7f0 12# tcp_default_ctloutput() at tcp_default_ctloutput+0x800/frame 0xfffffe013a91b960 13# tcp_ctloutput() at tcp_ctloutput+0x1f5/frame 0xfffffe013a91b9d0 14# sogetopt() at sogetopt+0x101/frame 0xfffffe013a91ba40 15# kern_getsockopt() at kern_getsockopt+0xb4/frame 0xfffffe013a91baa0 16# sys_getsockopt() at sys_getsockopt+0x52/frame 0xfffffe013a91bad0 17# amd64_syscall() at amd64_syscall+0x159/frame 0xfffffe013a91bbf0 18# fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe013a91bbf0 19# --- syscall (0, FreeBSD ELF64, nosys), rip = 0x80045446a, rsp = 0x7fffdffdcf88, rbp = 0x7fffdffdcfc0 --- 20# KDB: enter: panic 21# [ thread pid 5313 tid 101679 ] 22# Stopped at kdb_enter+0x37: movq $0,0x10c7fa6(%rip) 23# db> x/s version 24# version: FreeBSD 13.0-CURRENT #0 r361886: Tue Jun 9 08:32:24 CEST 2020\012 pho@t2.osted.lan:/usr/src/sys/amd64/compile/KTLS\012 25# db> 26 27# Reproduced on r361886 with "options KERN_TLS" 28 29[ `uname -p` = "i386" ] && exit 0 30 31. ../default.cfg 32cat > /tmp/syzkaller14.c <<EOF 33// https://syzkaller.appspot.com/bug?id=d50164ce557a20a785510aac5d6f104d8a62e779 34// autogenerated by syzkaller (https://github.com/google/syzkaller) 35// Reported-by: syzbot+a8829e888a93a4a04619@syzkaller.appspotmail.com 36 37#define _GNU_SOURCE 38 39#include <sys/types.h> 40 41#include <errno.h> 42#include <pthread.h> 43#include <pwd.h> 44#include <signal.h> 45#include <stdarg.h> 46#include <stdbool.h> 47#include <stdint.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <sys/endian.h> 52#include <sys/syscall.h> 53#include <sys/wait.h> 54#include <time.h> 55#include <unistd.h> 56 57static unsigned long long procid; 58 59static void kill_and_wait(int pid, int* status) 60{ 61 kill(pid, SIGKILL); 62 while (waitpid(-1, status, 0) != pid) { 63 } 64} 65 66static void sleep_ms(uint64_t ms) 67{ 68 usleep(ms * 1000); 69} 70 71static uint64_t current_time_ms(void) 72{ 73 struct timespec ts; 74 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 75 exit(1); 76 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 77} 78 79static void thread_start(void* (*fn)(void*), void* arg) 80{ 81 pthread_t th; 82 pthread_attr_t attr; 83 pthread_attr_init(&attr); 84 pthread_attr_setstacksize(&attr, 128 << 10); 85 int i; 86 for (i = 0; i < 100; i++) { 87 if (pthread_create(&th, &attr, fn, arg) == 0) { 88 pthread_attr_destroy(&attr); 89 return; 90 } 91 if (errno == EAGAIN) { 92 usleep(50); 93 continue; 94 } 95 break; 96 } 97 exit(1); 98} 99 100typedef struct { 101 pthread_mutex_t mu; 102 pthread_cond_t cv; 103 int state; 104} event_t; 105 106static void event_init(event_t* ev) 107{ 108 if (pthread_mutex_init(&ev->mu, 0)) 109 exit(1); 110 if (pthread_cond_init(&ev->cv, 0)) 111 exit(1); 112 ev->state = 0; 113} 114 115static void event_reset(event_t* ev) 116{ 117 ev->state = 0; 118} 119 120static void event_set(event_t* ev) 121{ 122 pthread_mutex_lock(&ev->mu); 123 if (ev->state) 124 exit(1); 125 ev->state = 1; 126 pthread_mutex_unlock(&ev->mu); 127 pthread_cond_broadcast(&ev->cv); 128} 129 130static void event_wait(event_t* ev) 131{ 132 pthread_mutex_lock(&ev->mu); 133 while (!ev->state) 134 pthread_cond_wait(&ev->cv, &ev->mu); 135 pthread_mutex_unlock(&ev->mu); 136} 137 138static int event_isset(event_t* ev) 139{ 140 pthread_mutex_lock(&ev->mu); 141 int res = ev->state; 142 pthread_mutex_unlock(&ev->mu); 143 return res; 144} 145 146static int event_timedwait(event_t* ev, uint64_t timeout) 147{ 148 uint64_t start = current_time_ms(); 149 uint64_t now = start; 150 pthread_mutex_lock(&ev->mu); 151 for (;;) { 152 if (ev->state) 153 break; 154 uint64_t remain = timeout - (now - start); 155 struct timespec ts; 156 ts.tv_sec = remain / 1000; 157 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 158 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 159 now = current_time_ms(); 160 if (now - start > timeout) 161 break; 162 } 163 int res = ev->state; 164 pthread_mutex_unlock(&ev->mu); 165 return res; 166} 167 168struct thread_t { 169 int created, call; 170 event_t ready, done; 171}; 172 173static struct thread_t threads[16]; 174static void execute_call(int call); 175static int running; 176 177static void* thr(void* arg) 178{ 179 struct thread_t* th = (struct thread_t*)arg; 180 for (;;) { 181 event_wait(&th->ready); 182 event_reset(&th->ready); 183 execute_call(th->call); 184 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 185 event_set(&th->done); 186 } 187 return 0; 188} 189 190static void execute_one(void) 191{ 192 int i, call, thread; 193 int collide = 0; 194again: 195 for (call = 0; call < 3; call++) { 196 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 197 thread++) { 198 struct thread_t* th = &threads[thread]; 199 if (!th->created) { 200 th->created = 1; 201 event_init(&th->ready); 202 event_init(&th->done); 203 event_set(&th->done); 204 thread_start(thr, th); 205 } 206 if (!event_isset(&th->done)) 207 continue; 208 event_reset(&th->done); 209 th->call = call; 210 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 211 event_set(&th->ready); 212 if (collide && (call % 2) == 0) 213 break; 214 event_timedwait(&th->done, 45); 215 break; 216 } 217 } 218 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 219 sleep_ms(1); 220 if (!collide) { 221 collide = 1; 222 goto again; 223 } 224} 225 226static void execute_one(void); 227 228#define WAIT_FLAGS 0 229 230static void loop(void) 231{ 232 int iter; 233 for (iter = 0;; iter++) { 234 int pid = fork(); 235 if (pid < 0) 236 exit(1); 237 if (pid == 0) { 238 execute_one(); 239 exit(0); 240 } 241 int status = 0; 242 uint64_t start = current_time_ms(); 243 for (;;) { 244 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 245 break; 246 sleep_ms(1); 247 if (current_time_ms() - start < 5 * 1000) 248 continue; 249 kill_and_wait(pid, &status); 250 break; 251 } 252 } 253} 254 255uint64_t r[1] = {0xffffffffffffffff}; 256 257void execute_call(int call) 258{ 259 intptr_t res = 0; 260 switch (call) { 261 case 0: 262 res = syscall(SYS_socket, 0x1cul, 1ul, 0); 263 if (res != -1) 264 r[0] = res; 265 break; 266 case 1: 267 syscall(SYS_getsockopt, r[0], 6, 0x2a, 0ul, 0ul); 268 break; 269 case 2: 270 syscall(SYS_listen, r[0], 1); 271 break; 272 } 273} 274int main(void) 275{ 276 syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 277 for (procid = 0; procid < 4; procid++) { 278 if (fork() == 0) { 279 loop(); 280 } 281 } 282 sleep(1000000); 283 return 0; 284} 285EOF 286mycc -o /tmp/syzkaller14 -Wall -Wextra -O2 /tmp/syzkaller14.c -lpthread || 287 exit 1 288 289(cd /tmp; ./syzkaller14) & 290sleep 60 291pkill -9 syzkaller14 292wait 293 294rm -f /tmp/syzkaller14 /tmp/syzkaller14.c /tmp/syzkaller14.core 295exit 0 296