1#!/bin/sh 2 3# panic: mtx_lock() of spin mutex (null) @ ../../../netinet/tcp_output.c:350 4# cpuid = 1 5# time = 1587276361 6# KDB: stack backtrace: 7# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01388956f0 8# vpanic() at vpanic+0x182/frame 0xfffffe0138895740 9# panic() at panic+0x43/frame 0xfffffe01388957a0 10# __mtx_lock_flags() at __mtx_lock_flags+0x13c/frame 0xfffffe01388957f0 11# tcp_output() at tcp_output+0x34e/frame 0xfffffe0138895980 12# tcp_usr_connect() at tcp_usr_connect+0x123/frame 0xfffffe01388959e0 13# soconnectat() at soconnectat+0xd0/frame 0xfffffe0138895a30 14# kern_connectat() at kern_connectat+0xe2/frame 0xfffffe0138895a90 15# sys_connect() at sys_connect+0x75/frame 0xfffffe0138895ad0 16# amd64_syscall() at amd64_syscall+0x159/frame 0xfffffe0138895bf0 17# fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe0138895bf0 18 19# Reproduced on r358885 20 21[ `uname -p` = "i386" ] && exit 0 22 23. ../default.cfg 24cat > /tmp/syzkaller11.c <<EOF 25// https://syzkaller.appspot.com/bug?id=f81a41d30e772445b13de6dcf07fc1afaf122a61 26// autogenerated by syzkaller (https://github.com/google/syzkaller) 27 28#define _GNU_SOURCE 29 30#include <sys/types.h> 31 32#include <errno.h> 33#include <pthread.h> 34#include <pwd.h> 35#include <signal.h> 36#include <stdarg.h> 37#include <stdbool.h> 38#include <stdint.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <sys/endian.h> 43#include <sys/syscall.h> 44#include <sys/wait.h> 45#include <time.h> 46#include <unistd.h> 47 48static void kill_and_wait(int pid, int* status) 49{ 50 kill(pid, SIGKILL); 51 while (waitpid(-1, status, 0) != pid) { 52 } 53} 54 55static void sleep_ms(uint64_t ms) 56{ 57 usleep(ms * 1000); 58} 59 60static uint64_t current_time_ms(void) 61{ 62 struct timespec ts; 63 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 64 exit(1); 65 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 66} 67 68static void thread_start(void* (*fn)(void*), void* arg) 69{ 70 pthread_t th; 71 pthread_attr_t attr; 72 pthread_attr_init(&attr); 73 pthread_attr_setstacksize(&attr, 128 << 10); 74 int i; 75 for (i = 0; i < 100; i++) { 76 if (pthread_create(&th, &attr, fn, arg) == 0) { 77 pthread_attr_destroy(&attr); 78 return; 79 } 80 if (errno == EAGAIN) { 81 usleep(50); 82 continue; 83 } 84 break; 85 } 86 exit(1); 87} 88 89typedef struct { 90 pthread_mutex_t mu; 91 pthread_cond_t cv; 92 int state; 93} event_t; 94 95static void event_init(event_t* ev) 96{ 97 if (pthread_mutex_init(&ev->mu, 0)) 98 exit(1); 99 if (pthread_cond_init(&ev->cv, 0)) 100 exit(1); 101 ev->state = 0; 102} 103 104static void event_reset(event_t* ev) 105{ 106 ev->state = 0; 107} 108 109static void event_set(event_t* ev) 110{ 111 pthread_mutex_lock(&ev->mu); 112 if (ev->state) 113 exit(1); 114 ev->state = 1; 115 pthread_mutex_unlock(&ev->mu); 116 pthread_cond_broadcast(&ev->cv); 117} 118 119static void event_wait(event_t* ev) 120{ 121 pthread_mutex_lock(&ev->mu); 122 while (!ev->state) 123 pthread_cond_wait(&ev->cv, &ev->mu); 124 pthread_mutex_unlock(&ev->mu); 125} 126 127static int event_isset(event_t* ev) 128{ 129 pthread_mutex_lock(&ev->mu); 130 int res = ev->state; 131 pthread_mutex_unlock(&ev->mu); 132 return res; 133} 134 135static int event_timedwait(event_t* ev, uint64_t timeout) 136{ 137 uint64_t start = current_time_ms(); 138 uint64_t now = start; 139 pthread_mutex_lock(&ev->mu); 140 for (;;) { 141 if (ev->state) 142 break; 143 uint64_t remain = timeout - (now - start); 144 struct timespec ts; 145 ts.tv_sec = remain / 1000; 146 ts.tv_nsec = (remain % 1000) * 1000 * 1000; 147 pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 148 now = current_time_ms(); 149 if (now - start > timeout) 150 break; 151 } 152 int res = ev->state; 153 pthread_mutex_unlock(&ev->mu); 154 return res; 155} 156 157struct thread_t { 158 int created, call; 159 event_t ready, done; 160}; 161 162static struct thread_t threads[16]; 163static void execute_call(int call); 164static int running; 165 166static void* thr(void* arg) 167{ 168 struct thread_t* th = (struct thread_t*)arg; 169 for (;;) { 170 event_wait(&th->ready); 171 event_reset(&th->ready); 172 execute_call(th->call); 173 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 174 event_set(&th->done); 175 } 176 return 0; 177} 178 179static void execute_one(void) 180{ 181 int i, call, thread; 182 int collide = 0; 183again: 184 for (call = 0; call < 4; call++) { 185 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 186 thread++) { 187 struct thread_t* th = &threads[thread]; 188 if (!th->created) { 189 th->created = 1; 190 event_init(&th->ready); 191 event_init(&th->done); 192 event_set(&th->done); 193 thread_start(thr, th); 194 } 195 if (!event_isset(&th->done)) 196 continue; 197 event_reset(&th->done); 198 th->call = call; 199 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 200 event_set(&th->ready); 201 if (collide && (call % 2) == 0) 202 break; 203 event_timedwait(&th->done, 45); 204 break; 205 } 206 } 207 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 208 sleep_ms(1); 209 if (!collide) { 210 collide = 1; 211 goto again; 212 } 213} 214 215static void execute_one(void); 216 217#define WAIT_FLAGS 0 218 219static void loop(void) 220{ 221 int iter; 222 for (iter = 0;; iter++) { 223 int pid = fork(); 224 if (pid < 0) 225 exit(1); 226 if (pid == 0) { 227 execute_one(); 228 exit(0); 229 } 230 int status = 0; 231 uint64_t start = current_time_ms(); 232 for (;;) { 233 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) 234 break; 235 sleep_ms(1); 236 if (current_time_ms() - start < 5 * 1000) 237 continue; 238 kill_and_wait(pid, &status); 239 break; 240 } 241 } 242} 243 244uint64_t r[1] = {0xffffffffffffffff}; 245 246void execute_call(int call) 247{ 248 intptr_t res; 249 switch (call) { 250 case 0: 251 res = syscall(SYS_socket, 2ul, 1ul, 0); 252 if (res != -1) 253 r[0] = res; 254 break; 255 case 1: 256 memcpy((void*)0x20000040, 257 "bbr\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" 258 "\000\000\000\000\000\000\000\000\000\000\000\000\000", 259 32); 260 *(uint32_t*)0x20000060 = 0; 261 syscall(SYS_setsockopt, r[0], 6, 0x2000, 0x20000040ul, 0x24ul); 262 break; 263 case 2: 264 *(uint8_t*)0x20000180 = 0x10; 265 *(uint8_t*)0x20000181 = 2; 266 *(uint16_t*)0x20000182 = htobe16(0x4e22); 267 *(uint32_t*)0x20000184 = htobe32(0xfff); 268 *(uint8_t*)0x20000188 = 0; 269 *(uint8_t*)0x20000189 = 0; 270 *(uint8_t*)0x2000018a = 0; 271 *(uint8_t*)0x2000018b = 0; 272 *(uint8_t*)0x2000018c = 0; 273 *(uint8_t*)0x2000018d = 0; 274 *(uint8_t*)0x2000018e = 0; 275 *(uint8_t*)0x2000018f = 0; 276 syscall(SYS_connect, r[0], 0x20000180ul, 0x10ul); 277 break; 278 case 3: 279 syscall(SYS_listen, r[0], 0); 280 break; 281 } 282} 283int main(void) 284{ 285 syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 286 loop(); 287 return 0; 288} 289EOF 290mycc -o /tmp/syzkaller11 -Wall -Wextra -O2 /tmp/syzkaller11.c -lpthread || 291 exit 1 292 293(cd /tmp; ./syzkaller11) & 294sleep 60 295pkill -9 syzkaller11 296wait 297 298rm -f /tmp/syzkaller11 /tmp/syzkaller11.c /tmp/syzkaller11.core 299exit 0 300