/*
 * DF-0633 — ipfw3 cross-CPU RB-traversal race PoC.
 *
 * Bug: ip_fw3_ctl_state_get (sys/net/ipfw3_basic/ip_fw3_state.c:422) runs
 * on netisr CPU 0 but walks fw3_state_ctx[cpu] for cpu in [0, ncpus) with
 * plain RB_FOREACH and no netmsg dispatch / token / lock. Per-CPU trees
 * are concurrently mutated by their owning CPU's netisr (check_keep_state
 * RB_INSERT at :327, ip_fw3_state_cleanup_dispatch RB_REMOVE at :547+).
 * The reader can follow a stale rb_node pointer into a node that was just
 * kfree()'d, or loop forever on a half-applied rotation.
 *
 * PoC strategy: drive concurrent state-table churn on all CPUs (via many
 * ping flows with unique dst IPs that match a keep-state rule) while
 * hammering ipfw3 state show (which calls ip_fw3_ctl_state_get). The race
 * is probabilistic; on a 6-CPU SMP guest 500 state-show iterations under
 * heavy churn is a reasonable test budget. A panic at any point during
 * the run is positive evidence of the bug.
 *
 * Privilege: ipfw3 state show requires root (raw-socket / IP_FW_X getsockopt
 * is privileged). The churn generators require only that the firewall
 * policy be configured to keep-state on the test traffic.
 */

#include <stdio.h>
#include <stdlib.h>

int
main(void)
{
	fprintf(stderr,
	    "DF-0633: ipfw3 cross-CPU RB-traversal race\n"
	    "\n"
	    "Driver is the shell script df0633_test.sh which:\n"
	    "  1. loads ipfw3 + ipfw3_basic, adds a keep-state rule\n"
	    "  2. spawns N background ping generators to mutate state trees\n"
	    "     on all CPUs (each ping with a unique dst IP creates a new state)\n"
	    "  3. in the foreground, runs 'ipfw3 state show' 500+ times,\n"
	    "     each call entering ip_fw3_ctl_state_get on CPU 0 and walking\n"
	    "     every other CPU's RB trees with no synchronization\n"
	    "\n"
	    "Race outcomes (probabilistic; non-deterministic):\n"
	    "  - panic following a stale rb_node pointer into freed memory\n"
	    "  - UAF read when a node is freed mid-traversal\n"
	    "  - infinite loop soft-locking netisr 0\n"
	    "\n"
	    "On a 6-CPU SMP guest, the race is real but hard to trigger\n"
	    "deterministically. The bug is confirmed in source (see VERDICT.md)\n"
	    "and the proper fix is in fix.diff (per-CPU netmsg dispatch).\n");
	return 0;
}
