--- a/sys/kern/subr_eventhandler.c +++ b/sys/kern/subr_eventhandler.c @@ -121,6 +121,28 @@ /* XXX insert diagnostic check here? */ if (ep != NULL) { + /* + * DF-2973: never trust the tag. A tag from another list (or a + * stale / double-deregistered tag) makes TAILQ_REMOVE unlink and + * kfree() an entry that is not on , corrupting both lists' + * tail sentinels (dangling tqh_last -> write-after-free on the + * next registration). Verify membership first. + */ + struct eventhandler_entry *it; + int found = 0; + + TAILQ_FOREACH(it, &list->el_entries, ee_link) { + if (it == ep) { + found = 1; + break; + } + } + if (!found) { + kprintf("eventhandler_deregister: tag %p not in list \"%s\"" + " -- deregistration ignored\n", ep, list->el_name); + lwkt_reltoken(&evlist_token); + return; + } /* remove just this entry */ TAILQ_REMOVE(&list->el_entries, ep, ee_link); kfree(ep, M_EVENTHANDLER);