DF-3465 / wireshim.c
/* * DF-3465 PoC wiring shim. * * ip_fw3_log.c's ip_fw3_log_modevent(MOD_LOAD) attaches the "ipfw" cloner * and registers ip_fw3_log_clone_destroy as a handler for the GLOBAL * ifnet_detach_event. In the stock tree ipfw3_basic's module handler * (ip_fw3_basic.c:657-658) never calls it, so the whole subsystem is * dormant (ip_fw3_log_ptr is likewise never assigned). This shim performs * exactly the one-line wiring the module is missing, so the dormant code * becomes live the way upstream intends. After that, destroying or * renaming ANY interface whose if_dunit collides with a live ipfwN clone * unit (0..9) triggers the type-confused destroy -> double if_detach + * double if_free of the wrong ifnet. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/eventhandler.h> #include <net/if_var.h> #include <net/if_clone.h> extern void ip_fw3_log_modevent(int type); static void wireshim_detach_event(void *ctx, struct ifnet *ifp) { kprintf("wireshim: ifnet_detach_event: ifp=%s dname=%s dunit=%d " "(ctx=%p)\n", ifp->if_xname, ifp->if_dname ? ifp->if_dname : "(null)", ifp->if_dunit, ctx); } static eventhandler_tag wireshim_cookie; static int wireshim_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: /* * Layout facts needed to predict what the (mis-registered) * ipfw3 handler reads when EVENTHANDLER_INVOKE calls * ip_fw3_log_clone_destroy(&ipfw3_log_cloner, ifp). */ kprintf("wireshim: offsetof(struct ifnet, if_dunit) = %zu\n", offsetof(struct ifnet, if_dunit)); kprintf("wireshim: sizeof(struct if_clone) = %zu " "offsetof(ifc_name)=%zu ifc_minifs=%zu ifc_maxunit=%zu\n", sizeof(struct if_clone), offsetof(struct if_clone, ifc_name), offsetof(struct if_clone, ifc_minifs), offsetof(struct if_clone, ifc_maxunit)); ip_fw3_log_modevent(MOD_LOAD); wireshim_cookie = EVENTHANDLER_REGISTER(ifnet_detach_event, wireshim_detach_event, NULL, EVENTHANDLER_PRI_ANY); kprintf("wireshim: ipfw3 log subsystem wired " "(cloner attached + ifnet_detach_event handler)\n"); break; case MOD_UNLOAD: EVENTHANDLER_DEREGISTER(ifnet_detach_event, wireshim_cookie); ip_fw3_log_modevent(MOD_UNLOAD); break; default: break; } return 0; } static moduledata_t wireshim_mod = { "wireshim", wireshim_modevent, NULL }; DECLARE_MODULE(wireshim, wireshim_mod, SI_SUB_PROTO_END, SI_ORDER_ANY); MODULE_DEPEND(wireshim, ipfw3_basic, 1, 1, 1); MODULE_VERSION(wireshim, 1); |