DF-5744 / gmuxobs.c
/* * gmuxobs.c -- kernel observer for DF-5744. * * Watches COM1 scratch register (I/O port 0x3ff). The 16550 SCR byte is * fully readable/writable and has ZERO functional effect, which makes it a * perfect side-effect-free canary for an out-of-bounds port write. * * Rig geometry (SSDT): one gmux device with a 4-byte _CRS at base 0x333. * apple_gmux attach then does (production code, apple-gmux.c): * gmux_read8 VERSION_{MAJOR,MINOR,RELEASE} -> bus_read_1(res, 0x04..0x06) * (3 OOB reads past 4-byte res) * -> all 0xff -> gmux_is_indexed() (apple-gmux.c:346-362): * bus_write_1(res, 0xcc, 0xaa) == outb(0x333+0xcc=0x3ff, 0xaa) <-- CANARY * bus_write_1(res, 0xcd, 0x55) == outb(0x400, 0x55) * bus_write_1(res, 0xce, 0x00) == outb(0x401, 0x00) * -> val = 0xaa | (inb(0x400) << 8) != 0x55aa -> "not indexed" -> ENODEV * * If SCR(0x3ff) reads 0xaa after `kldload apple_gmux`, the production * driver demonstrably wrote 0xcc bytes past its 4-byte rman allocation. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <machine/cpufunc.h> static int gmuxobs_scr(SYSCTL_HANDLER_ARGS); SYSCTL_PROC(_hw, OID_AUTO, gmuxobs_scr, CTLTYPE_INT | CTLFLAG_RD, NULL, 0, gmuxobs_scr, "I", "current COM1 SCR (port 0x3ff) value"); static int gmuxobs_scr(SYSCTL_HANDLER_ARGS) { int v = inb(0x3ff); return (sysctl_handle_int(oidp, &v, 0, req)); } static int gmuxobs_handler(struct module *m, int what, void *arg) { switch (what) { case MOD_LOAD: kprintf("gmuxobs: COM1 SCR (0x3ff) at module load = 0x%02x\n", inb(0x3ff)); break; case MOD_UNLOAD: kprintf("gmuxobs: COM1 SCR (0x3ff) at module unload = 0x%02x\n", inb(0x3ff)); break; } return (0); } static moduledata_t gmuxobs_mod = { "gmuxobs", gmuxobs_handler, NULL }; DECLARE_MODULE(gmuxobs, gmuxobs_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); |