DF-0001 / run_fix_validate.sh
#!/bin/sh # DF-0001 โ fix-validation: same choreography as run.sh but WITHOUT the # "INVARIANTS KASSERT strings must be present" precondition (since the # fix *removes* the KASSERTs and therefore the panic strings from the # kernel binary). On the patched kernel we expect: # * ftruncate(2) returns ESTALE (the GETATTR error), NOT panic # * guest stays up after the trigger # * no panic signature in dfbsd-qemu/boot.log # Exits 0 if no panic was observed and the guest is still up. set -eu cd "$(dirname "$0")" HERE="$(pwd)" ROOT="$(cd "$HERE/../../.." && pwd)" VM="$ROOT/dfbsd-qemu/vm.sh" CFG="$ROOT/dfbsd-qemu/config" echo "==> [1/5] ensure vfs.quota_enabled=1 (loader tunable, reboot if needed)" $VM run_root 'grep -q quota_enabled /boot/loader.conf || echo "vfs.quota_enabled=\"1\"" >> /boot/loader.conf; sync' if [ "$($VM run_root 'sysctl -n vfs.quota_enabled')" != "1" ]; then echo " quota not yet enabled -> non-reverting reboot" ( $VM down >/dev/null 2>&1 ) || { P=$(cat "$ROOT/dfbsd-qemu/vm.pid"); kill -9 "$P" 2>/dev/null; } sleep 3 $VM up 90 fi $VM run_root 'test "$(sysctl -n vfs.quota_enabled)" = "1" || { echo "quota not enabled"; exit 4; }' echo "==> [2/5] build trigger + stand up loopback NFS server + soft mount" $VM run_user 'mkdir -p poc/DF-0001' scp -F "$CFG" -q "$HERE/estale_trig.c" dfbsd-maxx:poc/DF-0001/ $VM run_user 'cd poc/DF-0001 && cc -O0 -g -o estale_trig estale_trig.c' $VM run_root ' mkdir -p /export; chmod 777 /export printf "/export -maproot=root -network 127.0.0.0 -mask 255.0.0.0\n" > /etc/exports pkill -x nfsd 2>/dev/null; pkill -x mountd 2>/dev/null; pkill -x rpcbind 2>/dev/null sleep 1 rpcbind 2>/dev/null; sleep 1 mountd 2>/dev/null; sleep 1 nfsd -t -u -n 4 2>/dev/null; sleep 2 umount -f /mnt 2>/dev/null; mkdir -p /mnt mount_nfs -U -s -x 1 -t 1 \ -o acregmin=0,acregmax=0,acdirmin=0,acdirmax=0 127.0.0.1:/export /mnt dd if=/dev/zero of=/export/estale_target bs=4096 count=1 2>/dev/null chown maxx:maxx /export/estale_target; chmod 644 /export/estale_target ls -l /mnt/estale_target ' echo "==> [3/5] launch estale_trig as maxx (opens fd, holds fixed filehandle)" $VM run_user 'cd poc/DF-0001 && nohup ./estale_trig /mnt/estale_target > /tmp/df0001.out 2>&1 & echo "pid $!"' sleep 3 $VM run_user 'cat /tmp/df0001.out' echo "==> [4/5] invalidate the fd filehandle SERVER-SIDE (delete + recreate -> stale FH)" $VM run_root 'rm -f /export/estale_target; sync; touch /export/estale_target; chown maxx:maxx /export/estale_target; chmod 644 /export/estale_target; echo handle_invalidated' echo "==> [5/5] wait + observe (FIXED = no panic, guest up, ftruncate returns error)" # give the trigger time to wake and call ftruncate, then check guest liveness sleep 20 st=$($VM status 2>/dev/null || echo down) echo " guest status after trigger: $st" echo "--- maxx trigger stdout/stderr ---" $VM run_user 'cat /tmp/df0001.out 2>/dev/null || echo "(no output file)"' || true echo "--- check boot.log for panic ---" if grep -qE 'panic: kern_(f)?truncate' "$ROOT/dfbsd-qemu/boot.log"; then echo "!!! PANIC detected in boot.log โ fix FAILED" awk '/panic: kern_(f)?truncate/{p=1} p{print} /^db> /{p=0; exit}' "$ROOT/dfbsd-qemu/boot.log" exit 2 else echo "no panic: kern_(f)?truncate in boot.log โ fix HELD" fi if [ "$st" = "up" ]; then echo "==> RESULT: FIXED (guest up, no panic)" exit 0 else echo "==> RESULT: guest down (might be a different bug; inspect boot.log)" exit 3 fi |