#!/bin/sh
# DF-3527 trigger: leak M_NETGRAPH kernel heap via NGM_IFACE_POINT2POINT
# early-return in ng_iface_rcvmsg (ng_iface.c:666).
#
# PRECONDITIONS (all set up by run.sh before this runs):
#   - patched ng_iface module (DF-3485 + DF-3486 fixes) loaded so that an
#     ng_iface node can actually be created and brought UP on this guest
#   - ng0 created and IFF_UP set (ifconfig ng0 up)
# Must run as root.
set -e

echo "=== env ==="
uname -a
kldstat | grep -E 'ng_iface|ng_socket' || true
ifconfig ng0 || true

echo "=== M_NETGRAPH baseline ==="
vmstat -m | grep -i netgraph || true
BASE=$(vmstat -m | awk '$1 ~ /^[Nn]et[Gg]raph$/ {print $2, $3}')
echo "BASE_NETGRAPH_InUse_MemUse=$BASE"

echo "=== control run: 512 x GET_IFNAME (must be leak-free) ==="
/tmp/df3527_leak ng0 512 1024 1 || echo "(control rc=$?)"

MID=$(vmstat -m | awk '$1 ~ /^[Nn]et[Gg]raph$/ {print $2, $3}')
echo "AFTER_CONTROL_InUse_MemUse=$MID (was $BASE)"

echo "=== leak run: 2048 x POINT2POINT arglen=16384 on UP ng0 ==="
/tmp/df3527_leak ng0 2048 16384 2 || echo "(leak rc=$?)"

sleep 1
echo "=== M_NETGRAPH after ==="
vmstat -m | grep -i netgraph || true
AFTER=$(vmstat -m | awk '$1 ~ /^[Nn]et[Gg]raph$/ {print $2, $3}')
echo "AFTER_LEAK_InUse_MemUse=$AFTER (control: $MID)"
echo "EXPECTED_LEAK_BYTES=$((2048 * (52 + 16384 + 1)))"

echo "[+] netgraph allocator line above must show ~2K more InUse and ~34MB+ more MemUse than the control run"
