DF-5678 / df5678_mod.c
/* * DF-5678 — kernel trigger module (loaded as root on the audit guest). * * Exercises the exact code path in the running stock kernel * (X86_64_GENERIC, "options INVARIANTS" -> _PROP_ASSERT == KKASSERT * active): * * df5678_set.ko : prop_array_set(pa, idx > count) -> expect * panic: assertion "idx < pa->pa_count" failed * in prop_array_set at prop_array.c:648 * df5678_rem.ko : prop_array_remove(pa, idx >= count) -> expect * panic ... in prop_array_remove at prop_array.c:701 * * On a kernel built WITHOUT INVARIANTS the same calls are silent: the * assert is compiled to nothing and :650/:654/:709/:719 execute OOB (see * the userland -DNDEBUG differential for that half). * * On a kernel with the fix (real bounds checks) both modules load cleanly * and print their observations — that is the fix validation. * * Build: make -DMODE_SET -> df5678_set.ko * make -DMODE_REM -> df5678_rem.ko */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <libprop/proplib.h> #if !defined(MODE_SET) && !defined(MODE_REM) #define MODE_SET 1 /* default */ #endif static int df5678_modevent(module_t mod __unused, int type, void *arg __unused) { prop_array_t pa; prop_object_t po; #if defined(MODE_SET) int rv; #endif switch (type) { case MOD_LOAD: pa = prop_array_create_with_capacity(2); po = prop_string_create_cstring("x"); if (pa == NULL || po == NULL) return (ENOMEM); /* count == capacity == 2: backing store is exactly 16 bytes */ if (prop_array_add(pa, po) == false || prop_array_add(pa, po) == false) { kprintf("DF5678: setup add failed\n"); return (ENOMEM); } kprintf("DF5678: array ready count=%u cap=%u\n", prop_array_count(pa), prop_array_capacity(pa)); #if defined(MODE_SET) kprintf("DF5678: calling prop_array_set(pa, 5, po)\n"); rv = prop_array_set(pa, 5, po); /* INVARIANTS kernel: never returns (panic at prop_array.c:648). * Fixed kernel: returns 0 (false). */ kprintf("DF5678: set(5) returned %d, count=%u\n", rv, prop_array_count(pa)); #else /* MODE_REM */ kprintf("DF5678: calling prop_array_remove(pa, 7)\n"); prop_array_remove(pa, 7); /* INVARIANTS kernel: panic at prop_array.c:701. * Fixed kernel: no-op, count unchanged. */ kprintf("DF5678: remove(7) returned, count=%u\n", prop_array_count(pa)); #endif prop_object_release(po); prop_object_release(pa); kprintf("DF5678: module completed without panic\n"); return (0); default: return (EOPNOTSUPP); } } static moduledata_t df5678_mod = { #if defined(MODE_SET) "df5678", #else "df5678rem", #endif df5678_modevent, NULL }; DECLARE_MODULE(df5678, df5678_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); |