DF-5779 / seqputs_rig.c
/* * DF-5779 differential rig โ proves the seq_puts() shim contract divergence * on the live DragonFly kernel. * * The shim (sys/dev/drm/include/linux/seq_file.h:44) is: * #define seq_puts(m, str) ksnprintf((m)->buf, (m)->size, str) * i.e. the DATA string `str` occupies ksnprintf's FORMAT parameter. * * Rig A: controlled %n -> is the write-through-pointer conversion live in * the kernel printf core (sys/kern/subr_prf.c:688-701)? * Rig B: exact macro expansion with a dynamic data string (the thing a * ported Linux caller would pass) containing %d โ the kernel * interprets it against varargs that were NEVER passed. * * Build: see build.sh. Load with kldload(8); evidence lands in dmesg. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/module.h> /* exact replica of sys/dev/drm/include/linux/seq_file.h:37-44 */ struct seq_file { char *buf; size_t size; }; #define seq_puts(m, str) ksnprintf((m)->buf, (m)->size, str) static void rig_run(void) { struct seq_file m; char backing[256]; char snap[256]; int written = -1; const char *data = "conn=DP-1 link=%d ok=100%%\n"; m.buf = backing; m.size = sizeof(backing); /* --- Rig A: is %n live? (controlled, safe) --- */ backing[0] = '\0'; ksnprintf(m.buf, m.size, "AA%nBB\n", &written); kprintf("seqputs_rig A: %%n wrote %d (2 == LIVE write conv)\n", written); /* --- Rig B: seq_puts(m, dynamic_data) โ the shim contract --- */ seq_puts(&m, data); /* == ksnprintf(buf,size,data) */ bcopy(m.buf, snap, sizeof(snap) - 1); snap[sizeof(snap) - 1] = '\0'; kprintf("seqputs_rig B: seq_puts(m,data) produced: '%s'\n", snap); kprintf("seqputs_rig B: Linux contract would print the literal " "data string verbatim (no interpretation)\n"); } static int seqputs_rig_load(struct module *m __unused, int what, void *arg __unused) { switch (what) { case MOD_LOAD: kprintf("seqputs_rig: loaded\n"); rig_run(); return (0); default: return (0); } } static moduledata_t seqputs_rig_mod = { "seqputs_rig", seqputs_rig_load, NULL }; DECLARE_MODULE(seqputs_rig, seqputs_rig_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_VERSION(seqputs_rig, 1); |