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