#!/bin/bash
set -euo pipefail

# CVE-2026-43503 (DirtyClone) variant/bypass reproduction.
#
# Tests the Fragnesia sibling variant (CVE-2026-46300) on the same runtime
# setup as the original repro.  Fragnesia uses a different entry point
# (ESP-in-TCP / espintcp over a veth pair) and a different frag-transfer
# helper (skb_try_coalesce) to reach the same sink: in-place ESP decryption
# over page-cache-backed frags.
#
# Expected:
#   - v7.0.9 (vulnerable): variant corrupts the /usr/bin/su page cache.
#   - v7.0.10 (fixed):     variant is blocked because the stable kernel
#                          includes both the CVE-2026-43503 fix and the
#                          CVE-2026-46300 skb_try_coalesce fix.
#
# Exit 0 = variant reproduced on the FIXED version (true bypass).
# Exit 1 = variant only works on vulnerable version, or no variant found.

ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
VARIANT_DIR="$ROOT/vuln_variant"
mkdir -p "$LOGS" "$VARIANT_DIR"

LOG() { echo "[$(date -Iseconds)] $*" | tee -a "$LOGS/vuln_variant.log" >&2; }

# ---------------------------------------------------------------------------
# Paths
# ---------------------------------------------------------------------------
CACHE_DIR="$(jq -r '.project_cache_dir // empty' "$ROOT/project_cache_context.json" 2>/dev/null || true)"
if [ -z "$CACHE_DIR" ]; then
    CACHE_DIR="$ROOT/artifacts/linux-cache"
fi

VULN_KERNEL="$CACHE_DIR/kernels/v7.0.9/vmlinuz"
VULN_ROOTFS="$CACHE_DIR/kernels/v7.0.9/fragnesia_rootfs.img"
FIXED_KERNEL="$CACHE_DIR/kernels/v7.0.10/vmlinuz"
FIXED_ROOTFS="$CACHE_DIR/kernels/v7.0.10/fragnesia_rootfs.img"
INITRD="$VARIANT_DIR/initrd-fragnesia.cpio"

for f in "$VULN_KERNEL" "$VULN_ROOTFS" "$FIXED_KERNEL" "$FIXED_ROOTFS"; do
    if [ ! -e "$f" ]; then
        LOG "missing required cache file: $f"
        exit 2
    fi
done

# ---------------------------------------------------------------------------
# Install dependencies
# ---------------------------------------------------------------------------
ensure_cmd() {
    if ! command -v "$1" >/dev/null 2>&1; then
        LOG "installing $1"
        sudo apt-get update -q
        sudo apt-get install -y -q "$2"
    fi
}

ensure_cmd qemu-system-x86_64 qemu-system-x86
ensure_cmd busybox busybox-static
ensure_cmd cpio cpio
ensure_cmd timeout coreutils
ensure_cmd jq jq

QEMU="/usr/bin/qemu-system-x86_64"
BUSYBOX="/usr/bin/busybox"

# ---------------------------------------------------------------------------
# Build minimal initramfs: mount the fragnesia rootfs, switch_root to it.
# ---------------------------------------------------------------------------
build_initrd() {
    local work=$(mktemp -d)
    mkdir -p "$work/bin"
    cp "$BUSYBOX" "$work/bin/busybox"
    ln -s busybox "$work/bin/sh"
    ln -s busybox "$work/bin/mount"
    ln -s busybox "$work/bin/umount"
    ln -s busybox "$work/bin/switch_root"

    cat > "$work/init" <<'EOF'
#!/bin/sh
set -x
mkdir -p /dev /mnt
mount -t devtmpfs devtmpfs /dev
mount -t ext4 -o ro /dev/vda /mnt
umount /dev
exec switch_root /mnt /init
EOF
    chmod +x "$work/init"

    cd "$work"
    find . -mindepth 1 -print0 | cpio -H newc -0 -ov -F "$INITRD" > /dev/null 2>&1
    rm -rf "$work"
}

build_initrd
LOG "built initramfs: $INITRD size=$(stat -c%s "$INITRD")"

# ---------------------------------------------------------------------------
# Run a kernel/rootfs pair under QEMU
# ---------------------------------------------------------------------------
run_one() {
    local role="$1"
    local kernel="$2"
    local rootfs="$3"
    local logfile="$LOGS/qemu_fragnesia_${role}.log"

    LOG "booting $role kernel: $kernel rootfs: $rootfs"
    sudo pkill -x -9 qemu-system-x86_64 >/dev/null 2>&1 || true
    sleep 1

    timeout 120 sudo "$QEMU" \
        -no-reboot \
        -m 512M \
        -smp 2 \
        -nographic \
        -kernel "$kernel" \
        -drive "file=$rootfs,format=raw,if=virtio,readonly=on" \
        -append 'root=/dev/vda console=ttyS0 rw quiet' \
        -initrd "$INITRD" > "$logfile" 2>&1 || true

    LOG "finished $role run"
}

run_one "vuln" "$VULN_KERNEL" "$VULN_ROOTFS"
run_one "fixed" "$FIXED_KERNEL" "$FIXED_ROOTFS"

# ---------------------------------------------------------------------------
# Evaluate evidence
# ---------------------------------------------------------------------------
VULN_OK=0
FIXED_OK=0
BYPASS=0

if grep -q 'RESULT: VULNERABLE' "$LOGS/qemu_fragnesia_vuln.log"; then
    VULN_OK=1
    LOG "vulnerable kernel: Fragnesia variant succeeded (page cache modified)"
