/*
 * DF-5779 fix-validation rig — compiles the FIXED seq_puts() (fix.diff:
 * data string passed through "%s", never the ksnprintf format slot) and
 * re-runs the exact inputs that (a) leaked a vararg slot (rig B: "%d") and
 * (b) PANICKED the kernel (rig C: 9x "%s" walking unset varargs).
 *
 * Expected with fix: both strings print VERBATIM; %n inside data prints
 * literally; guest stays up.
 */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>

struct seq_file {
	char   *buf;
	size_t  size;
};

/* ---- fixed shim (fix.diff) ---- */
static inline void
seq_puts_fixed(struct seq_file *m, const char *str)
{
	ksnprintf(m->buf, m->size, "%s", str);
}

static void
rig_run(void)
{
	struct seq_file m;
	char backing[1024];
	const char *d1 = "conn=DP-1 link=%d ok=100%%\n";
	const char *d2 = "m=%s s=%s x=%s y=%s z=%s w=%s v=%s u=%s t=%s\n";
	const char *d3 = "w=%d write=%n addr=%p\n";

	m.buf = backing;
	m.size = sizeof(backing);

	seq_puts_fixed(&m, d1);
	kprintf("rigfix B: '%s'\n", backing);

	seq_puts_fixed(&m, d2);
	kprintf("rigfix C: '%s'\n", backing);

	seq_puts_fixed(&m, d3);
	kprintf("rigfix N: '%s'\n", backing);

	kprintf("rigfix: DONE verbatim, guest alive\n");
}

static int
rigfix_load(struct module *m __unused, int what, void *arg __unused)
{
	switch (what) {
	case MOD_LOAD:
		rig_run();
		return (0);
	default:
		return (0);
	}
}

static moduledata_t rigfix_mod = { "seqputs_rigfix", rigfix_load, NULL };
DECLARE_MODULE(seqputs_rigfix, rigfix_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
MODULE_VERSION(seqputs_rigfix, 1);
