DF-4582 / rs690_div0_kmod.c
/* * DF-4582 / DF-4583 kernel-context reproduction (runtime-input variant). * * The verbatim rs690_crtc_bandwidth_compute() (rs690_div0_body.h) runs in * the live guest kernel when the admin writes a scenario number to: * * sysctl df4582.run=<0|1|2> * * The scenario (and thus mode->clock / sideport mclk / pm.sclk) is a pure * runtime value here — exactly like the real driver, where mode->clock * arrives from the DRM ioctl — so the compiler cannot constant-fold the * arithmetic (the shipped radeon.ko likewise computes a runtime div: * see objdump 0x5ac39-0x5ac61 in VERDICT.md). * * vulnerable build: sysctl df4582.run=0 -> Fatal trap 0 (divide error) panic * fixed build: sysctl df4582.run=0|1|2 -> "zero divisor avoided", survives */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/types.h> #define KERNEL 1 /* scenario chosen at COMPILE time for the default; overridden at RUNTIME */ #ifndef DF4582_SCENARIO #define DF4582_SCENARIO 0 #endif #include "rs690_div0_body.h" static int df4582_run(int s) { struct df4582_rdev rdev; struct df4582_crtc crtc; struct rs690_watermark wm; kprintf("DF4582-KMOD: scenario %d: entering verbatim " "rs690_crtc_bandwidth_compute()\n", s); df4582_setup(&rdev, &crtc, s); kprintf("DF4582-KMOD: scenario %d: mode.clock=%d kHz sideport=%d " "pm.sclk=%u igp_sideport_mclk=%u\n", s, crtc.base.mode.clock, rdev.mc.igp_sideport_enabled, rdev.pm.sclk.full >> 12, rdev.pm.igp_sideport_mclk.full >> 12); rs690_crtc_bandwidth_compute(&rdev, &crtc, &wm, 0); kprintf("DF4582-KMOD: scenario %d: SURVIVED fifo=%u (fixed build?)\n", s, wm.lb_request_fifo_depth); return (0); } static int df4582_sysctl_run(SYSCTL_HANDLER_ARGS) { int s = 0, error; error = sysctl_handle_int(oidp, &s, 0, req); if (error != 0 || req->newptr == NULL) return (error); if (s < 0 || s > 2) { kprintf("DF4582-KMOD: scenario must be 0, 1 or 2\n"); return (EINVAL); } return (df4582_run(s)); } SYSCTL_NODE(, OID_AUTO, df4582, CTLFLAG_RW, 0, "DF-4582/4583 rs690 div0 repro"); SYSCTL_PROC(_df4582, OID_AUTO, run, CTLTYPE_INT | CTLFLAG_RW, 0, 0, df4582_sysctl_run, "I", "scenario 0=clock-wrap 1=sideport-mclk0 2=pm.sclk0"); static int df4582_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: kprintf("DF4582-KMOD: loaded; write sysctl df4582.run=<0|1|2>\n"); return (0); case MOD_UNLOAD: kprintf("DF4582-KMOD: unloaded\n"); return (0); } return (0); } static moduledata_t df4582_mod = { "df4582_div0", df4582_modevent, NULL }; DECLARE_MODULE(df4582_div0, df4582_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_VERSION(df4582_div0, 1); |