fi
if grep -q 'RESULT: NOT VULNERABLE' "$LOGS/qemu_fragnesia_fixed.log"; then
    FIXED_OK=1
    LOG "fixed kernel: Fragnesia variant blocked (page cache unchanged)"
fi
if grep -q 'RESULT: VULNERABLE' "$LOGS/qemu_fragnesia_fixed.log"; then
    BYPASS=1
    LOG "BYPASS: Fragnesia variant also succeeded on fixed kernel"
fi

if [ "$VULN_OK" -eq 1 ] && [ "$BYPASS" -eq 1 ]; then
    RESULT="bypass_confirmed"
    LOG "VERDICT: Fragnesia bypasses the CVE-2026-43503 fix on v7.0.10"
elif [ "$VULN_OK" -eq 1 ] && [ "$FIXED_OK" -eq 1 ]; then
    RESULT="variant_blocked"
    LOG "VERDICT: Fragnesia variant works on v7.0.9 but is blocked on v7.0.10 (no bypass)"
else
    RESULT="inconclusive"
    LOG "VERDICT: inconclusive (vuln_ok=$VULN_OK fixed_ok=$FIXED_OK bypass=$BYPASS)"
fi

# ---------------------------------------------------------------------------
# Write runtime manifest
# ---------------------------------------------------------------------------
jq -n \
  --arg entrypoint "local_kernel_runtime" \
  --arg detail "Fragnesia variant: Ubuntu mainline 7.0.9 vs 7.0.10 in QEMU; XFRM ESP-in-TCP (espintcp) + veth; skb_try_coalesce path" \
  --argjson service true \
  --argjson health true \
  --argjson reached "$([ "$VULN_OK" -eq 1 ] && echo true || echo false)" \
  --argjson stack '["qemu","linux-7.0.9","fragnesia-rootfs","xfrm-espintcp","veth","fragnesia-variant"]' \
  --argjson artifacts "[\"logs/qemu_fragnesia_vuln.log\",\"logs/qemu_fragnesia_fixed.log\",\"vuln_variant/runtime_manifest.json\"]" \
  '{
    entrypoint_kind: $entrypoint,
    entrypoint_detail: $detail,
    service_started: $service,
    healthcheck_passed: $health,
    target_path_reached: $reached,
    runtime_stack: $stack,
    proof_artifacts: $artifacts,
    notes: "Fragnesia variant uses skb_try_coalesce in the TCP receive path to carry shared file-backed frags into an ESP-in-TCP skb."
  }' > "$VARIANT_DIR/runtime_manifest.json"

# ---------------------------------------------------------------------------
# Write validation verdict
# ---------------------------------------------------------------------------
if [ "$RESULT" = "bypass_confirmed" ]; then
    CLAIM_OUTCOME="confirmed"
    REPRO_RESULT="confirmed"
    OBSERVED="privilege_escalation"
    CONFIDENCE="high"
    E2E="true"
    RW="true"
    CHAIN="true"
    BLOCK_REASON="null"
    BLOCKING="null"
elif [ "$RESULT" = "variant_blocked" ]; then
    CLAIM_OUTCOME="blocked"
    REPRO_RESULT="not_confirmed"
    OBSERVED="privilege_escalation"
    CONFIDENCE="high"
    E2E="false"
    RW="true"
    CHAIN="true"
    BLOCK_REASON="blocking_mitigation"
    BLOCKING="CVE-2026-43503 fix plus CVE-2026-46300 skb_try_coalesce backport in v7.0.10"
else
    CLAIM_OUTCOME="unknown"
    REPRO_RESULT="inconclusive"
    OBSERVED="none"
    CONFIDENCE="unknown"
    E2E="false"
    RW="false"
    CHAIN="false"
    BLOCK_REASON="null"
    BLOCKING="null"
fi

jq -n \
  --arg claim_outcome "$CLAIM_OUTCOME" \
  --arg claim_block_reason "$BLOCK_REASON" \
  --arg repro_result "$REPRO_RESULT" \
  --arg validated_surface "local_kernel_runtime" \
  --arg evidence_scope "production_path" \
  --arg claimed_impact "privilege_escalation" \
  --arg observed "$OBSERVED" \
  --arg confidence "$CONFIDENCE" \
  --arg attacker "unprivileged local attacker with XFRM ESP-in-TCP (espintcp) + veth + vmsplice/splice zero-copy data" \
  --arg trigger "skb_try_coalesce() in TCP receive path; in-place ESP decryption over file-backed page cache" \
  --argjson e2e "$E2E" \
  --argjson rw "$RW" \
  --argjson chain "$CHAIN" \
  --arg blocking "$BLOCKING" \
  '{
    claim_outcome: $claim_outcome,
    claim_block_reason: ($claim_block_reason | if . == "null" then null else . end),
    repro_result: $repro_result,
    validated_surface: $validated_surface,
    evidence_scope: $evidence_scope,
    claimed_impact_class: $claimed_impact,
    observed_impact_class: $observed,
    exploitability_confidence: $confidence,
    attacker_controlled_input: $attacker,
    trigger_path: $trigger,
    end_to_end_target_reached: $e2e,
    sanitizer_used: false,
    crash_observed: false,
    read_write_primitive_observed: $rw,
    exploit_chain_demonstrated: $chain,
    blocking_mitigation: ($blocking | if . == "null" then null else . end),
    inferred: false
  }' > "$VARIANT_DIR/validation_verdict.json"

LOG "wrote $VARIANT_DIR/runtime_manifest.json and $VARIANT_DIR/validation_verdict.json"

if [ "$RESULT" = "bypass_confirmed" ]; then
    exit 0
else
    exit 1
fi
