DF-2574 / ngdpoc_shim_prepend.h
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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | /* * NGDPOC shim prologue -- DF-2573 / DF-2574 verification scaffolding. * * sys/netgraph/ng_device.c is bit-rotted dead code: it is absent from * sys/conf/files and from the module SUBDIR list, and it programs against * the 2003-era DragonFly device API (`struct cdevsw`, make_dev(cdevsw*), * d_*_t(cdev_t,...) signatures, cdevsw_add) that no longer exists in the * tree (the live API is `struct dev_ops` + args-struct trampolines). * * To verify the code UNDER TEST byte-verbatim, this prologue is PREPENDED * to an unmodified copy of ng_device.c (see gen_ngdpoc.sh) and provides * ONLY the missing infrastructure: * - the old `struct cdevsw` definition matching the file's positional * initializer, * - an interposed make_dev() that (a) forwards to the REAL * make_dev()/devfs with a modern dev_ops trampoline so a REAL * /dev/ngd%d appears, and (b) can be armed to fail exactly the Nth * call (DF-2573 fault injection, scoped to this file only), * - no-op macros for symbols that no longer exist (cdevsw_add, * cdevsw_remove, nommap, nostrategy, nodump, nopsize), * - typedef renames so the file's old-style d_*_t declarations compile * against modern headers WITHOUT touching the file body. * * Nothing in ng_device.c lines 1..633 (the verbatim region) is modified. * The fault-injection knobs themselves live in kern/df_ngdpoc.c. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/conf.h> /* real make_dev(struct dev_ops*,...), destroy_dev(cdev_t) */ #include <sys/device.h> /* modern dev_ops + d_*_t + dev_*_args */ #include <sys/malloc.h> #include <sys/types.h> #include <machine/stdint.h> /* fault-injection knobs -- defined in kern/df_ngdpoc.c */ extern int ngdpoc_fail_makedev_nth; /* DF-2573: fail next N shim make_dev() calls */ extern int ngdpoc_kmalloc_fail_armed; /* DF-2573: one-shot kmalloc failure (see kern_slaballoc.c patch) */ extern unsigned long ngdpoc_kmalloc_fail_size; struct thread; /* ---- old-style (2003-era) cdevsw API, exactly what ng_device.c expects ---- */ typedef int ngdpoc_d_open_t(cdev_t dev, int oflags, int devtype, struct thread *td); typedef int ngdpoc_d_close_t(cdev_t dev, int fflag, int devtype, struct thread *td); typedef int ngdpoc_d_read_t(cdev_t dev, struct uio *uio, int ioflag); typedef int ngdpoc_d_write_t(cdev_t dev, struct uio *uio, int ioflag); typedef int ngdpoc_d_ioctl_t(cdev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td); typedef int ngdpoc_d_poll_t(cdev_t dev, int events, struct thread *td); typedef int ngdpoc_d_mmap_t(cdev_t dev, vm_offset_t offset, int nprot); typedef void ngdpoc_d_strategy_t(cdev_t dev, struct bio *bio); typedef int ngdpoc_d_dump_t(cdev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length); typedef int ngdpoc_d_psize_t(cdev_t dev); struct cdevsw { const char *name; int maj; int flags; void *port; void *clone; ngdpoc_d_open_t *open; ngdpoc_d_close_t *close; ngdpoc_d_read_t *read; ngdpoc_d_write_t *write; ngdpoc_d_ioctl_t *ioctl; ngdpoc_d_poll_t *poll; ngdpoc_d_mmap_t *mmap; ngdpoc_d_strategy_t *strategy; ngdpoc_d_dump_t *dump; ngdpoc_d_psize_t *psize; }; /* stubs replacing the kern_device.c statics referenced by the verbatim * initializer (they are only stored, the trampoline dev_ops below never * routes mmap/strategy/dump/psize to them) */ static int ngdpoc_nommap(cdev_t dev, vm_offset_t off, int nprot) { return (-1); } static void ngdpoc_nostrategy(cdev_t dev, struct bio *bio) { } static int ngdpoc_nodump(cdev_t dev, void *v, vm_offset_t p, off_t o, size_t l) { return (ENXIO); } static int ngdpoc_nopsize(cdev_t dev) { return (0); } /* * Trampoline dev_ops: translates the modern args-struct device API onto the * verbatim file's old-signature driver methods (ngdopen/ngdclose/ngdread/ * ngdwrite/ngdioctl). All units share the same static cdevsw. */ static struct cdevsw *ngdpoc_csw; static int ngdpoc_t_open(struct dev_open_args *ap) { return (ngdpoc_csw->open(ap->a_head.a_dev, ap->a_oflags, ap->a_devtype, NULL)); } static int ngdpoc_t_close(struct dev_close_args *ap) { return (ngdpoc_csw->close(ap->a_head.a_dev, ap->a_fflag, ap->a_devtype, NULL)); } static int ngdpoc_t_read(struct dev_read_args *ap) { return (ngdpoc_csw->read(ap->a_head.a_dev, ap->a_uio, ap->a_ioflag)); } static int ngdpoc_t_write(struct dev_write_args *ap) { return (ngdpoc_csw->write(ap->a_head.a_dev, ap->a_uio, ap->a_ioflag)); } static int ngdpoc_t_ioctl(struct dev_ioctl_args *ap) { return (ngdpoc_csw->ioctl(ap->a_head.a_dev, ap->a_cmd, ap->a_data, ap->a_fflag, NULL)); } static struct dev_ops ngdpoc_real_ops = { { "ngd", 197, 0, NULL, 0, 0 }, /* head; maj 197 unused on this guest */ .d_open = ngdpoc_t_open, .d_close = ngdpoc_t_close, .d_read = ngdpoc_t_read, .d_write = ngdpoc_t_write, .d_ioctl = ngdpoc_t_ioctl, }; /* * Interposed make_dev(): this is the ONLY symbol the verbatim file calls * that must be renamed, because the real make_dev() takes a dev_ops*. * * DF-2573 fault injection: when armed (kern.ngdpoc.fail_makedev_nth > 0), * the Nth call FROM THIS FILE returns NULL -- precisely the * ng_device_newhook() error path at ng_device.c:288. Zero global impact: * every other make_dev() caller in the kernel is untouched. */ cdev_t ngdpoc_make_dev(struct cdevsw *csw, int minor, uid_t uid, gid_t gid, int perms, const char *fmt, ...); /* accessors implemented in the epilogue */ size_t ngdpoc_conn_size(void); int ngdpoc_list_count(void); void ngdpoc_list_dump(char *buf, size_t len); cdev_t ngdpoc_make_dev(struct cdevsw *csw, int minor, uid_t uid, gid_t gid, int perms, const char *fmt, ...) { char name[64]; __va_list ap; if (ngdpoc_fail_makedev_nth > 0 && --ngdpoc_fail_makedev_nth == 0) { kprintf("NGDPOC: injected make_dev() failure\n"); return (NULL); } ngdpoc_csw = csw; compile_dev_ops(&ngdpoc_real_ops); __va_start(ap, fmt); kvsnprintf(name, sizeof(name), fmt, ap); __va_end(ap); return (make_dev(&ngdpoc_real_ops, minor, uid, gid, perms, "%s", name)); } /* * From here on, the verbatim ng_device.c text is compiled against the shim: * make_dev -> ngdpoc_make_dev, the old d_*_t typedefs, and no-op macros for * symbols that no longer exist anywhere in the tree. */ #define make_dev ngdpoc_make_dev #define d_open_t ngdpoc_d_open_t #define d_close_t ngdpoc_d_close_t #define d_read_t ngdpoc_d_read_t #define d_write_t ngdpoc_d_write_t #define d_ioctl_t ngdpoc_d_ioctl_t #define d_poll_t ngdpoc_d_poll_t #define nommap ngdpoc_nommap #define nostrategy ngdpoc_nostrategy #define nodump ngdpoc_nodump #define nopsize ngdpoc_nopsize #define cdevsw_add(a, b, c) do { } while (0) #define cdevsw_remove(a, b, c) do { } while (0) /* ng_device.c:103 redefines MIN(a,b) with a different macro body than * sys/param.h -- drop the param.h one so the verbatim definition stands */ #undef MIN |