Previously, to destroy an ithread we would set IT_DEAD in its flags, and
then wake it up if it wasn't already running. After doing this,
intr_event_destroy() would free the intr_event structure. However, it
did not wait for the ithread to exit, so it was possible for the ithread
to access the intr_event after it was freed.
This use-after-free happens readily when running the pf tests in
parallel, since they frequently create and destroy VNET jails, and pf
registers several VNET-local swi handlers.
Fix the race by modifying ithread_destroy() to wait until the ithread
has signaled that it is about to exit by setting ie->ie_thread = NULL.
Existing callers of intr_event_destroy() are allowed to sleep.
Reported by: KASAN
Reviewed by: kib, jhb
MFC after: 3 weeks
Differential Revision: https://reviews.freebsd.org/D45492