DF-3501 / dumpif.c
#include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_arp.h> #include <net/if_types.h> #include <stdint.h> /* * debug.dumpif: dump sizeof(struct ifnet), arpcom offsets, and the 32 * bytes immediately past the end of a given interface's ifnet allocation * (default lo0). Used to demonstrate the ng_fec_addport arpcom * type-confusion OOB read/write. */ static int dumpif_sysctl(SYSCTL_HANDLER_ARGS) { char ifname[IFNAMSIZ]; struct ifnet *ifp; caddr_t end; int i, error; uint64_t v; strlcpy(ifname, "lo0", sizeof(ifname)); error = sysctl_handle_string(oidp, ifname, sizeof(ifname), req); if (error != 0 || req->newptr == NULL) return (error); ifnet_lock(); ifp = ifunit(ifname); if (ifp == NULL) { ifnet_unlock(); kprintf("DUMPIF: %s: no such interface\n", ifname); return (ENOENT); } kprintf("DUMPIF: %s ifp=%p sizeof(struct ifnet)=%zu " "sizeof(struct arpcom)=%zu off(ac_enaddr)=%zu off(ac_netgraph)=%zu\n", ifname, ifp, sizeof(struct ifnet), sizeof(struct arpcom), offsetof(struct arpcom, ac_enaddr), offsetof(struct arpcom, ac_netgraph)); end = (caddr_t)ifp + sizeof(struct ifnet); for (i = 0; i < 32; i += 8) { v = *(volatile uint64_t *)(end + i); kprintf("DUMPIF: %s tail+%3d (ifnet_end%+d): %016jx\n", ifname, i, i, (uintmax_t)v); } ifnet_unlock(); return (0); } SYSCTL_PROC(_debug, OID_AUTO, dumpif, CTLTYPE_STRING | CTLFLAG_RW, 0, 0, dumpif_sysctl, "A", "dump bytes past ifnet end"); static int dumpif_load(struct module *m, int what, void *arg) { switch (what) { case MOD_LOAD: kprintf("dumpif: loaded; use 'sysctl -n debug.dumpif=<ifname>'\n"); return (0); default: return (0); } } static moduledata_t dumpif_mod = { "dumpif", dumpif_load, NULL }; DECLARE_MODULE(dumpif, dumpif_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); |