1*6deacc1bSPeter Holm#!/bin/sh 2*6deacc1bSPeter Holm 3*6deacc1bSPeter Holm# panic: Assertion (cnp->cn_flags & (LOCKPARENT | WANTPARENT)) == 0 failed at ../../../kern/vfs_cache.c:4790 4*6deacc1bSPeter Holm# cpuid = 5 5*6deacc1bSPeter Holm# time = 1634453452 6*6deacc1bSPeter Holm# KDB: stack backtrace: 7*6deacc1bSPeter Holm# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0146912830 8*6deacc1bSPeter Holm# vpanic() at vpanic+0x187/frame 0xfffffe0146912890 9*6deacc1bSPeter Holm# panic() at panic+0x43/frame 0xfffffe01469128f0 10*6deacc1bSPeter Holm# cache_fplookup_emptypath() at cache_fplookup_emptypath+0x1b2/frame 0xfffffe0146912930 11*6deacc1bSPeter Holm# cache_fplookup_noentry() at cache_fplookup_noentry+0xbc/frame 0xfffffe01469129a0 12*6deacc1bSPeter Holm# cache_fplookup() at cache_fplookup+0x605/frame 0xfffffe0146912a90 13*6deacc1bSPeter Holm# namei() at namei+0x203/frame 0xfffffe0146912b50 14*6deacc1bSPeter Holm# vn_open_cred() at vn_open_cred+0x12c/frame 0xfffffe0146912cb0 15*6deacc1bSPeter Holm# kern_openat() at kern_openat+0x285/frame 0xfffffe0146912e00 16*6deacc1bSPeter Holm# amd64_syscall() at amd64_syscall+0x147/frame 0xfffffe0146912f30 17*6deacc1bSPeter Holm# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0146912f30 18*6deacc1bSPeter Holm# --- syscall (0, FreeBSD ELF64, nosys), rip = 0x8003aeafa, rsp = 0x7fffdfffdf28, rbp = 0x7fffdfffdf70 --- 19*6deacc1bSPeter Holm# KDB: enter: panic 20*6deacc1bSPeter Holm# [ thread pid 2864 tid 100315 ] 21*6deacc1bSPeter Holm# Stopped at kdb_enter+0x37: movq $0,0x126f74e(%rip) 22*6deacc1bSPeter Holm# db> x/s version 23*6deacc1bSPeter Holm# version: FreeBSD 14.0-CURRENT #0 main-n250087-a7d137fcbcac: Sun Oct 17 08:46:08 CEST 2021 24*6deacc1bSPeter Holm# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO\012 25*6deacc1bSPeter Holm# db> 26*6deacc1bSPeter Holm 27*6deacc1bSPeter Holm# Fixed by 1045352f1503 28*6deacc1bSPeter Holm 29*6deacc1bSPeter Holm[ `uname -p` != "amd64" ] && exit 0 30*6deacc1bSPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 31*6deacc1bSPeter Holm 32*6deacc1bSPeter Holm. ../default.cfg 33*6deacc1bSPeter Holmcat > /tmp/syzkaller45.c <<EOF 34*6deacc1bSPeter Holm// https://syzkaller.appspot.com/bug?id=283995ae4346041c1757f62f3322a3545d0a62a4 35*6deacc1bSPeter Holm// autogenerated by syzkaller (https://github.com/google/syzkaller) 36*6deacc1bSPeter Holm// Reported-by: syzbot+bd48ee0843206a09e6b8@syzkaller.appspotmail.com 37*6deacc1bSPeter Holm 38*6deacc1bSPeter Holm#define _GNU_SOURCE 39*6deacc1bSPeter Holm 40*6deacc1bSPeter Holm#include <errno.h> 41*6deacc1bSPeter Holm#include <pthread.h> 42*6deacc1bSPeter Holm#include <pwd.h> 43*6deacc1bSPeter Holm#include <setjmp.h> 44*6deacc1bSPeter Holm#include <signal.h> 45*6deacc1bSPeter Holm#include <stdarg.h> 46*6deacc1bSPeter Holm#include <stdbool.h> 47*6deacc1bSPeter Holm#include <stdint.h> 48*6deacc1bSPeter Holm#include <stdio.h> 49*6deacc1bSPeter Holm#include <stdlib.h> 50*6deacc1bSPeter Holm#include <string.h> 51*6deacc1bSPeter Holm#include <sys/endian.h> 52*6deacc1bSPeter Holm#include <sys/syscall.h> 53*6deacc1bSPeter Holm#include <time.h> 54*6deacc1bSPeter Holm#include <unistd.h> 55*6deacc1bSPeter Holm 56*6deacc1bSPeter Holmstatic __thread int skip_segv; 57*6deacc1bSPeter Holmstatic __thread jmp_buf segv_env; 58*6deacc1bSPeter Holm 59*6deacc1bSPeter Holmstatic void segv_handler(int sig, siginfo_t* info, void* ctx __unused) 60*6deacc1bSPeter Holm{ 61*6deacc1bSPeter Holm uintptr_t addr = (uintptr_t)info->si_addr; 62*6deacc1bSPeter Holm const uintptr_t prog_start = 1 << 20; 63*6deacc1bSPeter Holm const uintptr_t prog_end = 100 << 20; 64*6deacc1bSPeter Holm int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; 65*6deacc1bSPeter Holm int valid = addr < prog_start || addr > prog_end; 66*6deacc1bSPeter Holm if (sig == SIGBUS) 67*6deacc1bSPeter Holm valid = 1; 68*6deacc1bSPeter Holm if (skip && valid) { 69*6deacc1bSPeter Holm _longjmp(segv_env, 1); 70*6deacc1bSPeter Holm } 71*6deacc1bSPeter Holm exit(sig); 72*6deacc1bSPeter Holm} 73*6deacc1bSPeter Holm 74*6deacc1bSPeter Holmstatic void install_segv_handler(void) 75*6deacc1bSPeter Holm{ 76*6deacc1bSPeter Holm struct sigaction sa; 77*6deacc1bSPeter Holm memset(&sa, 0, sizeof(sa)); 78*6deacc1bSPeter Holm sa.sa_sigaction = segv_handler; 79*6deacc1bSPeter Holm sa.sa_flags = SA_NODEFER | SA_SIGINFO; 80*6deacc1bSPeter Holm sigaction(SIGSEGV, &sa, NULL); 81*6deacc1bSPeter Holm sigaction(SIGBUS, &sa, NULL); 82*6deacc1bSPeter Holm} 83*6deacc1bSPeter Holm 84*6deacc1bSPeter Holm#define NONFAILING(...) \ 85*6deacc1bSPeter Holm ({ \ 86*6deacc1bSPeter Holm int ok = 1; \ 87*6deacc1bSPeter Holm __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 88*6deacc1bSPeter Holm if (_setjmp(segv_env) == 0) { \ 89*6deacc1bSPeter Holm __VA_ARGS__; \ 90*6deacc1bSPeter Holm } else \ 91*6deacc1bSPeter Holm ok = 0; \ 92*6deacc1bSPeter Holm __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ 93*6deacc1bSPeter Holm ok; \ 94*6deacc1bSPeter Holm }) 95*6deacc1bSPeter Holm 96*6deacc1bSPeter Holmstatic void sleep_ms(uint64_t ms) 97*6deacc1bSPeter Holm{ 98*6deacc1bSPeter Holm usleep(ms * 1000); 99*6deacc1bSPeter Holm} 100*6deacc1bSPeter Holm 101*6deacc1bSPeter Holmstatic uint64_t current_time_ms(void) 102*6deacc1bSPeter Holm{ 103*6deacc1bSPeter Holm struct timespec ts; 104*6deacc1bSPeter Holm if (clock_gettime(CLOCK_MONOTONIC, &ts)) 105*6deacc1bSPeter Holm exit(1); 106*6deacc1bSPeter Holm return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; 107*6deacc1bSPeter Holm} 108*6deacc1bSPeter Holm 109*6deacc1bSPeter Holmstatic void thread_start(void* (*fn)(void*), void* arg) 110*6deacc1bSPeter Holm{ 111*6deacc1bSPeter Holm pthread_t th; 112*6deacc1bSPeter Holm pthread_attr_t attr; 113*6deacc1bSPeter Holm pthread_attr_init(&attr); 114*6deacc1bSPeter Holm pthread_attr_setstacksize(&attr, 128 << 10); 115*6deacc1bSPeter Holm int i = 0; 116*6deacc1bSPeter Holm for (; i < 100; i++) { 117*6deacc1bSPeter Holm if (pthread_create(&th, &attr, fn, arg) == 0) { 118*6deacc1bSPeter Holm pthread_attr_destroy(&attr); 119*6deacc1bSPeter Holm return; 120*6deacc1bSPeter Holm } 121*6deacc1bSPeter Holm if (errno == EAGAIN) { 122*6deacc1bSPeter Holm usleep(50); 123*6deacc1bSPeter Holm continue; 124*6deacc1bSPeter Holm } 125*6deacc1bSPeter Holm break; 126*6deacc1bSPeter Holm } 127*6deacc1bSPeter Holm exit(1); 128*6deacc1bSPeter Holm} 129*6deacc1bSPeter Holm 130*6deacc1bSPeter Holmtypedef struct { 131*6deacc1bSPeter Holm pthread_mutex_t mu; 132*6deacc1bSPeter Holm pthread_cond_t cv; 133*6deacc1bSPeter Holm int state; 134*6deacc1bSPeter Holm} event_t; 135*6deacc1bSPeter Holm 136*6deacc1bSPeter Holmstatic void event_init(event_t* ev) 137*6deacc1bSPeter Holm{ 138*6deacc1bSPeter Holm if (pthread_mutex_init(&ev->mu, 0)) 139*6deacc1bSPeter Holm exit(1); 140*6deacc1bSPeter Holm if (pthread_cond_init(&ev->cv, 0)) 141*6deacc1bSPeter Holm exit(1); 142*6deacc1bSPeter Holm ev->state = 0; 143*6deacc1bSPeter Holm} 144*6deacc1bSPeter Holm 145*6deacc1bSPeter Holmstatic void event_reset(event_t* ev) 146*6deacc1bSPeter Holm{ 147*6deacc1bSPeter Holm ev->state = 0; 148*6deacc1bSPeter Holm} 149*6deacc1bSPeter Holm 150*6deacc1bSPeter Holmstatic void event_set(event_t* ev) 151*6deacc1bSPeter Holm{ 152*6deacc1bSPeter Holm pthread_mutex_lock(&ev->mu); 153*6deacc1bSPeter Holm if (ev->state) 154*6deacc1bSPeter Holm exit(1); 155*6deacc1bSPeter Holm ev->state = 1; 156*6deacc1bSPeter Holm pthread_mutex_unlock(&ev->mu); 157*6deacc1bSPeter Holm pthread_cond_broadcast(&ev->cv); 158*6deacc1bSPeter Holm} 159*6deacc1bSPeter Holm 160*6deacc1bSPeter Holmstatic void event_wait(event_t* ev) 161*6deacc1bSPeter Holm{ 162*6deacc1bSPeter Holm pthread_mutex_lock(&ev->mu); 163*6deacc1bSPeter Holm while (!ev->state) 164*6deacc1bSPeter Holm pthread_cond_wait(&ev->cv, &ev->mu); 165*6deacc1bSPeter Holm pthread_mutex_unlock(&ev->mu); 166*6deacc1bSPeter Holm} 167*6deacc1bSPeter Holm 168*6deacc1bSPeter Holmstatic int event_isset(event_t* ev) 169*6deacc1bSPeter Holm{ 170*6deacc1bSPeter Holm pthread_mutex_lock(&ev->mu); 171*6deacc1bSPeter Holm int res = ev->state; 172*6deacc1bSPeter Holm pthread_mutex_unlock(&ev->mu); 173*6deacc1bSPeter Holm return res; 174*6deacc1bSPeter Holm} 175*6deacc1bSPeter Holm 176*6deacc1bSPeter Holmstatic int event_timedwait(event_t* ev, uint64_t timeout) 177*6deacc1bSPeter Holm{ 178*6deacc1bSPeter Holm uint64_t start = current_time_ms(); 179*6deacc1bSPeter Holm uint64_t now = start; 180*6deacc1bSPeter Holm pthread_mutex_lock(&ev->mu); 181*6deacc1bSPeter Holm for (;;) { 182*6deacc1bSPeter Holm if (ev->state) 183*6deacc1bSPeter Holm break; 184*6deacc1bSPeter Holm uint64_t remain = timeout - (now - start); 185*6deacc1bSPeter Holm struct timespec ts; 186*6deacc1bSPeter Holm ts.tv_sec = remain / 1000; 187*6deacc1bSPeter Holm ts.tv_nsec = (remain % 1000) * 1000 * 1000; 188*6deacc1bSPeter Holm pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); 189*6deacc1bSPeter Holm now = current_time_ms(); 190*6deacc1bSPeter Holm if (now - start > timeout) 191*6deacc1bSPeter Holm break; 192*6deacc1bSPeter Holm } 193*6deacc1bSPeter Holm int res = ev->state; 194*6deacc1bSPeter Holm pthread_mutex_unlock(&ev->mu); 195*6deacc1bSPeter Holm return res; 196*6deacc1bSPeter Holm} 197*6deacc1bSPeter Holm 198*6deacc1bSPeter Holmstruct thread_t { 199*6deacc1bSPeter Holm int created, call; 200*6deacc1bSPeter Holm event_t ready, done; 201*6deacc1bSPeter Holm}; 202*6deacc1bSPeter Holm 203*6deacc1bSPeter Holmstatic struct thread_t threads[16]; 204*6deacc1bSPeter Holmstatic void execute_call(int call); 205*6deacc1bSPeter Holmstatic int running; 206*6deacc1bSPeter Holm 207*6deacc1bSPeter Holmstatic void* thr(void* arg) 208*6deacc1bSPeter Holm{ 209*6deacc1bSPeter Holm struct thread_t* th = (struct thread_t*)arg; 210*6deacc1bSPeter Holm for (;;) { 211*6deacc1bSPeter Holm event_wait(&th->ready); 212*6deacc1bSPeter Holm event_reset(&th->ready); 213*6deacc1bSPeter Holm execute_call(th->call); 214*6deacc1bSPeter Holm __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); 215*6deacc1bSPeter Holm event_set(&th->done); 216*6deacc1bSPeter Holm } 217*6deacc1bSPeter Holm return 0; 218*6deacc1bSPeter Holm} 219*6deacc1bSPeter Holm 220*6deacc1bSPeter Holmstatic void loop(void) 221*6deacc1bSPeter Holm{ 222*6deacc1bSPeter Holm int i, call, thread; 223*6deacc1bSPeter Holm int collide = 0; 224*6deacc1bSPeter Holmagain: 225*6deacc1bSPeter Holm for (call = 0; call < 3; call++) { 226*6deacc1bSPeter Holm for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); 227*6deacc1bSPeter Holm thread++) { 228*6deacc1bSPeter Holm struct thread_t* th = &threads[thread]; 229*6deacc1bSPeter Holm if (!th->created) { 230*6deacc1bSPeter Holm th->created = 1; 231*6deacc1bSPeter Holm event_init(&th->ready); 232*6deacc1bSPeter Holm event_init(&th->done); 233*6deacc1bSPeter Holm event_set(&th->done); 234*6deacc1bSPeter Holm thread_start(thr, th); 235*6deacc1bSPeter Holm } 236*6deacc1bSPeter Holm if (!event_isset(&th->done)) 237*6deacc1bSPeter Holm continue; 238*6deacc1bSPeter Holm event_reset(&th->done); 239*6deacc1bSPeter Holm th->call = call; 240*6deacc1bSPeter Holm __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); 241*6deacc1bSPeter Holm event_set(&th->ready); 242*6deacc1bSPeter Holm if (collide && (call % 2) == 0) 243*6deacc1bSPeter Holm break; 244*6deacc1bSPeter Holm event_timedwait(&th->done, 50); 245*6deacc1bSPeter Holm break; 246*6deacc1bSPeter Holm } 247*6deacc1bSPeter Holm } 248*6deacc1bSPeter Holm for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) 249*6deacc1bSPeter Holm sleep_ms(1); 250*6deacc1bSPeter Holm if (!collide) { 251*6deacc1bSPeter Holm collide = 1; 252*6deacc1bSPeter Holm goto again; 253*6deacc1bSPeter Holm } 254*6deacc1bSPeter Holm} 255*6deacc1bSPeter Holm 256*6deacc1bSPeter Holmuint64_t r[1] = {0xffffffffffffffff}; 257*6deacc1bSPeter Holm 258*6deacc1bSPeter Holmvoid execute_call(int call) 259*6deacc1bSPeter Holm{ 260*6deacc1bSPeter Holm intptr_t res = 0; 261*6deacc1bSPeter Holm switch (call) { 262*6deacc1bSPeter Holm case 0: 263*6deacc1bSPeter Holm NONFAILING(memcpy((void*)0x20000480, "./file0\000", 8)); 264*6deacc1bSPeter Holm res = syscall(SYS_open, 0x20000480ul, 0x80400000000206ul, 0ul); 265*6deacc1bSPeter Holm if (res != -1) 266*6deacc1bSPeter Holm r[0] = res; 267*6deacc1bSPeter Holm break; 268*6deacc1bSPeter Holm case 1: 269*6deacc1bSPeter Holm syscall(SYS_mmap, 0x20000000ul, 0x200000ul, 1ul, 0x12ul, r[0], 0ul); 270*6deacc1bSPeter Holm break; 271*6deacc1bSPeter Holm case 2: 272*6deacc1bSPeter Holm syscall(SYS_ftruncate, r[0], 5ul); 273*6deacc1bSPeter Holm break; 274*6deacc1bSPeter Holm } 275*6deacc1bSPeter Holm} 276*6deacc1bSPeter Holmint main(void) 277*6deacc1bSPeter Holm{ 278*6deacc1bSPeter Holm syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); 279*6deacc1bSPeter Holm install_segv_handler(); 280*6deacc1bSPeter Holm loop(); 281*6deacc1bSPeter Holm return 0; 282*6deacc1bSPeter Holm} 283*6deacc1bSPeter HolmEOF 284*6deacc1bSPeter Holmmycc -o /tmp/syzkaller45 -Wall -Wextra -O0 /tmp/syzkaller45.c -lpthread || exit 1 285*6deacc1bSPeter Holm 286*6deacc1bSPeter Holm(cd /tmp; ./syzkaller45) 287*6deacc1bSPeter Holm 288*6deacc1bSPeter Holmrm -rf /tmp/syzkaller45 /tmp/syzkaller45.c /tmp/syzkaller.* /tmp/file0 289*6deacc1bSPeter Holmexit 0 290