#!/bin/sh
# DF-0736 fix-validation script: applies the fix to ng_ipfw.c (locally, in the
# /usr/src tree), rebuilds the standalone ng_ipfw.ko + netgraph.ko + ng_socket.ko
# (so ABI matches), loads everything, and then runs the attack module.  On the
# fixed kernel the attack module returns cleanly instead of panicking.
set -e

echo "=== A. Apply fix.diff to /usr/src/sys/netgraph7/ng_ipfw.c ==="
cd /usr/src
patch -p1 --forward < /root/fix.diff || true
echo "--- patched line ---"
sed -n '248,256p' sys/netgraph7/ng_ipfw.c

echo ""
echo "=== B. Rebuild netgraph.ko + ng_socket.ko from source (ABI match) ==="
cd /usr/src/sys/netgraph7/netgraph && make clean && make >/dev/null
cd /usr/src/sys/netgraph7/socket  && make clean && make >/dev/null
mount -uw /boot 2>/dev/null || mount -uw /
cp /usr/src/sys/netgraph7/netgraph/netgraph.ko /boot/kernel/netgraph.ko
cp /usr/src/sys/netgraph7/socket/ng_socket.ko  /boot/kernel/ng_socket.ko
mount -ro / 2>/dev/null
echo "fresh .ko deployed"

echo ""
echo "=== C. Rebuild patched ng_ipfw.ko (with include symlink, stripped ipfw dep, defined ng_ipfw_input_p) ==="
mkdir -p /usr/src/sys/netgraph7/ipfw/netinet
cp /usr/src/sys/netgraph7/ng_ipfw.c /usr/src/sys/netgraph7/ipfw/
cp /usr/src/sys/netgraph7/ng_ipfw.h /usr/src/sys/netgraph7/ipfw/
ln -sf /usr/src/sys/net/ipfw/ip_fw.h /usr/src/sys/netgraph7/ipfw/netinet/ip_fw.h
# Strip MODULE_DEPEND on ipfw (broken dep) and add the missing ng_ipfw_input_p definition
sed -i "" -e "/MODULE_DEPEND.*ng_ipfw.*ipfw/d" /usr/src/sys/netgraph7/ipfw/ng_ipfw.c
awk '/^static int[[:space:]]+ng_ipfw_mod_event/ { print "ng_ipfw_input_t *ng_ipfw_input_p;"; print ""; } { print }' \
    /usr/src/sys/netgraph7/ipfw/ng_ipfw.c > /usr/src/sys/netgraph7/ipfw/ng_ipfw.c.new
mv /usr/src/sys/netgraph7/ipfw/ng_ipfw.c.new /usr/src/sys/netgraph7/ipfw/ng_ipfw.c
cat > /usr/src/sys/netgraph7/ipfw/Makefile <<EOF
KMOD=   ng_ipfw
SRCS=   ng_ipfw.c
WARNS=  0
KCFLAGS+= -I/usr/src/sys/netgraph7
.include <bsd.kmod.mk>
EOF
cd /usr/src/sys/netgraph7/ipfw && make clean && make

echo ""
echo "=== D. Verify the panic() call is gone from the patched ng_ipfw.ko ==="
nm /usr/src/sys/netgraph7/ipfw/ng_ipfw.ko 2>&1 | head
objdump -d /usr/src/sys/netgraph7/ipfw/ng_ipfw.ko 2>/dev/null | grep -A2 -B2 -iE "panic|vpanic" || echo "(no panic reference found in disasm)"

echo ""
echo "=== E. Load netgraph + ng_socket + patched ng_ipfw ==="
kldload netgraph
kldload ng_socket
kldload /usr/src/sys/netgraph7/ipfw/ng_ipfw.ko
kldstat | tail

echo ""
echo "=== F. Load the attack module; on the FIXED kernel it must NOT panic ==="
kldload /root/df736attack.ko
echo "POST-LOAD EXIT=$?"
kldstat | tail
dmesg | tail -10
echo "=== VALIDATION COMPLETE ==="
