DF-1215 / bktrig.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | /* * bktrig.c -- DF-1215 verification rig (DragonFly KLD module) * * The audit QEMU guest has no Brooktree bt848/878 PCI capture card, so the * production bktr driver never attaches and /dev/bktr0 is never created. * This rig makes the PRODUCTION ioctl handler reachable anyway: * * - /dev/bktrig0 (mode 0666) with its own tiny dev_ops * - d_ioctl dispatches DIRECTLY to the production video_ioctl() * (sys/dev/video/bktr/bktr_core.c:1202) resolved from the loaded * production bktr.ko module (unmodified code, unfixed on the baseline * kernel, fixed after the fix-build) * - the softc passed to video_ioctl is a synthetic, zeroed struct * bktr_softc with bigbuf != 0, mirroring the post-attach state on real * hardware (attach allocates bigbuf before any open can occur, so the * bigbuf gate in bktr_ioctl (bktr_os.c) passes on real hardware too) * * Only METEORSVIDEO / METEORGVIDEO are exercised by the PoC: both cases * touch softc fields only (no MMIO), so no real bt848 registers are needed * to demonstrate the missing privilege check on the production path. * * On real hardware the same production path is reached by ANY user because * the bktr device nodes are created mode 0444 (bktr_os.c:325). */ #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/device.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/event.h> #include <sys/signalvar.h> #include <sys/bus.h> #include <sys/rman.h> #include <sys/thread.h> #include <dev/video/meteor/ioctl_meteor.h> #include <dev/video/bktr/ioctl_bt848.h> #include <dev/video/bktr/bktr_reg.h> /* production entry point: bktr_core.c:1202 (global, resolved from bktr.ko * or the fix-built kernel) */ extern int video_ioctl(bktr_ptr_t bktr, int unit, ioctl_cmd_t cmd, caddr_t arg, struct thread *td); static cdev_t bktrig_dev; static bktr_ptr_t rig_sc; static int bktrig_open(struct dev_open_args *ap) { return 0; } static int bktrig_close(struct dev_close_args *ap) { return 0; } static int bktrig_ioctl(struct dev_ioctl_args *ap) { /* dispatch to the PRODUCTION handler on the synthetic softc */ return video_ioctl(rig_sc, 0, ap->a_cmd, ap->a_data, curthread); } static struct dev_ops bktrig_ops = { { "bktrig", 0, 0 }, .d_open = bktrig_open, .d_close = bktrig_close, .d_ioctl = bktrig_ioctl, }; static int bktrig_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: rig_sc = kmalloc(sizeof(struct bktr_softc), M_DEVBUF, M_WAITOK | M_ZERO); if (rig_sc == NULL) return (ENOMEM); /* post-attach state on real hardware: bigbuf allocated */ rig_sc->bigbuf = (vm_offset_t)0xDEADB000; rig_sc->flags = METEOR_INITALIZED; bktrig_dev = make_dev(&bktrig_ops, 0, UID_ROOT, GID_WHEEL, 0666, "bktrig0"); kprintf("bktrig: DF-1215 rig ready /dev/bktrig0 sc=%p " "(video_ioctl=%p)\n", rig_sc, video_ioctl); return 0; case MOD_UNLOAD: destroy_dev(bktrig_dev); kfree(rig_sc, M_DEVBUF); rig_sc = NULL; return 0; default: return 0; } } static moduledata_t bktrig_mod = { "bktrig", bktrig_modevent, NULL }; /* pull in the production (unmodified) bktr.ko for video_ioctl. * NB: on the FIX-built kernel (bktr compiled in) use the BKTRIG_NODEP * variant so the auto-load of bktr.ko ("module already exists") does not * fail -- video_ioctl then resolves from the kernel's own globals. */ #ifndef BKTRIG_NODEP MODULE_DEPEND(bktrig, bktr, 1, 1, 1); #endif DECLARE_MODULE(bktrig, bktrig_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); |