1#!/bin/sh 2 3# Fatal trap 12: page fault while in kernel mode 4# cpuid = 10; apic id = 0a 5# fault virtual address = 0x0 6# fault code = supervisor read data, page not present 7# instruction pointer = 0x20:0xffffffff80e04f35 8# stack pointer = 0x28:0xfffffe014fd0fbc0 9# frame pointer = 0x28:0xfffffe014fd0fc00 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 = 13332 (repro77) 14# trap number = 12 15# panic: page fault 16# cpuid = 10 17# time = 1640585179 18# KDB: stack backtrace: 19# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe014fd0f980 20# vpanic() at vpanic+0x17f/frame 0xfffffe014fd0f9d0 21# panic() at panic+0x43/frame 0xfffffe014fd0fa30 22# trap_fatal() at trap_fatal+0x385/frame 0xfffffe014fd0fa90 23# trap_pfault() at trap_pfault+0xab/frame 0xfffffe014fd0faf0 24# calltrap() at calltrap+0x8/frame 0xfffffe014fd0faf0 25# --- trap 0xc, rip = 0xffffffff80e04f35, rsp = 0xfffffe014fd0fbc0, rbp = 0xfffffe014fd0fc00 --- 26# tcp_usr_rcvd() at tcp_usr_rcvd+0x65/frame 0xfffffe014fd0fc00 27# soreceive_generic() at soreceive_generic+0xe44/frame 0xfffffe014fd0fcc0 28# soreceive() at soreceive+0x4b/frame 0xfffffe014fd0fce0 29# kern_recvit() at kern_recvit+0x1ba/frame 0xfffffe014fd0fd90 30# sys_recvmsg() at sys_recvmsg+0x6f/frame 0xfffffe014fd0fe00 31# amd64_syscall() at amd64_syscall+0x145/frame 0xfffffe014fd0ff30 32# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe014fd0ff30 33# --- syscall (0, FreeBSD ELF64, nosys), rip = 0x8020e328a, rsp = 0x22f48, rbp = 0x22f70 --- 34# KDB: enter: panic 35# [ thread pid 13332 tid 103311 ] 36# Stopped at kdb_enter+0x37: movq $0,0x128720e(%rip) 37# db> x/s version 38# version: FreeBSD 14.0-CURRENT #0 ufs-n251956-c3008785b91: Mon Dec 27 06:11:30 CET 2021 39# pho@mercat1.netperf.freebsd.org:/var/tmp/deviant3/sys/amd64/compile/PHO 40# db> 41 42. ../default.cfg 43[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 44 45cat > /tmp/syzkaller49.c <<EOF 46// https://syzkaller.appspot.com/bug?id=efb2e9f019f36fbc39380724a31cb0c458bb4e61 47// autogenerated by syzkaller (https://github.com/google/syzkaller) 48// Reported-by: syzbot+93c75c4618b2a4f0f0ac@syzkaller.appspotmail.com 49 50#define _GNU_SOURCE 51 52#include <errno.h> 53#include <pthread.h> 54#include <pwd.h> 55#include <stdarg.h> 56#include <stdbool.h> 57#include <stdint.h> 58#include <stdio.h> 59#include <stdlib.h> 60#include <string.h> 61#include <sys/endian.h> 62#include <sys/syscall.h> 63#include <time.h> 64#include <unistd.h> 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 = 0; 86 for (; 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 loop(void) 191{ 192 int i, call, thread; 193 for (call = 0; call < 6; call++) { 194 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 195 thread++) { 196 struct thread_t* th = &threads[thread]; 197 if (!th->created) { 198 th->created = 1; 199 event_init(&th->ready); 200 event_init(&th->done); 201 event_set(&th->done); 202 thread_start(thr, th); 203 } 204 if (!event_isset(&th->done)) 205 continue; 206 event_reset(&th->done); 207 th->call = call; 208 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 209 event_set(&th->ready); 210 event_timedwait(&th->done, 50); 211 break; 212 } 213 } 214 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 215 sleep_ms(1); 216} 217 218uint64_t r[1] = {0xffffffffffffffff}; 219 220void execute_call(int call) 221{ 222 intptr_t res = 0; 223 switch (call) { 224 case 0: 225 res = syscall(SYS_socket, 2ul, 1ul, 0); 226 if (res != -1) 227 r[0] = res; 228 break; 229 case 1: 230 *(uint8_t*)0x20000140 = 0x10; 231 *(uint8_t*)0x20000141 = 2; 232 *(uint16_t*)0x20000142 = htobe16(0x4e23); 233 *(uint32_t*)0x20000144 = htobe32(0x7f000001); 234 memset((void*)0x20000148, 0, 8); 235 syscall(SYS_bind, r[0], 0x20000140ul, 0x10ul); 236 break; 237 case 2: 238 *(uint8_t*)0x20000080 = 0x10; 239 *(uint8_t*)0x20000081 = 2; 240 *(uint16_t*)0x20000082 = htobe16(0x4e23); 241 *(uint32_t*)0x20000084 = htobe32(0x7f000001); 242 memset((void*)0x20000088, 0, 8); 243 syscall(SYS_sendto, r[0], 0ul, 0ul, 0ul, 0x20000080ul, 0x10ul); 244 break; 245 case 3: 246 memset((void*)0x20000100, 69, 1); 247 syscall(SYS_sendto, r[0], 0x20000100ul, 0xfda4ul, 0ul, 0ul, 0ul); 248 break; 249 case 4: 250 *(uint64_t*)0x200003c0 = 0; 251 *(uint32_t*)0x200003c8 = 0; 252 *(uint64_t*)0x200003d0 = 0x20000340; 253 *(uint64_t*)0x20000340 = 0x20000680; 254 *(uint64_t*)0x20000348 = 0x19000; 255 *(uint64_t*)0x200003d8 = 1; 256 *(uint64_t*)0x200003e0 = 0; 257 *(uint64_t*)0x200003e8 = 0; 258 *(uint32_t*)0x200003f0 = 0; 259 syscall(SYS_recvmsg, r[0], 0x200003c0ul, 0x40ul); 260 break; 261 case 5: 262 syscall(SYS_shutdown, r[0], 1ul); 263 break; 264 } 265} 266int main(void) 267{ 268 syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 269 loop(); 270 return 0; 271} 272EOF 273 274set -e 275mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 276[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 277mdconfig -a -t swap -s 5g -u $mdstart 278newfs $newfs_flags -n md$mdstart > /dev/null 279mount /dev/md$mdstart $mntpoint 280set +e 281 282mkdir $mntpoint/work 283mycc -o $mntpoint/work/syzkaller49 -Wall -Wextra -O0 /tmp/syzkaller49.c -lpthread || exit 1 284 285start=`date +%s` 286while [ $((`date +%s` - start)) -lt 120 ]; do 287 (cd $mntpoint/work; ./syzkaller49) 288done 289 290for i in `jot 6`; do 291 mount | grep -q "on $mntpoint " || break 292 umount $mntpoint && break || sleep 10 293 [ $i -eq 6 ] && 294 { echo FATAL; fstat -mf $mntpoint; exit 1; } 295done 296mdconfig -d -u $mdstart 297 298rm -rf /tmp/syzkaller49.c 299exit 0 300