DF-4129 / fakempu.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 118 119 120 121 122 123 124 | /* * DF-4129 harness โ fakempu.ko * * Registers 32 fake MPU-401-style UART MIDI units through the exported * midi_init() API (sys/dev/sound/midi/midi.c:274) so that a sequencer * open enumerates midi_number == 32 (the maximum that does NOT trigger * the known DF-1394 midis[32] heap overflow). Each unit appears as * /dev/midi<unit>.<channel> (0666). * * This simulates the "machine with many MIDI ports" configuration * (e.g. a pro-audio box with multiple mpu401 UARTs) โ the only * precondition seq_sync()'s sync[16] overflow needs besides an open * /dev/sequencer. Loading a kld requires root; USING /dev/sequencer * does not โ the vulnerability trigger itself runs unprivileged. * * Build: see build.sh (compiled inside the kernel module obj tree so the * generated mpu_if.h / kobj headers resolve). */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/kobj.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/malloc.h> #include <dev/sound/midi/midi.h> #include "mpu_if.h" #define FAKE_UNITS 32 /* 32 => sync[16..31] OOB, midis[] in-bounds */ struct snd_midi *fake_units[FAKE_UNITS]; static int fakempu_inqsize(struct snd_midi *kobj, void *cookie) { return (1024); } static int fakempu_outqsize(struct snd_midi *kobj, void *cookie) { return (1024); } static int fakempu_init(struct snd_midi *kobj, void *cookie) { return (0); } static int fakempu_uninit(struct snd_midi *kobj, void *cookie) { return (0); } static void fakempu_callback(struct snd_midi *kobj, void *cookie, int flags) { } static void fakempu_callbackp(struct snd_midi *kobj, void *cookie, int flags) { } static const char * fakempu_descr(struct snd_midi *kobj, void *cookie, int unit) { return ("fake mpu401 UART for DF-4129"); } static const char * fakempu_provider(struct snd_midi *kobj) { return ("fakempu"); } static kobj_method_t fakempu_methods[] = { KOBJMETHOD(mpu_inqsize, fakempu_inqsize), KOBJMETHOD(mpu_outqsize, fakempu_outqsize), KOBJMETHOD(mpu_init, fakempu_init), KOBJMETHOD(mpu_uninit, fakempu_uninit), KOBJMETHOD(mpu_callback, fakempu_callback), KOBJMETHOD(mpu_callbackp, fakempu_callbackp), KOBJMETHOD(mpu_descr, fakempu_descr), KOBJMETHOD(mpu_provider, fakempu_provider), KOBJMETHOD_END }; DEFINE_CLASS(fakempu, fakempu_methods, 0); static int fakempu_modevent(module_t mod, int type, void *data) { int i, ok = 0; switch (type) { case MOD_LOAD: for (i = 0; i < FAKE_UNITS; i++) { fake_units[i] = midi_init(&fakempu_class, 0, i + 1, NULL); if (fake_units[i] != NULL) ok++; } kprintf("fakempu: %d/%d fake MIDI units registered\n", ok, FAKE_UNITS); break; case MOD_UNLOAD: for (i = 0; i < FAKE_UNITS; i++) { if (fake_units[i] != NULL) { midi_uninit(fake_units[i]); fake_units[i] = NULL; } } break; default: break; } return (0); } DEV_MODULE(fakempu, fakempu_modevent, NULL); |