DF-0207 / df0207_harness.c
/* * DF-0207 harness (kernel module) - directly exercises the bug. * * clist_alloc_cblocks() (sys/kern/tty_subr.c:48) leaks the old c_data * buffer on every resize. This module allocates a private clist and * resizes it repeatedly, so each clist_alloc_cblocks() call with a new * ccmax orphans the previous kmalloc()'d buffer. We measure the leak * with `vmstat -m | grep ttys` (M_TTYS MemUse / Requests) before and * after kldload. * * Build (in /root/df0207_kld): make * Load (root): kldload ./df0207_harness.ko */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/module.h> #include <sys/malloc.h> #include <sys/tty.h> static int df0207_modevent(module_t mod, int type, void *data) { struct clist cl; int i; switch (type) { case MOD_LOAD: bzero(&cl, sizeof(cl)); /* initial allocation: ccmax 0 -> 1024 */ clist_alloc_cblocks(&cl, 1024); /* every subsequent resize leaks the previous buffer */ for (i = 0; i < 3000; i++) { clist_alloc_cblocks(&cl, 4096); /* leaks 1024/prev */ clist_alloc_cblocks(&cl, 1024); /* leaks 4096 */ } /* frees only the LAST live buffer (1024); the other ~3000 * are permanently orphaned -> M_TTYS leak. */ clist_free_cblocks(&cl); kprintf("DF0207 harness: 3000 leak iterations done; " "~3000 c_data buffers orphaned in M_TTYS\n"); return (0); case MOD_UNLOAD: return (0); default: return (EOPNOTSUPP); } } static moduledata_t df0207_mod = { "df0207", df0207_modevent, NULL }; DECLARE_MODULE(df0207, df0207_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_VERSION(df0207, 1); |